Web Crypto API опирается на строгую работу с бинарными данными. Почти
все операции — от хеширования до шифрования — принимают и возвращают
значения в виде ArrayBuffer или представлений на его
основе. Это связано с тем, что криптография работает не со строками и
объектами высокого уровня, а с последовательностями байтов фиксированной
структуры.
ArrayBuffer представляет собой фиксированный блок памяти
без привязки к формату интерпретации. Он не содержит методов чтения или
записи данных напрямую — это только «сырой» контейнер.
const buffer = new ArrayBuffer(16); // 16 байт памяти
Сам по себе ArrayBuffer бесполезен без слоя
интерпретации. Именно для этого используются типизированные массивы.
TypedArray — это набор представлений над ArrayBuffer,
позволяющий интерпретировать бинарные данные как числа различных
типов.
Наиболее часто в Web Crypto используется:
Uint8Array — массив 8-битных беззнаковых чиселInt8ArrayUint32ArrayDataView — гибкий доступ к данным с контролем порядка
байтовconst buffer = new ArrayBuffer(4);
const view = new Uint8Array(buffer);
view[0] = 255;
view[1] = 16;
view[2] = 0;
view[3] = 128;
Uint8Array является де-факто стандартом для передачи
данных в Web Crypto API, поскольку криптографические алгоритмы оперируют
байтами.
Криптографические операции требуют строгого контроля над:
Строки в JavaScript не подходят для этих целей из-за:
Поэтому Web Crypto API использует только бинарные структуры:
ArrayBufferTypedArrayDataViewДля работы с текстом используется TextEncoder и
TextDecoder. Они обеспечивают предсказуемое преобразование
строк в байтовые массивы и обратно.
const encoder = new TextEncoder();
const data = encoder.encode("Hello");
console.log(data); // Uint8Array
Результатом является Uint8Array, который напрямую
совместим с Web Crypto API.
Обратное преобразование:
const decoder = new TextDecoder();
const text = decoder.decode(data);
Практически все методы crypto.subtle принимают
ArrayBuffer или TypedArray.
const encoder = new TextEncoder();
const data = encoder.encode("message");
const hashBuffer = await crypto.subtle.digest("SHA-256", data);
Результат digest — это ArrayBuffer,
содержащий 32 байта хеша.
Для дальнейшей работы его обычно преобразуют:
const hashArray = Array.from(new Uint8Array(hashBuffer));
Алгоритмы симметричного шифрования также используют бинарные данные.
const encoder = new TextEncoder();
const keyMaterial = encoder.encode("secret-key");
Генерация ключа:
const key = await crypto.subtle.importKey(
"raw",
keyMaterial,
{ name: "AES-GCM" },
false,
["encrypt", "decrypt"]
);
Шифрование:
const iv = crypto.getRandomValues(new Uint8Array(12));
const encrypted = await crypto.subtle.encrypt(
{
name: "AES-GCM",
iv
},
key,
encoder.encode("confidential data")
);
Здесь:
iv — Uint8ArrayUint8ArrayArrayBufferArrayBuffer не содержит методов доступа к данным,
поэтому всегда используется обёртка.
const buffer = new ArrayBuffer(8);
const view = new Uint8Array(buffer);
TypedArray не копирует данные, а создаёт представление
над той же областью памяти.
При работе с бинарными данными важно учитывать различие:
const original = new Uint8Array([1, 2, 3, 4]);
const sub = original.subarray(1, 3);
const copy = original.slice(1, 3);
subarray — создаёт новое представление без
копированияslice — создаёт копию данныхВ криптографических операциях предпочтителен subarray
для экономии памяти и повышения производительности.
Некоторые криптографические и низкоуровневые операции требуют контроля порядка байтов.
DataView позволяет явно задавать endianess:
const buffer = new ArrayBuffer(4);
const view = new DataView(buffer);
view.setUint16(0, 0x1234, true); // little-endian
view.setUint16(2, 0x1234, false); // big-endian
Это важно при реализации протоколов или совместимости с внешними системами.
Web Crypto API предоставляет криптографически стойкий генератор:
const bytes = new Uint8Array(16);
crypto.getRandomValues(bytes);
Результат — Uint8Array, который может использоваться как
IV, соль или ключевой материал.
Типичный поток данных выглядит следующим образом:
TextEncoder → Uint8ArrayUint8Array → crypto.subtle операцияArrayBufferArrayBuffer → Uint8ArrayTextDecoderconst a = new Uint8Array([1,2,3]);
const b = a.buffer;
b не является копией — это тот же буфер памяти.
crypto.subtle.digest("SHA-256", "text"); // ошибка
Строка недопустима — требуется ArrayBuffer или
TypedArray.
Web Crypto API спроектирован вокруг минимизации копирования данных. Использование:
subarrayArrayBufferпозволяет снизить нагрузку на GC и ускорить криптографические операции.
| Операция | Вход | Выход |
|---|---|---|
| digest | ArrayBuffer / TypedArray | ArrayBuffer |
| encrypt | ArrayBuffer / TypedArray | ArrayBuffer |
| decrypt | ArrayBuffer / TypedArray | ArrayBuffer |
| generateKey | параметры | CryptoKey |
Вся работа строится вокруг одной концепции:
любые данные → Uint8Array → ArrayBuffer → обратно Uint8Array
Эта модель обеспечивает: