为什么我不能解密一个文件与NodeJS我用openssl加密? [英] why can't i decrypt a file with NodeJS that i encrypted with openssl?

查看:159
本文介绍了为什么我不能解密一个文件与NodeJS我用openssl加密?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用

  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 decode.update(text_crypt,'binary');
chunks.push decoder.final('binary');
text = chunks.join('').toString('utf-8');

此失败与

  TypeError:error:06065064:数字信封例程:EVP_DecryptFinal_ex:坏解密

什么我做错了吗?

解决方案

密码学很有趣。以下是使用salt将openssl加密的文件解密的代码。

  var crypto = require('crypto'); 

函数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(decode.update(cryptotext,binary,utf8));
chunks.push(decode.final(utf8));
console.log(chunks.join(''));

更新:有关什么是cbc模式以及openssl如何工作的详细信息? / p>

如果你查看流密码在密码块链接模式,您将注意到密码开始加密数据需要两个初始值:初始化向量(iv)和密钥。重要的是,初始化向量的大小应等于块大小,密钥大小取决于算法,AES-256的长度为256位。



但用户不想设置256位随机密码来访问其数据。这将打开一个关于如何从用户的输入构建密钥和iv的问题,并且openssl通过将EVP_BytesToKey函数应用于用户输入来解决这个问题,这实际上MD5应用于密码和盐多次。



您可以通过执行

  C:\Tools\wget> openssl enc -aes-256-cbc -P 
输入aes-256-cbc加密密码:
验证 - 输入aes-256-cbc加密密码:
salt = A94B7976B2534923
key = C8B806C86E60ED664B9C369628D1A78260753580D78D09EAEC04EAC1535077C3
iv = 7B6FB26EB62C34F04F254A0C4F4F502A

这里的参数key和iv是输入参数密码和盐需要随机化密文,因此对于相同的数据将不会相同。



openssl将文件中的数据保存如下:

  Saltet __; [salt] [cipher-text] 

所以要解密我应该执行以下步骤:


  1. 应该跳过Salted前缀

  2. 8输入的字节应该从密码中读取并保存为盐

  3. ,并且键入并且iv应该被构造为

  4. 文件的其余部分应使用计算密钥应用AES-256-CBC解密器解密,并且iv

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


i encrypted a file on the command line using

openssl aes-256-cbc -in /tmp/text.txt -out /tmp/text.crypt

i then tried to decrypt it using the following JavaScript code:

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' );

this fails with

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

what am i doing wrong?

解决方案

Cryptography is fun. Here is the code that decrypts file encrypted with openssl with salt.

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(''));

Update: more details on what is cbc mode and how openssl works

If you look on how the stream ciphers in cipher-block chaining mode work you will notice that two initial values are required for the cipher to start encrypting the data: initialization vector (iv) and the key. It is important that size of the initialization vector should be equal to the block size and the key size depends on the algorithm, for AES-256 it is 256-bit long.

But users do not want to set up 256-bit random passwords to access their data. This opens a question on how to construct the key and iv from the user's input and openssl solves it by applying EVP_BytesToKey function to the user input, which is practically MD5 applied to the password and salt multiple times.

You can see the derived values by executing

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

The parameters "key and "iv" here are the input parameters to the cipher and the salt is required to randomize the cipher-text so it will not be the same for the same data.

The openssl saves the data in the file as follows:

Saltet__;[salt][cipher-text]

So to decrypt it the following steps should be made:

  1. the "Salted" prefix should be skipped
  2. 8 bytes of the input should be read and saved as salt
  3. from the password and salt the key and iv should be constructed
  4. the rest of the file should be decrypted by applying AES-256-CBC decryptor with calculated key and iv

The code above performs these steps and decrypts the file.

这篇关于为什么我不能解密一个文件与NodeJS我用openssl加密?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆