You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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格式、填充方式完全一致:

  1. 密钥长度:MD5输出128位,对应AES-128,PHP端需使用aes-128-cbc。
  2. IV处理:两端都要将MD5的十六进制字符串转换为二进制字节数据。
  3. 密钥解析:JS端必须用CryptoJS.enc.Hex.parse解析MD5结果,确保密钥是正确的二进制字节数组。

内容的提问来源于stack exchange,提问作者modosayca

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 02:20:01