如何在Node.js中解密PHP用AES-128-CBC加密的字符串?
问题:PHP加密AES-128-CBC字符串后,Node.js解密失败
需要将字符串加密后通过HTTP请求发送,再在Node.js服务器中解密,但解密时出现以下错误:
wrong final block length(最终块长度错误)this[kHandle].initiv(cipher, credential, iv, authTagLength); TypeError: Invalid initialization vector(无效的初始化向量)
PHP端加密代码
$var = openssl_encrypt('string', "aes-128-cbc", 'stringstringstri');
Node.js端尝试的解密代码
第一种
let decipher = crypto.createDecipher('aes-128-cbc', 'stringstringstri'); let decrypted = decipher.update(encrypted, 'utf8', 'utf8') + decipher.final('utf8');
第二种
const initVector = crypto.randomBytes(32); const decipher = crypto.createDecipheriv('aes-128-cbc', 'stringstringstri', initVector) let decryptedData = decipher.update(encrypted, 'utf8', 'utf-8') decryptedData += decipher.final('utf-8');
错误原因分析
- 密钥处理不匹配:第一种代码用
createDecipher方法,该方法会通过EVP_BytesToKey算法派生密钥,但PHP的openssl_encrypt是直接使用原始密钥,导致两端密钥不一致,触发「最终块长度错误」。 - IV长度错误:AES-128-CBC模式要求初始化向量(IV)长度为16字节,第二种代码生成了32字节的IV,不符合要求,触发「无效的初始化向量」错误。
- 编码不匹配:PHP的
openssl_encrypt默认输出base64编码的字符串,Node.js端用utf8解析加密数据会导致数据损坏,也是解密失败的原因之一。
修复方案
1. 修改PHP加密代码(统一参数并携带IV)
CBC模式必须使用IV,且两端要共用同一个IV,因此需要将IV和加密数据一起发送:
$plaintext = 'string'; $key = 'stringstringstri'; // 16字节,符合AES-128密钥长度要求 $iv = openssl_random_pseudo_bytes(16); // 生成标准16字节IV // 用OPENSSL_RAW_DATA输出原始二进制,再转base64;同时将IV也转base64,用分隔符拼接 $encryptedRaw = openssl_encrypt($plaintext, 'aes-128-cbc', $key, OPENSSL_RAW_DATA, $iv); $sendData = base64_encode($iv) . ':' . base64_encode($encryptedRaw);
2. Node.js端解密代码
解析发送过来的IV和加密数据,用正确的参数解密:
const crypto = require('crypto'); // 假设从HTTP请求中获取到sendData const [ivBase64, encryptedBase64] = sendData.split(':'); const iv = Buffer.from(ivBase64, 'base64'); const encrypted = Buffer.from(encryptedBase64, 'base64'); const key = Buffer.from('stringstringstri', 'utf8'); const decipher = crypto.createDecipheriv('aes-128-cbc', key, iv); let decryptedBuffer = decipher.update(encrypted); decryptedBuffer = Buffer.concat([decryptedBuffer, decipher.final()]); const plaintext = decryptedBuffer.toString('utf8'); console.log(plaintext); // 输出:string
内容的提问来源于stack exchange,提问作者Chumachenko Mihail
相关产品推荐
相关产品推荐

