C# .NET与JavaScript的AES加解密互通实现问题咨询
问题根因
你之前的代码存在三个核心不匹配点,导致加解密失败:
- 工作模式错误:.NET 中
Aes类默认使用 CBC 模式,你代码中配置的ECB模式和供应商逻辑完全不匹配;且ECB模式不需要IV,和供应商代码显式取密钥前16位作为IV的逻辑冲突。 - 密钥解析逻辑错误:CryptoJS 的 AES 接口如果直接传入字符串类型的密钥,会默认将其作为口令,走 OpenSSL 兼容的
EVP_BytesToKey算法派生实际密钥和IV,不会直接将字符串按UTF8编码转为字节作为原始AES密钥,和C#端直接取UTF8字节作为key/IV的逻辑不一致。 - 冗余编码错误:你对密文做了两次无意义的Base64转码操作,破坏了原始密文结构。
可互通实现方案
供应商C#代码的固定AES参数如下,两端严格对齐即可互通:
- 工作模式:CBC
- 填充方式:PKCS7
- 密钥:传入的key字符串按UTF8编码转字节,key长度必须为16/24/32位,分别对应AES-128/AES-192/AES-256,否则C#端会直接抛出参数异常
- IV:取key字符串前16位,按UTF8编码转字节
CryptoJS 版本实现(和你现有技术栈一致)
const CryptoJS = require('crypto-js'); // 对应C#端Encrypt方法 function aesEncrypt(plainText, key) { // 显式按UTF8解析key和IV,避免CryptoJS自动做密钥派生 const keyBytes = CryptoJS.enc.Utf8.parse(key); const ivBytes = CryptoJS.enc.Utf8.parse(key.slice(0, 16)); const encrypted = CryptoJS.AES.encrypt( CryptoJS.enc.Utf8.parse(plainText), keyBytes, { iv: ivBytes, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 } ); // 直接返回Base64格式密文,和C#端输出格式完全一致 return encrypted.toString(); } // 对应C#端Decrypt方法 function aesDecrypt(cipherTextBase64, key) { const keyBytes = CryptoJS.enc.Utf8.parse(key); const ivBytes = CryptoJS.enc.Utf8.parse(key.slice(0, 16)); const decrypted = CryptoJS.AES.decrypt( cipherTextBase64, keyBytes, { iv: ivBytes, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 } ); return decrypted.toString(CryptoJS.enc.Utf8); } // 测试示例 const testKey = "1234567890123456"; // 16位密钥对应AES-128 const testPlain = "跨端AES互通测试 test123!@#"; const cipher = aesEncrypt(testPlain, testKey); console.log("加密后密文:", cipher); const plain = aesDecrypt(cipher, testKey); console.log("解密后明文:", plain); // 输出和原始明文一致即为正常
Node.js 原生crypto模块实现(无第三方依赖)
如果不想引入第三方依赖,可以直接用Node.js内置的crypto模块实现,性能更好:
const crypto = require('crypto'); function aesEncrypt(plainText, key) { const iv = key.slice(0, 16); // 根据密钥长度自动匹配对应算法:16位=aes-128-cbc、24位=aes-192-cbc、32位=aes-256-cbc const algorithm = `aes-${key.length * 8}-cbc`; const cipher = crypto.createCipheriv( algorithm, Buffer.from(key, 'utf8'), Buffer.from(iv, 'utf8') ); let encrypted = cipher.update(plainText, 'utf8', 'base64'); encrypted += cipher.final('base64'); return encrypted; } function aesDecrypt(cipherTextBase64, key) { const iv = key.slice(0, 16); const algorithm = `aes-${key.length * 8}-cbc`; const decipher = crypto.createDecipheriv( algorithm, Buffer.from(key, 'utf8'), Buffer.from(iv, 'utf8') ); let decrypted = decipher.update(cipherTextBase64, 'base64', 'utf8'); decrypted += decipher.final('utf8'); return decrypted; }
注意:如果对接时出现解密乱码,先确认双方使用的key完全一致,且key长度符合AES要求,不要包含多余的空格、换行符。
内容的提问来源于stack exchange,提问作者homam
相关产品推荐
相关产品推荐

