如何修改C# AES-256-CBC加密代码使其与Node.js输出一致
C#实现与Node.js等效的AES-256-CBC加密
基准逻辑说明
业务侧Node.js加密逻辑为既定规则不可修改,对明文124_12344612加密后的正确密文结果为DhX6hhOUpeYZJexlMD+6zg==,对应Node.js实现代码:
const crypto = require('crypto'); var plainText = '124_12344612'; var keys ="gjOMA9mMihhOANN4erqksLIaHzDZWP0shFayUU39C0A="; //password/ var hash = Buffer.from(keys, 'base64'); var iv = Buffer.from([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]); var cipher = crypto.createCipheriv('aes-256-cbc',hash,Buffer.from(iv, 'utf8')); var ciph = cipher.update(plainText,'utf8','base64'); ciph +=cipher.final('base64') console.log("ciph" ,ciph)
初始代码问题
最初编写的C#版本加密同一段明文输出结果为nXU8XunpCy6OhiM251qcqg==,与预期结果不符,初始错误代码如下:
private const int AesKeySize = 16; static void Main(string[] args) { string password = "gjOMA9mMihhOANN4erqksLIaHzDZWP0shFayUU39C0A="; string message = "124_12344612"; // 错误:对密钥做了SHA256哈希,不符合Node.js逻辑 SHA256 mySHA256 = SHA256Managed.Create(); byte[] key = mySHA256.ComputeHash(Encoding.ASCII.GetBytes(password)); byte[] iv = new byte[16] { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }; string encrypted = EncryptString(message, key, iv); string decrypted = DecryptString(encrypted, key, iv); Console.ReadLine(); } public static string EncryptString(string plainText, byte[] key, byte[] iv) { Aes encryptor = Aes.Create(); encryptor.Mode = CipherMode.CBC; byte[] aesKey = new byte[32]; Array.Copy(key, 0, aesKey, 0, 32); encryptor.Key = aesKey; encryptor.IV = iv; MemoryStream memoryStream = new MemoryStream(); ICryptoTransform aesEncryptor = encryptor.CreateEncryptor(); CryptoStream cryptoStream = new CryptoStream(memoryStream, aesEncryptor, CryptoStreamMode.Write); // 错误:使用ASCII编码处理明文,与Node.js的UTF8编码不匹配 byte[] plainBytes = Encoding.ASCII.GetBytes(plainText); cryptoStream.Write(plainBytes, 0, plainBytes.Length); cryptoStream.FlushFinalBlock(); byte[] cipherBytes = memoryStream.ToArray(); memoryStream.Close(); cryptoStream.Close(); string cipherText = Convert.ToBase64String(cipherBytes, 0, cipherBytes.Length); return cipherText; }
修正点说明
共3处核心错误需要修正:
- 密钥处理逻辑错误:原代码对密钥字符串做SHA256哈希,实际Node.js逻辑是直接对Base64格式的密钥字符串做解码,得到32字节长度的AES-256密钥
- 明文编码错误:原代码使用ASCII编码转换明文字节,Node.js侧使用UTF8编码处理明文,需统一为UTF8编码
- 填充模式未匹配:Node.js的
aes-256-cbc算法默认使用PKCS7填充,需显式设置C# AES对象的填充模式为PaddingMode.PKCS7
修正后正确代码
修正后代码加密输出与Node.js结果完全一致:
static void Main(string[] args) { string password = "gjOMA9mMihhOANN4erqksLIaHzDZWP0shFayUU39C0A="; string message = "124_12344612"; // 直接对Base64格式密钥做解码 byte[] key = Convert.FromBase64String(password); byte[] iv = new byte[16] { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }; string encrypted = EncryptString(message, key, iv); string decrypted = DecryptString(encrypted, key, iv); Console.ReadLine(); } public static string EncryptString(string plainText, byte[] key, byte[] iv) { Aes encryptor = Aes.Create(); encryptor.Mode = CipherMode.CBC; byte[] aesKey = new byte[32]; Array.Copy(key, 0, aesKey, 0, 32); encryptor.Key = aesKey; encryptor.IV = iv; // 显式设置填充模式为PKCS7,与Node.js默认逻辑对齐 encryptor.Padding = PaddingMode.PKCS7; MemoryStream memoryStream = new MemoryStream(); ICryptoTransform aesEncryptor = encryptor.CreateEncryptor(); CryptoStream cryptoStream = new CryptoStream(memoryStream, aesEncryptor, CryptoStreamMode.Write); // 使用UTF8编码处理明文 byte[] plainBytes = Encoding.UTF8.GetBytes(plainText); cryptoStream.Write(plainBytes, 0, plainBytes.Length); cryptoStream.FlushFinalBlock(); byte[] cipherBytes = memoryStream.ToArray(); memoryStream.Close(); cryptoStream.Close(); string cipherText = Convert.ToBase64String(cipherBytes, 0, cipherBytes.Length); return cipherText; }
内容的提问来源于stack exchange,提问作者Billy Watsy
相关产品推荐
相关产品推荐

