Node.js 为什么可以';我不能用我用openssl加密的NodeJS解密一个文件吗?

Node.js 为什么可以';我不能用我用openssl加密的NodeJS解密一个文件吗?,node.js,encryption,Node.js,Encryption,我在命令行上使用 openssl aes-256-cbc -in /tmp/text.txt -out /tmp/text.crypt 然后,我尝试使用以下JavaScript代码对其进行解密: crypto = require( 'crypto' ); cipher_name = 'aes-256-cbc'; password = '*'; decoder = crypto.createDecipher( cipher_name, password )

我在命令行上使用

openssl aes-256-cbc -in /tmp/text.txt -out /tmp/text.crypt
然后,我尝试使用以下JavaScript代码对其进行解密:

crypto        = require( 'crypto' );
cipher_name   = 'aes-256-cbc';
password      = '*';
decoder       = crypto.createDecipher( cipher_name, password );
text_crypt    = njs_fs.readFileSync( '/tmp/text.crypt' );
chunks        = [];
chunks.push decoder.update( text_crypt, 'binary' );
chunks.push decoder.final( 'binary' );
text          = chunks.join( '' ).toString( 'utf-8' );
这与

TypeError: error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt

我做错了什么?

加密很有趣。下面是用salt对用openssl加密的文件进行解密的代码

var crypto = require('crypto');

function md5(data) {
    var hash = crypto.createHash('md5');
    hash.update(data);
    return new Buffer(hash.digest('hex'), 'hex');
}

var text = require('fs').readFileSync('text.crypt');
var salt = text.slice(8, 16);
var cryptotext = text.slice(16);
var password = new Buffer('*');

var hash0 = new Buffer('');
var hash1 = md5(Buffer.concat([ hash0, password, salt ]));
var hash2 = md5(Buffer.concat([ hash1, password, salt ]));
var hash3 = md5(Buffer.concat([ hash2, password, salt ]));
var key = Buffer.concat([ hash1, hash2 ]);
var iv = hash3;

var decoder = crypto.createDecipheriv('aes-256-cbc', key, iv);

var chunks = [];
chunks.push(decoder.update(cryptotext, "binary", "utf8"));
chunks.push(decoder.final("utf8"));
console.log(chunks.join(''));
更新:关于什么是cbc模式以及openssl如何工作的更多详细信息

如果您观察流密码是如何工作的,您会注意到密码开始加密数据需要两个初始值:初始化向量(iv)和密钥。重要的是,初始化向量的大小应等于块大小,密钥大小取决于算法,对于AES-256,其长度为256位

但是用户不希望设置256位随机密码来访问他们的数据。这打开了一个关于如何从用户输入构造密钥和iv的问题,openssl通过将EVP_BytesToKey函数应用于用户输入解决了这个问题,实际上MD5多次应用于密码和salt

您可以通过执行

C:\Tools\wget>openssl enc -aes-256-cbc -P
enter aes-256-cbc encryption password:
Verifying - enter aes-256-cbc encryption password:
salt=A94B7976B2534923
key=C8B806C86E60ED664B9C369628D1A78260753580D78D09EAEC04EAC1535077C3
iv =7B6FB26EB62C34F04F254A0C4F4F502A
这里的参数“key”和“iv”是密码的输入参数,salt需要对密码文本进行随机化,因此对于相同的数据,它将不相同

openssl将数据保存在文件中,如下所示:

Saltet__;[salt][cipher-text]
因此,要对其进行解密,应执行以下步骤:

  • 应跳过“Salted”前缀
  • 应读取8字节的输入并将其保存为salt
  • 根据密码和salt,应该构造密钥和iv
  • 文件的其余部分应使用AES-256-CBC解密程序和计算密钥进行解密

  • 上面的代码执行这些步骤并解密文件。

    类似的问题是:将
    -nosalt
    openssl
    一起使用将解决此问题。我不知道Node是否支持salt。但我知道了!如果您愿意,请将您的评论作为答案,这样我就可以接受它。我只发现了一个相关问题;)尽管如此,请查看@AlexAtNet的答案!@robertk顺便说一句,OpenSSL文档明确指出,除了用于测试目的或与OpenSSL和SSLeay的古老版本兼容之外,不应使用nosalt“-@AlexAtNet这就是为什么我没有回答,只是对一个相关问题发表了评论。如果我说你的回答,虽然可能以一种相当含蓄的方式解决了手头的问题,但至少提出了它试图解决的许多新问题,你会原谅我的。也就是说,我没有意识到,
    openssl
    默认情况下使用了salt,而NodeJS却幸福地没有意识到salt。-我自己就被那些对
    md5
    函数的重复调用所困扰,想知道
    iv
    可能是什么的缩写。我希望更新会有所帮助,如果您还有其他问题,请告诉我。谢谢。看到我对这些事情知之甚少,总是感到惊讶。我不知道你在哪里解释TESTOKEY指定给EVP_的轮数