CryptoJS AES-CBC无填充加解密结果不匹配问题求助
问题排查与解决
核心问题1:明文长度不符合AES-CBC NoPadding要求
AES-CBC模式搭配NoPadding时,明文长度必须严格等于AES块大小(16字节)的整数倍。你的输入明文0x7361776169去掉0x后仅为5字节,远小于16字节,这会导致CryptoJS加密时无法完成块对齐,解密后自然得不到原始数据。
核心问题2:Hex字符串带0x前缀导致解析错误
enc.Hex.parse()无法识别0x前缀,直接解析会因x不是合法十六进制字符,导致生成错误的字节数组,进一步加剧数据不匹配问题。
解决方案
方案1:改用标准PKCS7填充(推荐)
若无特殊要求,优先使用CryptoJS默认的pad.Pkcs7填充,它会自动处理明文块对齐,解密时也会自动去除填充:
export const encryptDataUsingKey = ( text: string, // Hex with 0x prefix key: string, // base64 (scrypt generated key) iv: string, // base64 (random 16 byte iv) ): string => { // 去掉0x前缀,解析Hex字符串 const plaintextBytes = enc.Hex.parse(text.slice(2)); const keyBytes = enc.Base64.parse(key); const ivBytes = enc.Base64.parse(iv); const encryptedCipher = AES.encrypt( plaintextBytes, keyBytes, { iv: ivBytes, padding: pad.Pkcs7, // 使用PKCS7填充 mode: mode.CBC, }, ); // 解密验证 const decryptedBytes = AES.decrypt( encryptedCipher, keyBytes, { iv: ivBytes, padding: pad.Pkcs7, mode: mode.CBC, }, ); console.log({ decryptedText: `0x${enc.Hex.stringify(decryptedBytes)}` }); return enc.Base64.stringify(encryptedCipher.ciphertext); };
方案2:坚持使用NoPadding,手动处理明文长度
若必须使用NoPadding,需手动将明文填充到16字节的整数倍(示例用零填充),解密后再去除填充:
export const encryptDataUsingKey = ( text: string, // Hex with 0x prefix key: string, // base64 (scrypt generated key) iv: string, // base64 (random 16 byte iv) ): string => { // 去掉0x前缀,解析Hex字符串 let plaintextBytes = enc.Hex.parse(text.slice(2)); const keyBytes = enc.Base64.parse(key); const ivBytes = enc.Base64.parse(iv); const blockSize = 16; // 手动零填充到块大小的整数倍 const paddingLength = blockSize - (plaintextBytes.sigBytes % blockSize); if (paddingLength !== blockSize) { const padding = new WordArray(paddingLength); plaintextBytes = plaintextBytes.concat(padding); } const encryptedCipher = AES.encrypt( plaintextBytes, keyBytes, { iv: ivBytes, padding: pad.NoPadding, mode: mode.CBC, }, ); // 解密后去掉零填充 const decryptedBytes = AES.decrypt( encryptedCipher, keyBytes, { iv: ivBytes, padding: pad.NoPadding, mode: mode.CBC, }, ); // 去掉末尾的零填充 const trimmedBytes = decryptedBytes.toString(enc.Hex).replace(/0+$/, ''); console.log({ decryptedText: `0x${trimmedBytes}` }); return enc.Base64.stringify(encryptedCipher.ciphertext); };
验证说明
运行修改后的代码后,解密输出的decryptedText应与原始输入的text完全一致。
内容的提问来源于stack exchange,提问作者Sayras Jain
相关产品推荐
相关产品推荐

