HMAC: теория и назначение

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


Механизм работы HMAC

HMAC строится на сочетании двух компонентов:

  • криптографической хеш-функции (например, SHA-256, SHA-1, SHA-512)
  • секретного ключа, известного только участникам обмена

Алгоритм использует два этапа хеширования с модифицированным ключом:

  1. Ключ приводится к фиксированной длине блока хеш-функции.
  2. Выполняется внутреннее хеширование данных.
  3. Результат объединяется с ключом и хешируется повторно.

Формально процесс можно представить как:

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

где:

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

Формальная конструкция и логика безопасности

Двойное хеширование не является случайным усложнением. Оно решает несколько криптографических проблем:

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

Хеш-функции вроде SHA-256 построены на итеративных конструкциях, что делает их уязвимыми при использовании без ключа. HMAC устраняет этот недостаток за счёт введения секретного контекста в обе стадии вычисления.


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

HMAC обладает набором характеристик, которые делают его стандартом де-факто в системах аутентификации сообщений:

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

Отличие от обычных хешей

Обычные хеш-функции (например, SHA-256) используются для проверки целостности данных, но не обеспечивают защиту от подделки:

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

HMAC добавляет секретный ключ, что приводит к следующим изменениям:

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

Области применения

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

  • API-аутентификация (подпись запросов)
  • токены доступа и сессии
  • TLS/SSL протоколы (внутренние механизмы)
  • проверка целостности сообщений в распределённых системах
  • цифровые подписи на основе симметричных ключей

Реализация HMAC в Jsrsasign

Библиотека Jsrsasign предоставляет криптографические функции через пространство имён KJUR.crypto. Для работы с HMAC используется объект Mac.

Основной принцип — указание алгоритма и секретного ключа, после чего вычисляется MAC (Message Authentication Code).


Пример использования HMAC-SHA256

const { KJUR } = require("jsrsasign");

const message = "data to protect";
const key = "secret_key";

const hmac = new KJUR.crypto.Mac({
  alg: "HmacSHA256",
  pass: key
});

hmac.updateString(message);
const result = hmac.doFinal();

console.log(result);

Результатом является шестнадцатеричная строка, представляющая криптографический код аутентификации.


Вычисление HMAC с SHA-1

const { KJUR } = require("jsrsasign");

const mac = new KJUR.crypto.Mac({
  alg: "HmacSHA1",
  pass: "my_secret"
});

mac.updateString("important message");
const hmacValue = mac.doFinal();

Несмотря на наличие SHA-1, в современных системах предпочтение отдаётся SHA-256 и выше из-за криптоаналитических уязвимостей SHA-1.


Обновление данных по частям

Jsrsasign поддерживает поэтапное добавление данных, что важно при работе с потоками:

const mac = new KJUR.crypto.Mac({
  alg: "HmacSHA256",
  pass: "key"
});

mac.updateString("part1 ");
mac.updateString("part2 ");
mac.updateString("part3");

const result = mac.doFinal();

Это позволяет вычислять HMAC без необходимости хранить всё сообщение в памяти целиком.


Частые ошибки при использовании HMAC

Одной из типичных ошибок является использование HMAC без криптографически стойкого ключа. Ключ должен обладать достаточной энтропией и не быть предсказуемым.

Другие ошибки включают:

  • повторное использование ключа в разных контекстах без разделения доменов
  • использование устаревших хеш-функций (MD5, SHA-1)
  • сравнение HMAC-значений через обычное ==, что может приводить к тайминговым атакам
  • хранение ключей в исходном коде

Сравнение алгоритмов HMAC в Jsrsasign

Алгоритм Уровень безопасности Рекомендация
HmacMD5 низкий не использовать
HmacSHA1 средний устаревший стандарт
HmacSHA256 высокий основной выбор
HmacSHA512 очень высокий предпочтителен для критичных систем

Внутренняя модель вычисления в библиотеке

Jsrsasign реализует HMAC через комбинацию стандартных хеш-алгоритмов и промежуточного буферного состояния. При этом:

  • ключ нормализуется под размер блока алгоритма
  • выполняется XOR с ipad и opad
  • используются внутренние реализации SHA, а не системные API
  • обеспечивается совместимость с криптографическими стандартами RFC 2104

Безопасность и криптографические особенности

HMAC остаётся устойчивым даже при частичном знании входных данных благодаря следующим свойствам:

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

С практической точки зрения безопасность определяется не только алгоритмом, но и качеством ключа и его управлением в системе.