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

Posted

技术标签:

【中文标题】使用 node.js 解密 AES256 返回错误的最终块长度【英文标题】:Decrypting AES256 with node.js returns wrong final block length 【发布时间】:2014-02-13 01:18:52 【问题描述】:

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

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

这是来自 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);

【问题讨论】:

我也面临着类似的问题。看看这个***.com/questions/32038267/… 这里有一些类似的问题和答案:Nodejs decrypt using crypto error wrong final block length、Getting error wrong final block length while decrypting AES256、Decrypt file in Node.js encrypted using OpenSSL、How to decipher string in node.js which is encrypted in crypto.js、What's wrong with node.js crypto decipher? 它对我有帮助 decipher.setAutoPadding(false); 默认情况下,节点使用 PKCS 填充,但其他语言 C++,Python 不使用此填充。 【参考方案1】:

好的,所以在从 0.8 到 0.10 Crypto methods return Buffer objects by default, rather than binary-encoded strings的切换中对 Crypto 进行了更改@

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

这四行:

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

改为:

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

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

【讨论】:

老兄,你为我节省了很多时间。像魅力一样工作! 我遇到了同样的错误,但我正在使用管道(将解密变量传递给文件上的pipe)以避免需要将整个文件放在内存中的问题。知道在这种情况下该怎么做吗? 我们在 package.json 中没有“engines”属性的 Heroku 应用程序中遇到了这个问题。该版本已在部署时更新,但我们没有发现问题。谢谢! @Michael 我在使用管道时也面临同样的问题......任何解决方案?? 你能帮帮我吗[***.com/questions/52550132/…【参考方案2】:

正如您的回答所述,除非您指定编码,否则这些函数现在可以与缓冲区一起使用。也就是说,您最好完全避免使用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'));

【讨论】:

我也面临着类似的问题。 ***.com/questions/32038267/…看一看,提出宝贵意见 是否可以对不同文件中的同一个字段进行加解密?我不断收到此错误Error: error:0606506D:digital envelope routines:EVP_DecryptFinal_ex:wrong final block length @kd12345 请发布一个新问题。 @loganfsmyth 你去***.com/questions/66476111/…【参考方案3】:

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

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

【讨论】:

以上是关于使用 node.js 解密 AES256 返回错误的最终块长度的主要内容,如果未能解决你的问题,请参考以下文章

符合Good Node JS AES标准的Encrypt Decrypt模块

使用 Java 的 AES-256-GCM 解密中的标签不匹配错误

如何使用 JavaScript 在浏览器中加密数据并使用 Node.js 在服务器端解密

使用 JavaScript BigQuery UDF 解密/解码 AES256 [重复]

从Java中的node.js解密字符串?

在 Node JS TLS 中添加/启用从 SSLv3 (DHE-RSA-AES256-SHA) 到 TLS 1.2 的密码