Конвертировать число в ArrayBuffer - PullRequest
2 голосов
/ 09 апреля 2019

Я пытаюсь расшифровать данные в браузере с помощью алгоритма AES-CTR. WebCrypto API требует, чтобы счетчик был передан как BufferSource .Как преобразовать счетчик (число) в ожидаемый ввод (байтовый массив)?

Я использую IV с нулевым значением, поэтому счетчик начинается с 0. Допустим, я пытаюсь расшифроватьdata where counter = 445566. Как мне преобразовать 445566 в ArrayBuffer?

const key = // retrieve decryption key
const encrypted = // retrieve encrypted data

const iv = new ArrayBuffer(16)
// iv is all zeros. I need it to represent 445566, how?

const algo = {
    name: 'AES-CTR',
    counter: iv,
    length: 128
}
const decrypted = await crypto.subtle.decrypt(algo, key, encrypted)

РЕДАКТИРОВАТЬ: После поиска некоторых крипто-библиотек, я в конечном итоге использовал это.Кажется, я делаю то, что хочу, но понятия не имею о правильности, производительности и т. Д.

function numberToArrayBuffer(value) {
    const view = new DataView(new ArrayBuffer(16))
    for (var index = 15; index >= 0; --index) {
      view.setUint8(index, value % 256)
      value = value >> 8;
    }
    return view.buffer
}

Ответы [ 2 ]

0 голосов
/ 09 апреля 2019

Вам ничего не нужно делать, ArrayBuffer инициализируется байтами, все со значением ноль, что, конечно, также представляет нулевое значение числа, используемое в статически неподписанном кодировании с прямым порядком байтов - что является распространенным способом представлениясчетчик в режиме CTR.

Вот описание возвращаемого значения ArrayBuffer только с указанным размером:

Новый ArrayBuffer объект указанного размера.Его содержимое инициализируется до 0.

, так что все готово, вы были готовы, не зная об этом.Единственное, что я, безусловно, хотел бы сделать, это прокомментировать , что счетчик в буфере был обнулен для следующего разработчика (который может фактически быть вами через пару лет).

Обратите внимание, что режим CTR безопасен, если счетчик никогда не повторяется для одного и того же ключа.Для этого одноразовый номер (который занимает неизвестное число байтов для левой руки , наиболее значимой стороны) обычно устанавливается в случайное значение, обычно путем простой инициализации первых 8 байтов случайными значениями.Так что для этого вам также не нужно ничего кодировать.

Вам нужно только кодировать одноразовый номер, если он состоит из 32- или 64-битного счетчика.

0 голосов
/ 09 апреля 2019

Не уверен, что это полезно.Но просто для перекрестной проверки подлинности кода.

Я написал несколько тестовых примеров, чтобы сначала преобразовать число в буфер массива и использовать значение буфера массива для его декодирования.

var hex = 445566..toString(16);
var buffer = new ArrayBuffer(16);
var dataView = new DataView(buffer);
dataView.setInt32(0, '0x'+ hex);
console.log(dataView.getInt32(0)); //445566


//Using the uint16array data generated by the above code 
var data = [0, 6, 204, 126, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
var buf = new ArrayBuffer(16);
var view = new DataView(buf);
data.forEach(function (b, i) {
    view.setUint8(i, b % 256);
});
var num = view.getInt32(0);
console.log(num);//445566


function numberToArrayBuffer(value) {
    const view = new DataView(new ArrayBuffer(16))
    for (var index = 15; index >= 0; --index) {
      view.setUint8(index, value % 256)
      value = value >> 8;
    }
    return view.buffer
}

console.log(numberToArrayBuffer(445566)) //  Uint8Array(16) [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 204, 126]

Оба результата одинаковы.Просто ваш код выдает результат в формате с прямым порядком байтов, а мой - в формате с прямым порядком байтов.

Таким образом, вы придерживались правильного подхода.Что касается производительности, я не думаю, что есть большое влияние

...