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

PHP解密CryptoJS-AES CBC加密内容失败(无IV)的问题排查

问题根源

CryptoJS的AES.encrypt(text, key)默认生成的是OpenSSL兼容的加盐格式密文(开头为U2FsdGVkX1/,对应字节Salted__),而你的PHP代码没有解析这个格式,直接传入openssl_decrypt导致解密失败。

具体差异:

  • CryptoJS会自动生成随机盐,再通过EVP_BytesToKey算法,从你传入的密钥字符串+盐生成真正的AES-256密钥和IV(CBC模式必须依赖IV)
  • 当前PHP代码直接用原始密钥字符串解密,既没解析盐,也没生成匹配的密钥和IV,自然解密失败。
修正后的PHP解密代码
<?php
$key = '12345678123456781234567812345678';
$ciphertext = "U2FsdGVkX1/ARpsMWWEdLiOanB67kh2akfCIN5s+RLDsJetSMagGsk444I+F/dbp";

// 1. 解析CryptoJS的加盐格式密文
$decoded = base64_decode($ciphertext);
$salt = substr($decoded, 8, 8); // 跳过前8字节的"Salted__"标识,提取8字节盐
$realCiphertext = substr($decoded, 16); // 剩余部分为真正的密文

// 2. 用EVP_BytesToKey算法生成匹配的AES密钥和IV(和CryptoJS逻辑一致)
$evpResult = EVP_BytesToKey($salt, $key);
$aesKey = substr($evpResult, 0, 32); // AES-256需要32字节密钥
$iv = substr($evpResult, 32, 16); // CBC模式需要16字节IV

// 3. 执行解密
$result = openssl_decrypt($realCiphertext, 'AES-256-CBC', $aesKey, OPENSSL_RAW_DATA, $iv);

// 输出结果与错误信息
var_dump($result);
while ($msg = openssl_error_string()) {
    echo $msg . "<br />";
}

// 实现EVP_BytesToKey算法(和OpenSSL/CryptoJS逻辑对齐)
function EVP_BytesToKey($salt, $password) {
    $key = '';
    $data = '';
    while (strlen($key) < 48) { // 32字节密钥 + 16字节IV = 共48字节
        $data = hash('md5', $data . $password . $salt, true);
        $key .= $data;
    }
    return $key;
}
?>
关键说明
  • CryptoJS的AES.encrypt默认行为:传入字符串密钥时,自动使用EVP_BytesToKey生成密钥和IV,同时输出包含盐的格式
  • 必须先解析密文中的盐,再用相同算法生成密钥和IV,才能和CryptoJS的加密逻辑匹配
  • 必须加上OPENSSL_RAW_DATA参数,因为我们传入的是原始字节密文,而非base64编码格式

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 21:15:41