使用 node.js 解密 AES256 返回错误的最终块长度

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/21292142/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 16:43:46  来源:igfitidea点击:

Decrypting AES256 with node.js returns wrong final block length

node.jsencryptionopensslaes

提问by Justin Cloud

Using this GistI was able to successfully decrypt AES256 in Node.js 0.8.7. Then when I upgraded to Node.js 0.10.24, I now see this error:

使用这个Gist,我能够在 Node.js 0.8.7 中成功解密 AES256。然后当我升级到 Node.js 0.10.24 时,我现在看到这个错误:

TypeError: error:0606506D:digital envelope routines:EVP_DecryptFinal_ex:wrong final block length
at Decipheriv.Cipher.final (crypto.js:292:27)

类型错误:错误:0606506D:数字信封例程:EVP_DecryptFinal_ex:
Decipheriv.Cipher.final 的最终块长度错误(crypto.js:292:27)

Here is the decrypt code from the Gist (shown here for convenience):

这是 Gist 中的解密代码(为方便起见,此处显示):

var crypto = require('crypto');

var AESCrypt = {};

AESCrypt.decrypt = function(cryptkey, iv, encryptdata) {
encryptdata = new Buffer(encryptdata, 'base64').toString('binary');

var decipher = crypto.createDecipheriv('aes-256-cbc', cryptkey, iv),
decoded = decipher.update(encryptdata);

decoded += decipher.final();
return decoded;
}

AESCrypt.encrypt = function(cryptkey, iv, cleardata) {
var encipher = crypto.createCipheriv('aes-256-cbc', cryptkey, iv),
encryptdata = encipher.update(cleardata);

encryptdata += encipher.final();
encode_encryptdata = new Buffer(encryptdata, 'binary').toString('base64');
return encode_encryptdata;
}

var cryptkey = crypto.createHash('sha256').update('Nixnogen').digest(),
iv = 'a2xhcgAAAAAAAAAA',
buf = "Here is some data for the encrypt", // 32 chars
enc = AESCrypt.encrypt(cryptkey, iv, buf);
var dec = AESCrypt.decrypt(cryptkey, iv, enc);

console.warn("encrypt length: ", enc.length);
console.warn("encrypt in Base64:", enc);
console.warn("decrypt all: " + dec);

回答by Justin Cloud

Ok, so there was a change to Crypto in the switch from 0.8 to 0.10 Crypto methods return Buffer objects by default, rather than binary-encoded strings

好的,所以在从 0.8 到 0.10 的切换中对 Crypto 进行了更改,默认情况下,Crypto 方法返回 Buffer 对象,而不是二进制编码的字符串

This means the above code needs to specify encodings.

这意味着上面的代码需要指定编码。

These four lines:

这四行:

decoded = decipher.update(encryptdata);
decoded += decipher.final();
encryptdata = encipher.update(cleardata);
encryptdata += encipher.final();

Are changed to:

改为:

decoded = decipher.update(encryptdata, 'binary', 'utf8');
decoded += decipher.final('utf8');
encryptdata = encipher.update(cleardata, 'utf8', 'binary');
encryptdata += encipher.final('binary');

This worked for me, but I am open to other suggestions.

这对我有用,但我愿意接受其他建议。

回答by loganfsmyth

As your answer states, those functions work with Buffers now unless you specify an encoding. That said, you'd be better off avoiding binaryencoded strings entirely and treat everything as Buffers until you strictly need a string for something. This way you can also use your encryption helpers to process non-text content.

正如您的回答所述,除非您指定编码,否则这些函数现在可以与 Buffers 一起使用。也就是说,您最好binary完全避免编码字符串并将所有内容视为缓冲区,直到您严格需要某个字符串为止。通过这种方式,您还可以使用加密助手来处理非文本内容。

var crypto = require('crypto');

var AESCrypt = {};

AESCrypt.decrypt = function(cryptkey, iv, encryptdata) {
    var decipher = crypto.createDecipheriv('aes-256-cbc', cryptkey, iv);
    return Buffer.concat([
        decipher.update(encryptdata),
        decipher.final()
    ]);
}

AESCrypt.encrypt = function(cryptkey, iv, cleardata) {
    var encipher = crypto.createCipheriv('aes-256-cbc', cryptkey, iv);
    return Buffer.concat([
        encipher.update(cleardata),
        encipher.final()
    ]);
}

var cryptkey = crypto.createHash('sha256').update('Nixnogen').digest(),
iv = new Buffer('a2xhcgAAAAAAAAAA'),
buf = new Buffer("Here is some data for the encrypt"), // 32 chars
enc = AESCrypt.encrypt(cryptkey, iv, buf);
var dec = AESCrypt.decrypt(cryptkey, iv, enc);

console.warn("encrypt length: ", enc.length);
console.warn("encrypt in Base64:", enc.toString('base64'));
console.warn("decrypt all: " + dec.toString('utf8'));

回答by Lanklaas

My issue was that the string I was passing to my decrypt function was empty. I built in a check for empty strings and I did not receive the message again.

我的问题是我传递给我的解密函数的字符串是空的。我内置了空字符串检查,但我没有再次收到该消息。

decrypt: function(text){
                if(text.length == 0){
                    return text;
                }
                return this.decipher.update(text, 'hex', 'utf8') + this.decipher.final('utf8');
            }