如何在C#中实现AES加密并兼容CryptoJS解密
问题根因与修复方案
核心不兼容点
- CryptoJS调用
AES.decrypt时如果第二个参数传入普通字符串,会默认使用OpenSSL兼容的EVP_BytesToKey算法从字符串派生密钥和IV,不会直接把字符串当成原始AES密钥使用,和你C#里直接把密钥字符串转UTF8字节当密钥的逻辑完全不匹配 - 你C#逻辑是把随机生成的16位IV拼在密文最前面,CryptoJS解密时需要先拆分出IV和实际密文才能正确解密
修正方案
方式一:修改JS解密逻辑适配现有C#加密逻辑(推荐,不需要改后端C#代码)
把密钥直接转成CryptoJS的WordArray,手动拆分Base64密文里的IV和密文部分:
const cryptojs = require("crypto-js"); // 原始密钥字符串 const keyStr = "gpubphkxqdrkizxgyomipluuyfkvhnci"; // 把密钥转成WordArray,不要直接传字符串给decrypt方法 const key = cryptojs.enc.Utf8.parse(keyStr); // 传入C#返回的Base64密文即可解密 function decrypt(ciphertextBase64) { // 把Base64密文转成WordArray const cipherData = cryptojs.enc.Base64.parse(ciphertextBase64); // AES块大小固定16字节,前16字节是C#生成的IV const iv = cryptojs.lib.WordArray.create(cipherData.words.slice(0, 4)); // 剩余部分是实际密文 const actualCipher = cryptojs.lib.WordArray.create(cipherData.words.slice(4)); // 解密需指定和C#侧一致的模式、填充规则 const decrypted = cryptojs.AES.decrypt( { ciphertext: actualCipher }, key, { iv: iv, mode: cryptojs.mode.CBC, padding: cryptojs.pad.Pkcs7 } ); // 转UTF8明文返回 return decrypted.toString(cryptojs.enc.Utf8); }
额外注意事项
- 你当前使用的密钥字符串长度为32字节,对应AES-256,C#侧不需要手动修改KeySize属性,只要密钥字节长度符合16/24/32的要求,会自动匹配AES-128/192/256规格
- 你注释掉的
aes.BlockSize = 4、aes.KeySize = 128 / 8赋值是错误的,AES块大小固定为128位(16字节),不要打开这两行注释 - C#侧
StreamWriter默认使用UTF8编码写入字符串,和JS侧转UTF8的逻辑匹配,不需要额外修改
内容的提问来源于stack exchange,提问作者Bataa Bataa
相关产品推荐
相关产品推荐

