将Java AES加密代码转换为C# .NET并保证加密结果一致
问题分析与修正方案
要让Java和C#的AES加密输出完全一致,你的C#代码有两个核心问题需要调整:
关键差异点
- Base64编码格式不匹配:Java使用的是URL安全的Base64(
Base64.getUrlEncoder()),会将+替换为-、/替换为_,并自动去除末尾的填充符=;而C#默认的Convert.ToBase64String是标准Base64,输出格式和Java不一致。 - 字符串转字节数组的编码一致性:Java中
String.getBytes()默认依赖平台编码,而C#明确使用了UTF-8,需要统一为UTF-8避免跨平台编码差异。
修正后的C#代码
public static string AesEncryption(string plainText, string key, string iv) { byte[] encrypted; using (Aes aesAlg = Aes.Create()) { aesAlg.Key = Encoding.UTF8.GetBytes(key); aesAlg.IV = Encoding.UTF8.GetBytes(iv); aesAlg.BlockSize = 128; aesAlg.Padding = PaddingMode.PKCS7; // 和Java的PKCS5Padding等价(AES块大小为128位) aesAlg.Mode = CipherMode.CBC; var encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV); using (var msEncrypt = new MemoryStream()) { using (var csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write)) { // 直接写入UTF8编码的明文字节数组,避免StreamWriter的默认编码潜在问题 byte[] plainBytes = Encoding.UTF8.GetBytes(plainText); csEncrypt.Write(plainBytes, 0, plainBytes.Length); csEncrypt.FlushFinalBlock(); } encrypted = msEncrypt.ToArray(); // 转换为URL安全的Base64格式 return Convert.ToBase64String(encrypted) .Replace('+', '-') .Replace('/', '_') .TrimEnd('='); } } }
Java代码的优化建议(可选)
为彻底消除编码差异,建议Java代码中明确指定UTF-8编码,避免依赖平台默认编码:
import java.nio.charset.StandardCharsets; import javax.crypto.Cipher; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; import java.util.Base64; public static String encryptAES(String plain, String secretKey, String iv) throws Exception { return encrypt(plain, secretKey, iv, "AES/CBC/PKCS5PADDING", "AES"); } private static String encrypt(String plain, String secretKey, String iv, String algorithm, String secretKeyAlgorithm) throws Exception { var cipher = Cipher.getInstance(algorithm); // 明确使用UTF-8编码转换字符串为字节数组 var secret = new SecretKeySpec(secretKey.getBytes(StandardCharsets.UTF_8), secretKeyAlgorithm); var ivParameterSpec = new IvParameterSpec(iv.getBytes(StandardCharsets.UTF_8)); cipher.init(Cipher.ENCRYPT_MODE, secret, ivParameterSpec); var cipherText = cipher.doFinal(plain.getBytes(StandardCharsets.UTF_8)); return Base64.getUrlEncoder().encodeToString(cipherText); }
验证注意事项
- 确保密钥和IV的长度符合AES规范:比如AES-128需要16字节密钥,AES-256需要32字节密钥,IV固定为16字节(AES块大小)。
- 两边使用完全相同的密钥、IV和明文进行测试。
内容的提问来源于stack exchange,提问作者MiladRajabi
相关产品推荐
相关产品推荐

