求适配NodeJS现有解密函数的兼容加密实现方案
问题描述
我有一个可正常解密C#请求payload的NodeJS解密函数_decryptMessage,代码如下:
function _decryptMessage(_encryptedData, _encryptedDek, _iv, _privateKey, _kek){ const decrypted = crypto.privateDecrypt({ key: _privateKey, passphrase: _kek, padding: crypto.constants.RSA_PKCS1_PADDING }, Buffer.from(_encryptedDek, "base64")); const dek = decrypted.toString("utf16le"); const buff = Buffer.from(_encryptedData, "base64"); const key = Buffer.from(dek, "utf8"); const iv = Buffer.from(_iv, "utf8"); const decipher = crypto.createDecipheriv("aes-256-cbc", key, iv); return decipher.update(buff).toString() + decipher.final().toString(); }
出于单元测试需求,我希望编写一个NodeJS等效加密函数,使加密后的JSON payload可被上述解密函数解密。尝试逆向编写代码时遭遇error:0200009F:rsa routines::pkcs decoding error错误,以下是未完成的_encrypt函数代码:
function _encrypt(_publicKey, _data){ const dek = "bf3c199c2470cb477d907b1e0917c17b"); const iv = "5183666c72eec9e4"); const encryptedData= (() => { const cipher = crypto.createCipheriv("aes-256-cbc", dek, iv); let encryptedData = cipher.update(_data, 'utf8', 'base64'); encryptedData += cipher.final('base64'); return { encryptedData }; })(); const encryptedDek = crypto.publicEncrypt({ key: _publicKey, oaepHash: "sha1", padding: crypto.constants.RSA_PKCS1_OAEP_PADDING }, dek).toString("base64"); return { encryptedDek, iv, encryptedData }; }
请求协助完善该加密函数,使其能适配现有解密函数正常工作。
解决方案
核心问题总结
- RSA填充方式不匹配:解密用
RSA_PKCS1_PADDING,加密误用RSA_PKCS1_OAEP_PADDING,导致解码错误 - DEK编码逻辑反向错误:解密时将RSA解密结果转
utf16le得到DEK,加密时未反向处理 - 存在语法错误:DEK和IV定义末尾多余闭合括号
- AES参数处理不严谨:未显式将DEK/IV转为Buffer,可能导致编码偏差
修正后的加密函数
function _encrypt(_publicKey, _data) { // 32位十六进制字符串,对应AES-256所需的32字节密钥 const dek = "bf3c199c2470cb477d907b1e0917c17b"; const iv = "5183666c72eec9e4"; // AES加密:对齐解密逻辑,显式转Buffer const cipher = crypto.createCipheriv( "aes-256-cbc", Buffer.from(dek, "utf8"), Buffer.from(iv, "utf8") ); let encryptedData = cipher.update(_data, "utf8", "base64"); encryptedData += cipher.final("base64"); // RSA加密DEK:匹配解密的PKCS1填充,将DEK转utf16le编码后加密 const dekUtf16leBuffer = Buffer.from(dek, "utf16le"); const encryptedDek = crypto.publicEncrypt( { key: _publicKey, padding: crypto.constants.RSA_PKCS1_PADDING }, dekUtf16leBuffer ).toString("base64"); return { encryptedDek, iv, encryptedData }; }
关键修改说明
- 对齐RSA填充:将加密的RSA padding改为
RSA_PKCS1_PADDING,与解密函数完全匹配,解决PKCS解码错误 - 反向处理DEK编码:加密时把DEK字符串转成
utf16le编码的Buffer再进行RSA加密,对应解密时decrypted.toString("utf16le")的逆向操作 - 修复语法错误:删除DEK和IV定义末尾多余的
) - 规范AES参数:显式将DEK和IV转为Buffer,确保编码与解密逻辑一致
- 简化代码结构:移除不必要的自执行函数,提升代码可读性
内容的提问来源于stack exchange,提问作者MFAL
相关产品推荐
相关产品推荐

