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

如何使用Laravel解密由CryptoJS生成的动态密钥加密内容?

在Laravel中解密CryptoJS生成的AES加密字符串

问题场景

前端用CryptoJS实现了AES加密,代码如下:

<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js"></script>
<script>
  const key = localStorage.getItem('key')
  // ... 其他业务逻辑
  content = CryptoJS.AES.encrypt(fileContent, key).toString();
  // ... 其他业务逻辑
</script>

现在需要在Laravel中解密该加密字符串,当前写的Laravel代码如下,但无法正确完成解密:

$cipher = "aes-256-cbc"; // 不确定这个值是否正确
$key = $request->key;
$value = $request->value;
$encrypter = new Encrypter($key, $cipher);

关键说明

CryptoJS的AES.encrypt默认采用AES-256-CBC模式,但它的加密格式和Laravel自带Encrypter类的格式不兼容:

  • CryptoJS会自动用PBKDF2算法从用户输入的key推导真正的加密密钥
  • 加密结果是包含salted__标识、随机salt、密文的组合Base64字符串
  • Laravel的Encrypter有自己的签名和格式规范,无法直接解析CryptoJS的加密结果

实现步骤与代码

直接用PHP的openssl扩展手动解析解密,代码示例:

use Illuminate\Contracts\Encryption\DecryptException;

function decryptCryptoJSAES(string $encryptedData, string $password): string
{
    // 解码Base64格式的加密字符串
    $decoded = base64_decode($encryptedData);
    
    // 校验CryptoJS加密标识
    if (substr($decoded, 0, 8) !== 'salted__') {
        throw new DecryptException('无效的CryptoJS加密数据');
    }
    
    // 提取salt和密文(前8字节是标识,接下来8字节是salt,剩余为密文)
    $salt = substr($decoded, 8, 8);
    $ciphertext = substr($decoded, 16);
    
    // 用PBKDF2推导密钥和IV(CryptoJS默认参数:迭代1000次,SHA-1,生成48字节数据:32字节key + 16字节iv)
    $derived = hash_pbkdf2('sha1', $password, $salt, 1000, 48, true);
    $key = substr($derived, 0, 32);
    $iv = substr($derived, 32, 16);
    
    // 解密,CryptoJS默认用PKCS#7填充,对应OPENSSL_RAW_DATA参数
    $decrypted = openssl_decrypt(
        $ciphertext,
        'aes-256-cbc',
        $key,
        OPENSSL_RAW_DATA,
        $iv
    );
    
    // 去除PKCS#7填充
    $paddingLength = ord(substr($decrypted, -1));
    return substr($decrypted, 0, -$paddingLength);
}

// 调用示例
try {
    $userKey = $request->input('key');
    $encryptedContent = $request->input('value');
    $originalContent = decryptCryptoJSAES($encryptedContent, $userKey);
    
    // 处理解密后的内容
} catch (DecryptException $e) {
    // 解密失败处理,比如密钥错误、数据损坏等
    abort(400, $e->getMessage());
}

注意事项

  • 确保前后端的key完全一致,包括字符编码、大小写、空格等,任何差异都会导致解密失败
  • 如果前端加密时手动指定了模式、填充方式或迭代次数,后端必须对应调整参数
  • 不要尝试用Laravel自带的Encrypter类直接解密,两者格式不兼容

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 12:43:07