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

如何在PHP中解密JSEncrypt加密的数据?前后端加解密实操遇阻

解决JS前端+PHP后端加密通信中openssl_open的信封数据问题

嘿,我来帮你理清这个困惑——你现在卡在openssl_open的信封数据上,核心是没搞清楚这个函数的参数对应关系,以及JSEncrypt加密后的内容该怎么对接PHP端的解密流程。

首先得纠正一个误区:你以为的“信封数据”其实在openssl_open里拆成了两个关键部分,而不是一个复杂的结构体。咱们一步步拆解:

先搞懂openssl_open到底要什么

openssl_open是为标准信封加密流程设计的,它需要的核心参数其实是:

  • $envelope_key:用服务器公钥加密后的对称密钥(就是你前端用JSEncrypt生成的那串加密内容,解码成二进制后传入)
  • $iv:如果你的对称加密算法需要初始化向量(比如AES-CBC),就得把前端生成的IV传进来(IV可以明文传输,不需要加密)

很多文档里说的“信封”是指包含加密密钥+IV的整体,但openssl_open把这两个拆成了单独参数,这也是你混淆的原因。

完整流程示例(前端+后端)

前端JS代码(JSEncrypt + CryptoJS)

// 1. 生成对称加密所需的密钥和IV(以AES-256-CBC为例)
const symmetricKey = CryptoJS.lib.WordArray.random(256/8).toString();
const iv = CryptoJS.lib.WordArray.random(128/8).toString(); // CBC模式需要16字节IV

// 2. 用服务器公钥加密对称密钥
const encryptor = new JSEncrypt();
encryptor.setPublicKey('服务器公钥PEM字符串');
const encryptedSymmetricKey = encryptor.encrypt(symmetricKey);

// 3. 用对称密钥加密业务数据,然后把所有需要的参数发给后端
fetch('/api/secure-communication', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    encryptedKey: encryptedSymmetricKey,
    iv: iv,
    encryptedData: CryptoJS.AES.encrypt('你的敏感业务数据', symmetricKey, { iv: iv }).toString()
  })
});

后端PHP代码

// 1. 获取前端提交的数据
$postData = json_decode(file_get_contents('php://input'), true);
$encryptedKey = $postData['encryptedKey'];
$iv = $postData['iv'];
$encryptedData = $postData['encryptedData'];

// 2. 加载服务器私钥(确保是PEM格式)
$privateKey = openssl_pkey_get_private(file_get_contents('./server_private_key.pem'));

// 3. 解密对称密钥:两种方式都可以,选适合你的
// 方式一:用openssl_open(贴合你提到的函数)
$decryptedSymmetricKey = '';
openssl_open(
    '', // 这个参数是信封加密的整体业务数据,咱们这里业务数据单独加密了,所以留空
    $decryptedSymmetricKey,
    base64_decode($encryptedKey), // 把JSEncrypt的Base64输出解码成二进制
    $privateKey,
    'AES-256-CBC', // 和前端对称算法保持一致
    $iv
);

// 方式二:更直接的openssl_private_decrypt(其实更适配这个场景)
// openssl_private_decrypt(base64_decode($encryptedKey), $decryptedSymmetricKey, $privateKey);

// 4. 用解密后的对称密钥解密业务数据
$decryptedData = openssl_decrypt(
    base64_decode($encryptedData),
    'AES-256-CBC',
    $decryptedSymmetricKey,
    OPENSSL_RAW_DATA,
    $iv
);

echo $decryptedData;

避坑提醒

  • 算法一致性:前后端的对称加密算法、密钥长度、IV长度必须完全匹配,比如前端用AES-256-CBC,后端不能换成AES-128-ECB。
  • 填充方式:JSEncrypt默认用PKCS1Padding,PHP的openssl函数默认也是这个,别乱改,否则会解密失败。
  • Base64解码:JSEncrypt返回的加密密钥是Base64编码的字符串,PHP的openssl函数需要原始二进制数据,一定要记得解码。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 09:57:31