HMAC

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

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

Как работает HMAC

  1. Отправитель вычисляет HMAC от сообщения и секретного ключа — получается строка фиксированной длины, например 64 шестнадцатеричных символа для HMAC-SHA256.
  2. Сообщение уходит вместе с этим кодом.
  3. Получатель сам вычисляет HMAC от полученного сообщения тем же ключом и сравнивает с присланным. Совпало — данные подлинные. Изменился хотя бы один символ сообщения — код получится совсем другим.

Посчитать HMAC можно одной командой:

echo -n "amount=1000&order=42" | openssl dgst -sha256 -hmac "secret-key"

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

Чем HMAC отличается от хеша и электронной подписи

  • Обычный хеш (например, SHA-256 файла) ключа не использует. Его может пересчитать кто угодно, поэтому он подтверждает только целостность: злоумышленник изменит данные и просто посчитает новый хеш.
  • HMAC требует секретного ключа, поэтому подделать код без ключа нельзя. Но ключ один на обе стороны: HMAC доказывает подлинность друг другу, а не третьему лицу.
  • Электронная подпись использует пару ключей: закрытым подписывают, открытым проверяет кто угодно. Отказаться от своей подписи нельзя, поэтому юридически значимые документы подписывают ею, в России — по ГОСТ.

Важно: HMAC не скрывает содержимое. Сообщение остается читаемым, и для конфиденциальности нужно шифрование — например, передача по TLS.

Где применяется

  • Подпись запросов к API. Клиент подписывает каждый запрос к REST API общим ключом — так устроена, например, подпись запросов в Amazon Web Services.
  • Уведомления (webhooks). Платежные сервисы и GitHub подписывают свои уведомления HMAC-SHA256, чтобы получатель отличил настоящие от поддельных.
  • Токены. JWT с алгоритмом HS256 подписан именно HMAC-SHA256.
  • Одноразовые коды. Шестизначные коды в приложениях-аутентификаторах (алгоритмы HOTP и TOTP) вычисляются через HMAC от общего секрета и счетчика или текущего времени.
  • Протоколы защиты связи. Внутри TLS функции на основе HMAC участвуют в выработке ключей шифрования.

При интеграции банковских систем с платежными и партнерскими сервисами проверка таких подписей — обязательная часть обмена данными.

Как использовать HMAC правильно

  • Ключ — длинный и случайный: для HMAC-SHA256 не короче 32 байт.
  • Ключ хранят в защищенном хранилище секретов, а не в коде и не в репозитории.
  • Коды сравнивают функцией постоянного времени (hmac.compare_digest в Python, hash_equals в PHP), иначе по времени ответа можно подобрать правильный код.
  • В подписываемые данные включают время или одноразовый номер запроса, чтобы перехваченное сообщение нельзя было отправить повторно.
  • Ключи периодически меняют, а при подозрении на утечку — сразу.