有关AES256 CBC的Node.js实现的问题

让我开始说我对密码学非常陌生。 我试图在Node.js中实现密码块链模式 。

我的问题是,在没有解密的encryption之后,它停止工作一个解密函数调用。 这是我的代码:

var crypto = require('crypto'); var encryptionMethod = 'aes-256-cbc'; var vector = new Buffer([0xF1, 0x4C, 0xB6, 0xBD, 0x82, 0x93, 0x3C, 0x97, 0x6A, 0x4B, 0x4A, 0xD2, 0xAD, 0xD5, 0xA8, 0x6D]); var key = new Buffer([59, 92, 128, 239, 136, 26, 19, 26, 226, 234, 53, 71, 157, 113, 209, 96, 111, 83, 167, 123, 217, 107, 124, 31, 238, 176, 58, 110, 161, 82, 81, 69]); var cipher = crypto.createCipheriv(encryptionMethod, key, vector); cipher.setAutoPadding(false); var decipher = crypto.createDecipheriv(encryptionMethod, key, vector); decipher.setAutoPadding(false); var encrypt = function(array) { return cipher.update(new Buffer(array)); }; var decrypt = function(buffer) { return decipher.update(buffer); }; var data = []; for (var i = 0; i < 32; i++) { data.push(i); } // no problem here (probably because the vector updates itself?) console.log(decrypt(encrypt(data))); // <Buffer 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f> console.log(decrypt(encrypt(data))); // <Buffer 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f> console.log(decrypt(encrypt(data))); // <Buffer 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f> // after one encryption without a decryption it stops working. console.log((encrypt(data))); // why can't this be decrypted correctly? The last 16 entries are correct. console.log(decrypt(encrypt(data))); // <Buffer e2 df 50 63 c7 eb 06 4c 28 19 6d 04 41 bd c0 db 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f> // expected result console.log(decrypt(encrypt(data))); // <Buffer 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f> 

请参阅console.log调用上面的注释以获取更多信息。 我怎样才能确保decryptfunction始终工作?

TL; DR:这是预期的行为。

您正在使用密码块链接(CBC)模式。 其中一个块(16字节)的encryption和解密取决于前一个块。 分组密码是一个伪随机排列,这意味着只要你给它16个字节的数据,它总是会encryption或解密任何东西。

用代码console.log(decrypt(encrypt(data))); 你正在encryption两个块,并给他们解密。 最后一个被处理的密文块被记住下次updatefinal呼叫。

现在,当你调用console.log((encrypt(data))); ,则不会将密文传递给不知道下一个console.log(decrypt(encrypt(data)));的中间密文块的解密函数console.log(decrypt(encrypt(data)));

这是一个例子:

在这里输入图像描述

最后的16个条目是正确的。

这是因为CBC不是错误传播模式。 你已经在同一时间encryption两个块。 由于decrypt的第二密文块是完整的,它将正确解密。