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

无法用Node.js crypto解密OpenSSL AES-256-CBC加密内容

Bash AES-256-CBC加密内容的Node.js解密方案

我用OpenSSL命令对字符串进行AES-256-CBC加密和解密完全正常:

ENCRYPTED=$(echo "my_secret_data" | openssl aes-256-cbc -pass "pass:bab3fd92bcd7d464" -pbkdf2 -a -A)

echo -n $ENCRYPTED | base64 -d | openssl aes-256-cbc -d -pass "pass:bab3fd92bcd7d464" -pbkdf2

但用Node.js的crypto模块解密时,执行以下代码报错:

const crypto = require('crypto');

const encryptedTextBase64 = 'U2FsdGVkX18AYE13z9uboo3WZhktr03EeV0WFA0MH4o=';
const password = 'bab3fd92bcd7d464';

// Decode the base64-encoded text
const encryptedText = Buffer.from(encryptedTextBase64, 'base64');

// Create a decipher object
const decipher = crypto.createDecipher('aes-256-cbc', password);

// Update the decipher with the encrypted text
let decrypted = decipher.update(encryptedText, 'binary', 'utf8');
decrypted += decipher.final('utf8');

console.log(decrypted);

错误信息:

node:internal/crypto/cipher:199
  const ret = this[kHandle].final();
                            ^

Error: error:1C800064:Provider routines::bad decrypt
    at Decipher.final (node:internal/crypto/cipher:199:29)
    at Object.<anonymous> (.../decrypt.js:14:23)
    at Module._compile (node:internal/modules/cjs/loader:1256:14)
    at Module._extensions..js (node:internal/modules/cjs/loader:1310:10)
    at Module.load (node:internal/modules/cjs/loader:1119:32)
    at Module._load (node:internal/modules/cjs/loader:960:12)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:86:12)
    at node:internal/main/run_main_module:23:47 {
  library: 'Provider routines',
  reason: 'bad decrypt',
  code: 'ERR_OSSL_BAD_DECRYPT'
}

目标是实现Bash加密、Node.js解密的兼容。


问题原因

OpenSSL的aes-256-cbc命令默认生成带盐值的特殊格式(开头固定为Salted__),且使用PBKDF2推导密钥时的默认参数(迭代次数10000、哈希算法SHA-256)与Node.js旧APIcreateDecipher的默认逻辑不匹配,导致密钥/IV推导不一致,触发解密失败。


解决方案

正确的Node.js解密代码

手动解析OpenSSL加密格式中的盐值,用PBKDF2推导匹配的密钥和IV,再调用createDecipheriv完成解密:

const crypto = require('crypto');

const encryptedTextBase64 = 'U2FsdGVkX18AYE13z9uboo3WZhktr03EeV0WFA0MH4o=';
const password = 'bab3fd92bcd7d464';

// 解码base64并提取OpenSSL格式中的盐值和密文
const encryptedBuffer = Buffer.from(encryptedTextBase64, 'base64');
const salt = encryptedBuffer.slice(8, 16); // 前8字节为固定标识"Salted__",后续8字节是盐值
const ciphertext = encryptedBuffer.slice(16);

// 用PBKDF2推导密钥和IV,匹配OpenSSL默认参数
const keyIv = crypto.pbkdf2Sync(password, salt, 10000, 48, 'sha256');
const key = keyIv.slice(0, 32); // AES-256需要32字节密钥
const iv = keyIv.slice(32, 48); // CBC模式需要16字节IV

// 执行解密
const decipher = crypto.createDecipheriv('aes-256-cbc', key, iv);
let decrypted = decipher.update(ciphertext, 'binary', 'utf8');
decrypted += decipher.final('utf8');

console.log(decrypted); // 输出: my_secret_data

可选:调整Bash加密命令(如需更可控格式)

如果不想处理OpenSSL默认格式,可在加密时显式指定盐值和IV,但需额外保存这些参数用于解密。不过保持原加密命令即可,上述Node.js代码已完全兼容默认格式。


内容的提问来源于stack exchange,提问作者Miguel Prytoluk

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 23:07:24