OpenSSL解密Node.js Crypto RSA加密UUID失败问题排查
问题根因
你遇到的解密失败由两个不匹配问题共同导致:
- 输入密文格式不匹配:你存储、下载到txt文件的内容是密文的base64编码字符串,不是RSA解密要求的原始二进制密文。Node.js侧解密成功是因为你显式调用
Buffer.from(encryptedUUID, "base64")完成了base64解码,拿到了2048位RSA对应的256字节标准长度密文;但OpenSSL的pkeyutl默认将输入文件内容直接作为原始二进制密文读取,base64字符串长度远大于256字节,直接触发「data greater than mod len」报错。 - RSA填充模式不匹配:Node.js
crypto.publicEncrypt默认使用RSA_PKCS1_OAEP_PADDING(PKCS#1 v2.0 OAEP填充,默认哈希算法为SHA256),而OpenSSLpkeyutl解密默认使用RSA_PKCS1_PADDING(PKCS#1 v1.5填充),即使完成base64解码,填充参数不匹配也会导致解密失败。
可落地修复方案
二选一即可:
方案1:调整OpenSSL解密命令,对齐现有加密逻辑
不需要修改前后端代码,解密时增加base64解码步骤、显式指定填充参数即可:
- 先将txt文件中的base64密文转为原始二进制格式:
openssl base64 -d -in encrypted-password.txt -out encrypted_raw.bin
- 解密时显式指定使用OAEP填充,哈希参数对齐Node.js默认值:
openssl pkeyutl -decrypt -inkey private_key.pem -in encrypted_raw.bin -out decrypted-password.txt -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha256 -pkeyopt rsa_mgf1_md:sha256
执行后decrypted-password.txt中就是原始UUID内容。
方案2:调整Node.js加密逻辑,对齐OpenSSL默认行为
如果希望简化后续OpenSSL解密命令,可以修改Node.js端加密配置,使用OpenSSL默认支持的PKCS#1 v1.5填充:
import * as crypto from "crypto"; // ... const uuidBuffer = Buffer.from(generatedUUID); const encryptedUUID = crypto.publicEncrypt( { key: publicKey, padding: crypto.constants.RSA_PKCS1_PADDING }, uuidBuffer ).toString("base64");
后续解密时,只需要先做base64转二进制,不需要额外指定填充参数:
openssl base64 -d -in encrypted-password.txt -out encrypted_raw.bin openssl pkeyutl -decrypt -inkey private_key.pem -in encrypted_raw.bin -out decrypted-password.txt
注意:如果选择存储二进制密文而非base64编码字符串,可以省略base64解码步骤,但需要确保数据库字段支持二进制存储、前端下载时不做字符编码转义,否则容易出现密文损坏问题。
内容的提问来源于stack exchange,提问作者Benjamin B.
相关产品推荐
相关产品推荐

