Я собираюсь ответить на свой вопрос, когда я вошел в библиотечный код, чтобы узнать, что он на самом деле делает.
Резюме:
Ответ Вы можете использовать любой из двух методов, и он будет работать, как ожидалось:
1) Pass в случайном нонса 96 бит в длину и сама библиотека автоматически добавит 32-битный счетчик и увеличит его с каждым генерируемым блоком ключей. Например.
var nonce = CryptoJS.enc.Hex.parse('2301cd4ef785690a1b2c3dab'); // 12 Bytes
var encryption = CryptoJS.AES.encrypt(plaintext, key, { iv: nonce, mode: CryptoJS.mode.CTR, padding: CryptoJS.pad.NoPadding });
2) Pass в случайном нонса 96 битов в длину и явно указать 32 битный счетчик, а если вы хотите. Вы даже можете указать счетчик, например 00000009
, если вы хотите начать шифрование/дешифрование с 9-го блока. Ниже приведен пример, начиная с счетчика 0:
var nonce = '2301cd4ef785690a1b2c3dab'; // 12 Bytes
var counter = '00000000'; // 4 Bytes, start at counter 0
var nonceAndCounter = CryptoJS.enc.Hex.parse(nonce + counter); // 16 Bytes
var encryption = CryptoJS.AES.encrypt(plaintext, key, { iv: nonceAndCounter, mode: CryptoJS.mode.CTR, padding: CryptoJS.pad.NoPadding });
Пояснение:
Используя код в вопросе с 32 бит счетчика 00000000
, соответствующий код в этом файле mode-ctr.js:
/**
* Counter block mode.
*/
CryptoJS.mode.CTR = (function() {
var CTR = CryptoJS.lib.BlockCipherMode.extend();
var Encryptor = CTR.Encryptor = CTR.extend({
processBlock: function (words, offset) {
// Shortcuts
var cipher = this._cipher
var blockSize = cipher.blockSize;
var iv = this._iv;
var counter = this._counter;
// Generate keystream
if (iv) {
counter = this._counter = iv.slice(0);
// Remove IV for subsequent blocks
this._iv = undefined;
}
var keystream = counter.slice(0);
cipher.encryptBlock(keystream, 0);
// Increment counter
counter[blockSize - 1] = (counter[blockSize - 1] + 1) | 0
// Encrypt
for (var i = 0; i < blockSize; i++) {
words[offset + i] ^= keystream[i];
}
}
});
CTR.Decryptor = Encryptor;
return CTR;
}());
При запуске этого кода в браузере JS-отладчик, использующий точку останова, он преобразует nonceAndCounter
в WordArray cons ствовавшие 32 битовых элементов:
[587320654, -142251766, 455884203, 0]
Это используется для шифрования блока. Для шифрования следующего блока он запускает эту строку:
counter[blockSize - 1] = (counter[blockSize - 1] + 1) | 0
который оценивает взять counter[3]
элемент т.е. целое число 0 и увеличивает его:
[587320654, -142251766, 455884203, 1]
С последующими блоками и временными значениями I можно увидеть ...
[587320654, -142251766, 455884203, 2]
[587320654, -142251766, 455884203, 3]
[587320654, -142251766, 455884203, 4]
И так далее. Таким образом, похоже, что он работает правильно таким образом.
Сравните это с тем, как это работает, если вы передаете 128-битное случайное исключение, например.
var nonceAndCounter = CryptoJS.enc.Hex.parse('2301cd4ef785690a1b2c3dabdf99a9b3');
Это производит случайное слово из:
[587320654, -142251766, 455884203, -543577677, 0]
Так что создает 5 элементов массива !? Затем функция увеличивает четвертый элемент от -543577677
до -543577676
, затем -543577675
, затем -543577674
и так далее. Таким образом, он все еще работает в некотором роде, но не увеличивается так же хорошо, как начиная с 0 и, возможно, более подвержен ошибкам.
Когда я прошел только 96-разрядное случайное исключение, библиотека автоматически добавила счетчик начала как 0 в конец массива счетчиков и правильно увеличила его для последующих блоков. например
[587320654, -142251766, 455884203, 0]
[587320654, -142251766, 455884203, 1]
[587320654, -142251766, 455884203, 2]
Итак, вам явно не нужно устанавливать счетчик, потому что CryptoJS автоматически добавит его для вас. Вероятно, он проверяет, является ли последнее слово уже 0. Кроме того, режим CTR не имеет IV, он называется nonce. –
«Кроме того, режим CTR не имеет IV, он называется nonce». Отметил благодарности. «Таким образом, вам явно не нужно устанавливать счетчик, потому что CryptoJS автоматически добавит его для вас». Да, я протестировал это, просто передав 96-битное nonce, и он автоматически добавляет начальный счетчик как 0 в конец массива 'counter', например. '[587320654, -142251766, 455884203, 0]' и правильно его исправить. Большое спасибо за ответ Artjom. Извините, я пометил вас, потому что увидел, что ваше имя связано с рядом других ответов CryptoJS, и я подумал, что вы хорошо разбираетесь в библиотеке. – seatosum
Добавил резюме к началу, спасибо Artjom! – seatosum