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

如何在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');

错误原因分析

  1. 密钥处理不匹配:第一种代码用createDecipher方法,该方法会通过EVP_BytesToKey算法派生密钥,但PHP的openssl_encrypt是直接使用原始密钥,导致两端密钥不一致,触发「最终块长度错误」。
  2. IV长度错误:AES-128-CBC模式要求初始化向量(IV)长度为16字节,第二种代码生成了32字节的IV,不符合要求,触发「无效的初始化向量」错误。
  3. 编码不匹配: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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 07:15:25