首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計疑難解答

Java AES 加密移植至 C# 的完整對照實作

     編輯:程式設計疑難解答

原始 Java 程式碼分析

提供的 Java 代碼使用 KeyGenerator 搭配 SecureRandom(SHA1PRNG) 從密鑰字串衍生 AES 密鑰,採用 Cipher.getInstance("AES") 預設為 ECB 模式、PKCS5Padding,輸出為大寫十六進位字串。

關鍵參數

  • 演算法:AES-128
  • 模式:ECB(預設)
  • 填充:PKCS5Padding(等同 PKCS7)
  • 密鑰衍生:SecureRandom.setSeed(key.getBytes()) → KeyGenerator.init(128, random)
  • 輸出格式:大寫 Hex,無分隔符

C# 完整對應實作

using System;
using System.Security.Cryptography;
using System.Text;

public static class AesEcbUtil
{
    /// 
    /// 兼容 Java 端:SHA1PRNG 衍生金鑰 + AES/ECB/PKCS7 + 大寫 Hex 輸出
    /// 
    public static string Encrypt(string plainText, string key)
    {
        // 1. 衍生 16 bytes 金鑰(模擬 Java SHA1PRNG 行為)
        byte[] keyBytes = DeriveKey(key, 16);

        // 2. AES/ECB/PKCS7 加密
        using (Aes aes = Aes.Create())
        {
            aes.Mode = CipherMode.ECB;
            aes.Padding = PaddingMode.PKCS7;
            aes.Key = keyBytes;

            using (ICryptoTransform encryptor = aes.CreateEncryptor())
            {
                byte[] input = Encoding.UTF8.GetBytes(plainText);
                byte[] cipher = encryptor.TransformFinalBlock(input, 0, input.Length);

                // 3. 轉大寫 Hex
                return ByteArrayToHexString(cipher);
            }
        }
    }

    private static byte[] DeriveKey(string key, int keySize)
    {
        // Java: SecureRandom.getInstance("SHA1PRNG").setSeed(key.getBytes())
        // .NET 對應:使用 SHA1 將種子雜湊,取前 keySize bytes
        using (SHA1 sha1 = SHA1.Create())
        {
            byte[] seed = Encoding.UTF8.GetBytes(key);
            byte[] hash = sha1.ComputeHash(seed);
            byte[] derived = new byte[keySize];
            Array.Copy(hash, derived, keySize);
            return derived;
        }
    }

    private static string ByteArrayToHexString(byte[] bytes)
    {
        StringBuilder sb = new StringBuilder(bytes.Length * 2);
        foreach (byte b in bytes)
            sb.AppendFormat("{0:X2}", b); // 大寫兩位十六進位
        return sb.toString();
    }
}

驗證清單

  1. 雙方同樣輸入 plainText、key,C# 輸出應與 Java 完全一致。
  2. 若 Java 端改用 Cipher.getInstance("AES/CBC/PKCS5Padding"),C# 需同步設定 Mode = CipherMode.CBC 並傳遞 IV。
  3. Java 8+ 的 SHA1PRNG 實作可能因提供者不同而有細微差異;若發現不一致,建議雙方改用 PBKDF2(Rfc2898DeriveBytes)統一衍生金鑰。

替代方案:Web Service 封裝

若不想處理跨平台加密細節,可將 Java 加密邏輯封裝為 REST API(如 /api/encrypt),C# 僅發送 HTTP 請求獲取密文。優點:零移植風險;缺點:增加網路延遲與單點故障。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved