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

如何使用Node.js解密经OpenSSL加密的文件

解决OpenSSL AES-256加密文件的Crypto库解密问题

核心问题原因

你用openssl enc -aes256 -k加密时,不是直接将密码作为密钥,而是通过OpenSSL特定的密钥派生算法生成密钥和IV。不同OpenSSL版本使用的派生逻辑不同,这是解密失败的核心。

解密步骤(分版本处理)

1. 提取加密文件中的Salt

OpenSSL默认会在加密文件开头添加Salted__标识(8字节)+ 8字节的salt值,解密必须使用这个salt:

// 示例:Node.js中读取并提取salt
const fs = require('fs');
const encryptedData = fs.readFileSync('encrypted');
const salt = encryptedData.slice(8, 16); // 第9-16字节是salt
const ciphertext = encryptedData.slice(16); // 剩余部分是实际密文

2. 根据OpenSSL版本生成密钥和IV

先通过openssl version确认你的版本:

情况1:OpenSSL版本 < 1.1.0c

使用EVP_BytesToKey算法,默认参数:MD5哈希、迭代次数1,生成32字节密钥(AES-256)+16字节IV:

const crypto = require('crypto');

function evpBytesToKey(passwordBytes, salt, keyLen, ivLen) {
  let key = Buffer.alloc(0);
  let iv = Buffer.alloc(0);
  let last = Buffer.alloc(0);
  
  while (key.length < keyLen || iv.length < ivLen) {
    last = crypto.createHash('md5')
                 .update(Buffer.concat([last, passwordBytes, salt]))
                 .digest();
    // 填充密钥和IV
    if (key.length < keyLen) {
      const need = keyLen - key.length;
      key = Buffer.concat([key, last.slice(0, need)]);
    }
    if (iv.length < ivLen) {
      const need = ivLen - iv.length;
      iv = Buffer.concat([iv, last.slice(Math.max(0, last.length - need))]);
    }
  }
  return { key, iv };
}

// 生成密钥和IV
const passwordBytes = Buffer.from('myverystrongpassword', 'utf8');
const { key, iv } = evpBytesToKey(passwordBytes, salt, 32, 16);

情况2:OpenSSL版本 >= 1.1.0c

默认改用PBKDF2算法,参数:SHA256哈希、迭代次数10000,生成48字节派生数据(前32字节密钥,后16字节IV):

const crypto = require('crypto');

const passwordBytes = Buffer.from('myverystrongpassword', 'utf8');
// 生成48字节派生数据:32字节密钥 + 16字节IV
const derived = crypto.pbkdf2Sync(passwordBytes, salt, 10000, 32 + 16, 'sha256');
const key = derived.slice(0, 32);
const iv = derived.slice(32);

3. 执行解密

使用AES-256-CBC算法(OpenSSL默认模式)+ PKCS#7填充(默认填充方式)解密:

const decipher = crypto.createDecipheriv('aes-256-cbc', key, iv);
let decrypted = decipher.update(ciphertext);
decrypted = Buffer.concat([decrypted, decipher.final()]);

// 保存解密后的文件
fs.writeFileSync('decrypted_data', decrypted);

常见错误排查

  • 忽略salt:必须提取加密文件中的salt,不能用自定义或空salt
  • 哈希函数/迭代次数不匹配:严格对应OpenSSL版本的默认参数
  • 加密模式错误:OpenSSL aes256默认是CBC模式,不是ECB或GCM

内容的提问来源于stack exchange,提问作者Karol M

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 12:25:14