将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代码有几个关键问题导致解密失败:
自定义hex2bin的编码问题:
PHP的hex2bin返回的是原始字节流,而你用String.fromCharCode转换的字符串会受Node.js默认编码影响,导致字节流不一致。直接用Node.js的Buffer处理十六进制转字节更可靠。输入处理反向错误:
PHP中是先对输入字符串做base64_decode,而你的Node.js代码里把输入string转成Buffer再转成base64,这完全搞反了——应该直接把输入字符串做base64解码成Buffer。语法错误导致变量无值:
var output = decoder.update(...) += decoder.final(...)是错误的赋值写法,会导致output未正确获取解密结果。函数未返回结果:
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
相关产品推荐
相关产品推荐

