如何用JavaScript解密PHP加密的AES-256-CBC字符串(不修改PHP代码)
解决Node.js解密PHP生成的AES-256-CBC密文时的"Invalid key length"错误(无需修改PHP代码)
可以不用修改PHP代码完成解密,问题出在PHP和Node.js对密钥的处理逻辑差异上:
- PHP的
openssl_encrypt在使用AES-256-CBC时,如果传入的密钥长度不符合32字节(256位)要求,会自动用NULL字节(\x00)填充到32字节;如果密钥超过32字节,则直接截断到前32字节。 - Node.js的
crypto模块则要求密钥长度严格匹配算法要求,不会自动处理,所以才会抛出"Invalid key length"错误。
解决步骤
- 确认PHP加密时使用的原始密钥和IV(这两个参数必须和PHP端完全一致)
- 在Node.js中按照PHP的逻辑处理密钥和IV:
- 密钥:调整为32字节,不足补\x00,过长则截断前32字节
- IV:调整为16字节(AES-CBC块大小),不足补\x00,过长则截断前16字节
- 用处理后的密钥和IV执行解密
Node.js示例代码
const crypto = require('crypto'); function decryptPhpAes(encryptedBase64, rawIv, rawKey) { // 处理密钥:匹配PHP的自动补全/截断逻辑 let keyBuffer = Buffer.from(rawKey, 'utf8'); if (keyBuffer.length !== 32) { keyBuffer = keyBuffer.length < 32 ? Buffer.concat([keyBuffer, Buffer.alloc(32 - keyBuffer.length, 0)]) : keyBuffer.slice(0, 32); } // 处理IV:匹配PHP的自动补全/截断逻辑 let ivBuffer = Buffer.from(rawIv, 'utf8'); if (ivBuffer.length !== 16) { ivBuffer = ivBuffer.length < 16 ? Buffer.concat([ivBuffer, Buffer.alloc(16 - ivBuffer.length, 0)]) : ivBuffer.slice(0, 16); } // 执行解密 const decipher = crypto.createDecipheriv('aes-256-cbc', keyBuffer, ivBuffer); let decrypted = decipher.update(encryptedBase64, 'base64', 'utf8'); decrypted += decipher.final('utf8'); return decrypted; } // 替换为你的实际参数 const encryptedStr = 'Ky27sjhxUY7BFoscEgyFToxRDAsARzRFgQBIApbPmjQ='; const phpIv = '这里填PHP加密用的IV'; const phpKey = '这里填PHP加密用的密钥'; console.log(decryptPhpAes(encryptedStr, phpIv, phpKey));
注意事项
- 必须确保PHP和Node.js使用的字符编码一致(通常都是UTF-8)
- 如果PHP端加密时使用了
OPENSSL_RAW_DATA选项,密文会是原始二进制而不是Base64,此时解密时要去掉base64参数,改用binary或者直接传入Buffer
内容的提问来源于stack exchange,提问作者Andrey A
相关产品推荐
相关产品推荐

