如何在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
相关产品推荐
相关产品推荐

