1

首先让我说我对密码学很陌生。我正在尝试在 Node.js中实现密码块链接模式。

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

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功能始终有效?

4

1 回答 1

1

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

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

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

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

这是一个插图:

在此处输入图像描述

最后 16 个条目是正确的。

那是因为 CBC 不是错误传播模式。您同时加密了两个块。由于第二个密文块decrypt是完整的,所以会正确解密。

于 2016-01-27T09:32:01.253 回答