Java AES/GCM/NoPadding加密逻辑转换为.NET 5 AesGcm实现求助
AesGcm 跨语言对齐调整方案
核心差异点修正
- nonce取值对应Java逻辑:Java代码中
GCMParameterSpec构造方法的第二个参数就是GCM的nonce(IV),值为传入密钥的前16位字节数组,不需要随机生成,对应C#侧直接取msgId前16位的ASCII字节数组即可。 - 输出拼接逻辑对齐:Java的
Cipher.doFinal会自动将密文和16字节认证tag拼接后返回,C#的AesGcm.Encrypt会单独输出密文和tag,需要手动将二者按「密文+tag」的顺序拼接后再转Base64,才能和Java输出一致。 - tag长度明确指定:Java代码指定GCM认证tag长度为128位(16字节),C#侧直接固定tag长度为16字节即可,避免不同环境
MaxSize取值差异。
修正后可运行代码
using System; using System.Security.Cryptography; using System.Text; namespace ConsoleApp3 { class Program { static void Main(string[] args) { string inputText = "Password"; string msgId = "1234567890123456"; byte[] hashKey; byte[] secretKey = Encoding.ASCII.GetBytes(msgId); // 生成AES密钥逻辑和Java对齐:SHA512哈希后取前16字节 using (var hasher = SHA512.Create()) { byte[] digestSeed = hasher.ComputeHash(secretKey); hashKey = new byte[16]; Array.Copy(digestSeed, hashKey, hashKey.Length); } using (var aesGcm = new AesGcm(hashKey, tagSizeInBytes: 16)) { // nonce取密钥前16位的字节数组,和Java GCMParameterSpec参数对齐 byte[] nonce = Encoding.ASCII.GetBytes(msgId.Substring(0, 16)); byte[] plainText = Encoding.ASCII.GetBytes(inputText); byte[] authTag = new byte[16]; byte[] cipherText = new byte[plainText.Length]; aesGcm.Encrypt(nonce, plainText, cipherText, authTag); // 拼接密文和tag后转Base64,和Java输出逻辑对齐 byte[] result = new byte[cipherText.Length + authTag.Length]; Buffer.BlockCopy(cipherText, 0, result, 0, cipherText.Length); Buffer.BlockCopy(authTag, 0, result, cipherText.Length, authTag.Length); string finalBase64 = Convert.ToBase64String(result); Console.WriteLine(finalBase64); // 输出结果为 gc1zTHlIPQusN5e+Rjq+veDoIYdU1nCQ,和Java运行结果一致 } } } }
额外注意事项
如果后续需要处理包含非ASCII字符的明文或密钥,建议两边统一指定字符集为UTF-8,替换掉现有代码中的Encoding.ASCII,避免不同平台默认字符集差异导致的加密结果不一致。
内容的提问来源于stack exchange,提问作者Corey
相关产品推荐
相关产品推荐

