Node.js AES256 CBC 实施的问题

Issues with a Node.js implementation of AES256 CBC

首先让我说我是密码学的新手。我正在尝试在 Node.js.

中实施 Cipher Block Chaining Mode

我的问题是,在没有解密的情况下进行加密后,它会停止调用一个解密函数。这是我的代码:

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 电话上方的评论。我怎样才能确保 decrypt 功能一直有效?

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

您正在使用 Cipher-Block Chaining (CBC) 模式。其中加解密一个块(16字节)依赖于前一个块。分组密码是 pseudo-random 排列,这意味着只要您给它 16 个字节的数据,它就会始终加密或解密任何内容。

使用代码 console.log(decrypt(encrypt(data)));,您将加密两个块并将它们提供给解密。为下一个 updatefinal 调用记住最后一个被处理的密文块。

现在,当您调用 console.log((encrypt(data))); 时,您不会将密文传递给不知道下一个 console.log(decrypt(encrypt(data)));.

的中间密文块的解密函数

这是一个例子:

The last 16 entries are correct.

那是因为 CBC 不是 error-propagating 模式。您同时加密了两个块。由于decrypt的第二个密文块是完整的,所以可以正确解密。