Семейство HMAC: HS256, HS384, HS512

Семейство HMAC-алгоритмов в контексте JWT представляет собой один из наиболее распространённых способов симметричного подписывания токенов. В библиотеке jose эти алгоритмы реализуются через механизм JWS (JSON Web Signature) и включают три основных варианта: HS256, HS384 и HS512. Все они основаны на HMAC и различаются используемой хеш-функцией семейства SHA.


HMAC (Hash-based Message Authentication Code) представляет собой механизм, который использует криптографическую хеш-функцию вместе с секретным ключом для создания подписи сообщения. В отличие от асимметричных алгоритмов (RSA, ECDSA), здесь используется один общий секрет для подписи и проверки.

Ключевые свойства:

  • одинаковый секрет применяется для подписи и верификации
  • устойчивость зависит от криптографической стойкости хеш-функции
  • высокая производительность по сравнению с асимметричными алгоритмами
  • требует строгой защиты секрета

Общая формула HMAC:

HMAC(K, m) = H((K ⊕ opad) || H((K ⊕ ipad) || m))

где:

  • K — секретный ключ
  • m — сообщение
  • H — хеш-функция
  • opad, ipad — фиксированные паддинги

HS256: HMAC с SHA-256

HS256 использует SHA-256 как базовую хеш-функцию. Это наиболее распространённый вариант в JWT.

Особенности:

  • длина хеша: 256 бит
  • баланс между безопасностью и производительностью
  • стандарт де-факто для большинства веб-приложений

В jose алгоритм HS256 применяется через JWS API и требует передачи секретного ключа в виде Uint8Array.

Пример подписи JWT

import { SignJWT } from 'jose'

const secret = new TextEncoder().encode('super-secret-key')

const jwt = await new SignJWT({ userId: 123 })
  .setProtectedHeader({ alg: 'HS256' })
  .setIssuedAt()
  .setExpirationTime('2h')
  .sign(secret)

Проверка токена

import { jwtVerify } from 'jose'

const { payload } = await jwtVerify(token, secret, {
  algorithms: ['HS256']
})

HS256 часто выбирается как стандартный вариант, если нет строгих требований к криптостойкости выше среднего уровня.


HS384: HMAC с SHA-384

HS384 использует SHA-384 и обеспечивает более высокий уровень криптографической стойкости по сравнению с HS256.

Особенности:

  • длина хеша: 384 бит
  • более высокая устойчивость к теоретическим атакам перебора
  • чуть более медленная обработка по сравнению с HS256

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

Подпись JWT с HS384

import { SignJWT } from 'jose'

const secret = new TextEncoder().encode('another-secret')

const token = await new SignJWT({ role: 'admin' })
  .setProtectedHeader({ alg: 'HS384' })
  .setIssuedAt()
  .setExpirationTime('1h')
  .sign(secret)

Проверка

import { jwtVerify } from 'jose'

const { payload } = await jwtVerify(token, secret, {
  algorithms: ['HS384']
})

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


HS512: HMAC с SHA-512

HS512 использует SHA-512 и обеспечивает максимальную криптографическую стойкость в рамках HMAC-семейства JWT.

Особенности:

  • длина хеша: 512 бит
  • высокая устойчивость к криптоанализу
  • более высокая вычислительная стоимость
  • предпочтителен для чувствительных данных

Подпись JWT

import { SignJWT } from 'jose'

const secret = new TextEncoder().encode('ultra-secure-secret')

const token = await new SignJWT({ permissions: ['read', 'write'] })
  .setProtectedHeader({ alg: 'HS512' })
  .setIssuedAt()
  .setExpirationTime('15m')
  .sign(secret)

Проверка токена

import { jwtVerify } from 'jose'

const { payload } = await jwtVerify(token, secret, {
  algorithms: ['HS512']
})

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


Работа с секретными ключами в jose

Все HMAC-алгоритмы в jose требуют симметричный секрет. В отличие от строковых представлений в некоторых JWT-библиотеках, jose требует бинарного формата.

Формирование секрета

const secret = new TextEncoder().encode('my-super-secret')

Для production-систем часто используют криптографически стойкие ключи:

import { randomBytes } from 'crypto'

const secret = randomBytes(32)

Длина ключа должна соответствовать уровню выбранного алгоритма:

  • HS256: минимум 32 байта
  • HS384: минимум 48 байт
  • HS512: минимум 64 байта

Различия HS256, HS384 и HS512 в практическом применении

Производительность

  • HS256 — самый быстрый
  • HS384 — средний
  • HS512 — самый медленный

Разница становится заметной при высокой нагрузке (миллионы токенов).

Уровень безопасности

  • HS256: достаточен для большинства веб-приложений
  • HS384: повышенная устойчивость
  • HS512: максимальная стойкость в HMAC-классе

Размер подписи

  • HS256: 32 байта
  • HS384: 48 байт
  • HS512: 64 байта

Типичные ошибки при использовании HMAC в jose

1. Использование строк вместо Uint8Array

// неправильно
const secret = 'my-secret'

// правильно
const secret = new TextEncoder().encode('my-secret')

2. Повторное использование слабых секретов

Секреты вида:

  • “123456”
  • “secret”
  • “password”

делают JWT уязвимым независимо от выбранного алгоритма.


3. Несоответствие алгоритма при проверке

await jwtVerify(token, secret, {
  algorithms: ['HS256'] // обязательно фиксировать допустимые алгоритмы
})

Отсутствие ограничения алгоритмов может привести к атакам типа alg confusion в старых реализациях.


4. Хранение секрета в коде

Секрет должен храниться вне исходного кода:

  • переменные окружения
  • secret vault
  • KMS системы

Рекомендации по выбору алгоритма

  • HS256 — стандартный выбор для API и веб-сервисов
  • HS384 — системы с повышенными требованиями к защите токенов
  • HS512 — высокозащищённые среды, финансовые и критические системы

При этом переход на HS512 не всегда оправдан, если архитектура или инфраструктура ограничивает производительность.


Поведение jose при обработке HMAC

Библиотека jose строго проверяет:

  • соответствие алгоритма заголовку JWT
  • корректность ключа (тип и длина не валидируются жёстко, но влияют на безопасность)
  • допустимость алгоритма в параметрах verify

Это снижает риск некорректной конфигурации по сравнению с более “свободными” библиотеками.


Совместимость с JWS стандартом

HS256, HS384 и HS512 являются частью стандарта JWA (JSON Web Algorithms) и полностью совместимы с:

  • RFC 7518
  • JWT (RFC 7519)
  • JWS (RFC 7515)

Это обеспечивает переносимость между различными реализациями, включая Node.js, браузерные окружения и серверные платформы.


Итоговая практическая картина использования

В экосистеме JavaScript HMAC-алгоритмы через jose формируют базовый уровень криптографической защиты JWT. Их выбор определяется компромиссом между:

  • скоростью обработки
  • длиной и стойкостью хеша
  • требованиями к безопасности системы
  • управлением секретами

HS256 остаётся наиболее универсальным вариантом, HS384 используется в усиленных сценариях, HS512 применяется в системах с максимальными требованиями к криптостойкости симметричной схемы подписи.