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

将PHP AES-256-CBC解密函数移植到Node.js时遇到问题求助

问题:将PHP AES-256-CBC解密函数移植到Node.js时无法正常运行

我在把一个PHP的AES解密函数移植到Node.js时遇到了问题,Node.js版本的函数无法正常解密API响应,解密结果既不输出也无法正确返回。以下是我的代码:

原PHP解密函数

<?php
require_once 'vendor/autoload.php';

function stringDecrypt($key, $string){
    $encrypt_method = 'AES-256-CBC';
    // hash
    $key_hash = hex2bin(hash('sha256', $key));
    // iv - encrypt method AES-256-CBC expects 16 bytes - else you will get a warning
    $iv = substr(hex2bin(hash('sha256', $key)), 0, 16);
    $output = openssl_decrypt(base64_decode($string), $encrypt_method, $key_hash, OPENSSL_RAW_DATA, $iv);
    return $output;
}
?>

我写的Node.js代码(无法正常运行)

function decryptResponse(timestamp, string, key) {
    var key_hash = hex2bin(crypto.createHash("sha256").update(key).digest('hex'));
    var iv = key_hash.substr(0,16);
    var decoder = crypto.createDecipheriv('aes-256-cbc', key_hash, iv);
    var output = decoder.update(Buffer.from(string).toString('base64'),'base64','utf8') += decoder.final('utf8');
    console.log("Decrypt Result : ", output); //Not Showing on Log
}

function hex2bin(hex) {
    var bytes = [];
    var str;
    for(var i=0; i< hex.length-1; i+=2){
        bytes.push(parseInt(hex.substr(i, 2), 16));
    }
    str = String.fromCharCode.apply(String, bytes);
    return str;
}

// 调用方式
var decompressedResponse = decryptResponse(timestamp, response.data.response, key);
res.send(decompressedResponse);

问题分析与修正方案

你的Node.js代码有几个关键问题导致解密失败:

  1. 自定义hex2bin的编码问题:
    PHP的hex2bin返回的是原始字节流,而你用String.fromCharCode转换的字符串会受Node.js默认编码影响,导致字节流不一致。直接用Node.js的Buffer处理十六进制转字节更可靠。

  2. 输入处理反向错误:
    PHP中是先对输入字符串做base64_decode,而你的Node.js代码里把输入string转成Buffer再转成base64,这完全搞反了——应该直接把输入字符串做base64解码成Buffer。

  3. 语法错误导致变量无值:
    var output = decoder.update(...) += decoder.final(...)是错误的赋值写法,会导致output未正确获取解密结果。

  4. 函数未返回结果:
    decryptResponse函数没有返回解密后的内容,调用时自然拿不到值。

修正后的Node.js代码

const crypto = require('crypto'); // 记得引入crypto模块

function decryptResponse(timestamp, string, key) {
    // 直接用Buffer处理hex转字节,替代自定义的hex2bin
    const keyHashHex = crypto.createHash("sha256").update(key).digest('hex');
    const keyHash = Buffer.from(keyHashHex, 'hex');
    // 截取前16字节作为IV,和PHP逻辑一致
    const iv = keyHash.subarray(0, 16);
    
    // 创建解密器,注意Node.js中createDecipheriv的参数需要Buffer类型
    const decipher = crypto.createDecipheriv('aes-256-cbc', keyHash, iv);
    // 正确处理输入:先base64解码,再分步骤解密
    let output = decipher.update(string, 'base64');
    output = Buffer.concat([output, decipher.final()]);
    
    // 转成utf8字符串(如果解密结果是文本的话,根据实际情况调整编码)
    const result = output.toString('utf8');
    console.log("Decrypt Result : ", result);
    return result; // 一定要返回结果
}

// 调用方式不变,现在能正确拿到解密结果
var decompressedResponse = decryptResponse(timestamp, response.data.response, key);
res.send(decompressedResponse);

额外说明

  • 确保已经引入crypto模块(Node.js内置模块,无需额外安装)。
  • 如果解密后的内容是二进制数据(比如压缩包),可以去掉toString('utf8'),直接返回Buffer即可。
  • Node.js的subarray和PHP的substr在处理字节流时逻辑一致,都是截取指定长度的字节。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.01 01:57:38