如何用CryptoJS解密Java AES/CBC模式输出的纯十六进制密文
纯十六进制密文的CryptoJS AES-CBC解密实现
卡这个解密环节基本是两个关键细节没对齐:
- 直接给
CryptoJS.AES.decrypt传入字符串类型参数时,方法默认会将字符串解析为带Salted__前缀的OpenSSL格式base64密文,你手里的纯hex原始密文完全没法被正确识别 - 之前写的CryptoJS逻辑没有和Java端的IV规则匹配:Java端是将原密钥反转后作为IV,之前直接把原密钥当IV用,就算密文格式处理对了,解密结果也是乱码
对齐Java逻辑的完整可运行代码
加密方法(输出和Java端完全一致的hex密文)
encodeByAES_CBC(data, key) { // 和Java逻辑对齐:密钥反转后作为IV const reversedKey = key.split('').reverse().join(''); return CryptoJS.AES.encrypt( data, CryptoJS.enc.Utf8.parse(key), { iv: CryptoJS.enc.Utf8.parse(reversedKey), mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.ZeroPadding } ).ciphertext.toString(); // 返回纯十六进制密文 }
解密方法(支持直接读取服务端返回的纯hex密文)
decodeByAES_CBC(hexCiphertext, key) { // 对齐Java端IV规则 const reversedKey = key.split('').reverse().join(''); // 核心处理:将纯hex密文转换为CryptoJS可识别的原始密文对象 const rawCipher = CryptoJS.enc.Hex.parse(hexCiphertext); const decryptedArray = CryptoJS.AES.decrypt( { ciphertext: rawCipher }, // 构造CipherParams对象传参,绕过默认格式解析 CryptoJS.enc.Utf8.parse(key), { iv: CryptoJS.enc.Utf8.parse(reversedKey), mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.ZeroPadding } ); // 清除ZeroPadding补充的尾部0字节,避免出现乱码后缀 return decryptedArray.toString(CryptoJS.enc.Utf8).replace(/\0+$/, ''); }
效果验证
用你提供的实际测试参数运行:
const testKey = '9999999999999999'; const testHexCipher = '030f7c7d57e82c6fb7d3066363e59c9dd6de7daa486146857552d31403a7cc71'; console.log(decodeByAES_CBC(testHexCipher, testKey)); // 输出结果:whywhywhywhywhywhy
补充:CryptoJS的
AES.decrypt本身支持接收CipherParams格式的对象参数,只要把hex密文parse成WordArray后作为ciphertext属性传入,就能跳过默认的OpenSSL格式解析,正确读取原始的十六进制密文。
内容的提问来源于stack exchange,提问作者Mr.Vexing
相关产品推荐
相关产品推荐

