HMAC в Web Crypto API используется как один из базовых механизмов
обеспечения целостности и аутентичности сообщений. Он основан на
симметричном ключе и криптографической хеш-функции, а в контексте
браузера реализуется через интерфейс SubtleCrypto,
доступный как crypto.subtle.
Метод subtle.sign выполняет вычисление цифровой подписи
или MAC (message authentication code) в зависимости от выбранного
алгоритма. В случае HMAC он не создает классическую асимметричную
подпись, а генерирует код аутентификации сообщения с использованием
общего секретного ключа.
В Web Crypto API HMAC реализуется как часть алгоритмов симметричной
криптографии. Ключевой элемент — объект CryptoKey, который
создается или импортируется заранее и используется как секретный
материал.
Основные характеристики HMAC в WebCrypto:
ArrayBufferАлгоритм задается объектом:
{
name: "HMAC",
hash: { name: "SHA-256" }
}
crypto.subtle.sign() применяется для вычисления
криптографического значения на основе входных данных и ключа.
Сигнатура метода:
crypto.subtle.sign(algorithm, key, data)
Параметры:
algorithm — объект с настройками HMACkey — объект CryptoKey с назначением
signdata — данные в виде ArrayBuffer,
TypedArray или DataViewВозвращаемое значение:
Promise<ArrayBuffer> — бинарная подписьПеред использованием subtle.sign необходимо создать
ключ.
const key = await crypto.subtle.generateKey(
{
name: "HMAC",
hash: { name: "SHA-256" }
},
false,
["sign", "verify"]
);
Параметры:
extractable: false — ключ нельзя экспортироватьkeyUsages — определяет допустимые операцииWeb Crypto API работает только с бинарными данными, поэтому строку необходимо преобразовать:
const encoder = new TextEncoder();
const data = encoder.encode("Сообщение для подписи");
TextEncoder преобразует строку в
Uint8Array, который совместим с
subtle.sign.
Основная операция вычисления HMAC:
const signature = await crypto.subtle.sign(
{
name: "HMAC"
},
key,
data
);
Результат — ArrayBuffer, содержащий бинарный MAC.
Для удобства часто преобразуют результат в hex:
const hashArray = Array.from(new Uint8Array(signature));
const hex = hashArray
.map(b => b.toString(16).padStart(2, "0"))
.join("");
HMAC в WebCrypto обычно используется вместе с проверкой:
const isValid = await crypto.subtle.verify(
{
name: "HMAC"
},
key,
signature,
data
);
Возвращаемое значение:
true — подпись корректнаfalse — данные или ключ измененыВ отличие от RSA или ECDSA, HMAC использует один и тот же ключ для подписи и проверки. Это упрощает реализацию, но требует безопасного хранения ключа.
HMAC не шифрует данные и не позволяет восстановить исходное сообщение. Он только подтверждает его целостность.
Выбор SHA-256, SHA-384 или SHA-512 влияет на:
SHA-256 является наиболее распространенным вариантом.
subtle.sign принимает несколько типов бинарных
данных:
const data = new Uint8Array([1, 2, 3, 4]);
const buffer = new ArrayBuffer(16);
const view = new DataView(buffer);
Во всех случаях данные интерпретируются как последовательность байтов.
Часто ключ не генерируется, а импортируется:
const rawKey = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8]);
const key = await crypto.subtle.importKey(
"raw",
rawKey,
{
name: "HMAC",
hash: { name: "SHA-256" }
},
false,
["sign", "verify"]
);
Импорт используется при:
Передача строки вместо бинарного массива приводит к ошибке. WebCrypto не выполняет автоматическое преобразование.
Ключ должен быть создан или импортирован с
usages: ["sign"]. Иначе вызов завершится исключением.
Алгоритм при вызове sign должен совпадать с алгоритмом
ключа.
const encoder = new TextEncoder();
const data = encoder.encode("auth message");
const key = await crypto.subtle.generateKey(
{
name: "HMAC",
hash: { name: "SHA-256" }
},
true,
["sign", "verify"]
);
const signature = await crypto.subtle.sign(
"HMAC",
key,
data
);
const isValid = await crypto.subtle.verify(
"HMAC",
key,
signature,
data
);
HMAC в Web Crypto API оптимизирован на уровне браузерной реализации и обычно работает быстрее, чем пользовательские реализации на JavaScript. Однако производительность зависит от:
Операции выполняются асинхронно, не блокируя UI.
HMAC считается криптографически стойким при соблюдении условий:
Web Crypto API обеспечивает:
extractable: false)До появления Web Crypto API HMAC часто реализовывался вручную на JavaScript. Это приводило к:
subtle.sign устраняет эти проблемы, так как: