Принцип работы HMAC

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

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


Базовая идея HMAC

В основе HMAC лежит комбинация:

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

Формально HMAC можно выразить так:

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

где:

  • K — секретный ключ
  • m — сообщение
  • H — хеш-функция
  • — операция XOR
  • || — конкатенация
  • ipad — внутренний паддинг (0x36 повторённый блоками)
  • opad — внешний паддинг (0x5c повторённый блоками)

Причина использования двойного хеширования

Конструкция HMAC использует два этапа хеширования:

  1. Внутренний хеш: сообщение объединяется с ключом и внутренним паддингом

  2. Внешний хеш: результат первого хеширования снова обрабатывается вместе с ключом и внешним паддингом

Такой подход решает несколько проблем:

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

Подготовка ключа

Перед использованием ключ приводится к фиксированной длине, равной размеру блока хеш-функции:

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

Это обеспечивает корректную работу XOR-операций с ipad и opad.


Алгоритм работы HMAC по шагам

  1. Приведение ключа к размеру блока
  2. XOR ключа с ipad
  3. Конкатенация результата с сообщением
  4. Хеширование результата
  5. XOR ключа с opad
  6. Конкатенация с результатом шага 4
  7. Финальное хеширование

Практическая реализация в CryptoJS

Библиотека CryptoJS предоставляет готовую реализацию HMAC, скрывая все низкоуровневые операции.

Пример с SHA-256

import CryptoJS from "crypto-js";

const secretKey = "super_secret_key";
const message = "transfer:1000:to:user42";

const hmac = CryptoJS.HmacSHA256(message, secretKey);

console.log(hmac.toString(CryptoJS.enc.Hex));

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


Использование разных хеш-функций

HMAC в CryptoJS не привязан к конкретному алгоритму. Поддерживаются:

  • SHA-1
  • SHA-256
  • SHA-512
  • MD5 (не рекомендуется в современных системах)

Пример с SHA-512:

const hmac = CryptoJS.HmacSHA512(message, secretKey);

Чем сильнее базовая хеш-функция, тем выше криптографическая стойкость всего HMAC.


Внутреннее устройство CryptoJS HMAC

Внутри библиотеки процесс выглядит как последовательность операций над WordArray:

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

CryptoJS реализует HMAC как обёртку над базовыми хеш-алгоритмами, не дублируя их логику, а используя единый интерфейс трансформации данных.


Безопасность и свойства HMAC

HMAC обладает рядом криптографически важных свойств:

1. Устойчивость к коллизиям хеш-функции Даже если у базовой функции есть слабости, HMAC сохраняет устойчивость при корректной длине ключа.

2. Защита от подделки сообщений Без знания ключа невозможно сгенерировать корректный MAC.

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

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


Типовые сценарии использования

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

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

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

Использование слабых ключей Короткие или предсказуемые ключи снижают стойкость всей схемы.

Повторное использование ключа в разных системах Это создаёт риск утечки через побочные каналы.

Использование MD5 без необходимости Даже в HMAC MD5 считается устаревшим для новых систем.

Сравнение строк без защиты от timing-атак При проверке HMAC важно использовать constant-time сравнение, иначе возможна утечка информации о ключе.


Сравнение HMAC с обычным хешированием

Обычный хеш:

H(message)

HMAC:

H(key + message + key)

Разница принципиальна:

  • хеширование → только целостность данных
  • HMAC → целостность + аутентификация

Представление результата в CryptoJS

CryptoJS возвращает результат в виде объекта WordArray, который можно конвертировать в разные форматы:

hmac.toString(CryptoJS.enc.Hex)
hmac.toString(CryptoJS.enc.Base64)

Выбор формата зависит от протокола передачи данных.


Взаимодействие с потоковыми данными

HMAC поддерживает работу с большими данными через последовательное обновление состояния:

const hmac = CryptoJS.algo.HMAC.create(CryptoJS.algo.SHA256, secretKey);

hmac.update("part1");
hmac.update("part2");

const result = hmac.finalize().toString();

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