使用CryptoJS在JS加密字符串,PHP用openssl_decrypt解密失败
CryptoJS AES加密与PHP openssl解密匹配方案
你遇到的bad decrypt错误源于两端加密参数不匹配,以下是具体问题修正和可运行的代码:
核心问题点
- 密钥长度不匹配:MD5生成128位(16字节)密钥,但PHP端错误使用了
aes-256-cbc,导致openssl自动补全密钥,与CryptoJS的密钥不一致。 - IV格式不匹配:CryptoJS将IV解析为十六进制二进制数据,PHP端直接使用字符串形式的MD5结果,字节编码不一致。
- 密钥解析错误:JS端直接将MD5的十六进制字符串作为密钥,CryptoJS会默认按UTF-8编码转换字节,与实际MD5二进制密钥不符。
修正后的JavaScript代码
const q = 'hello world'; const cryptKey = 'a'; // 将MD5结果解析为十六进制二进制密钥 const secretKey = CryptoJS.enc.Hex.parse(CryptoJS.MD5(cryptKey).toString()); // 生成符合要求的IV:两次MD5后解析为十六进制二进制 const iv = CryptoJS.enc.Hex.parse(CryptoJS.MD5(CryptoJS.MD5(cryptKey).toString()).toString()); // 明确指定CBC模式和PKCS7填充(与openssl默认一致) const encrypted = CryptoJS.AES.encrypt(q, secretKey, { iv: iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 }); // 直接获取Base64编码的加密结果 const encoded = encrypted.toString();
修正后的PHP代码
$cryptKey = 'a'; $encoded = "r+crKP3pmlRoAovRPCK2dQ=="; // JS端加密后的Base64字符串 // 转换密钥为十六进制二进制 $key = hex2bin(md5($cryptKey)); // 转换IV为十六进制二进制 $iv = hex2bin(md5(md5($cryptKey))); // 使用与密钥长度匹配的aes-128-cbc算法 $decrypted = openssl_decrypt(base64_decode($encoded), "aes-128-cbc", $key, OPENSSL_RAW_DATA, $iv); echo $decrypted; // 输出:hello world
关键说明
必须保证两端算法、密钥长度、IV格式、填充方式完全一致:
- 密钥长度:MD5输出128位,对应AES-128,PHP端需使用
aes-128-cbc。 - IV处理:两端都要将MD5的十六进制字符串转换为二进制字节数据。
- 密钥解析:JS端必须用
CryptoJS.enc.Hex.parse解析MD5结果,确保密钥是正确的二进制字节数组。
内容的提问来源于stack exchange,提问作者modosayca
相关产品推荐
相关产品推荐

