Все статьи

HMAC: чем хеш с ключом отличается от обычного хеша

Российские платёжные сервисы вроде ЮKassa и CloudPayments подписывают уведомления о платежах (вебхуки) именно через HMAC-SHA256: интернет-магазин при регистрации получает секретный ключ, а каждое входящее уведомление сопровождается подписью, которую нужно пересчитать локально и сравнить с присланной. Если подпись не совпадает — уведомление не от платёжного сервиса, а значит, доверять ему нельзя.

Зачем нужен именно секретный ключ, а не просто хеш

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

Почему это не просто "хеш от ключа плюс сообщение"

Наивная склейка hash(key + message) уязвима к атакам удлинения сообщения для некоторых хеш-функций — злоумышленник может дописать данные к сообщению и вычислить новый валидный хеш, даже не зная ключа целиком. HMAC использует специальную конструкцию с двойным хешированием и внутренним/внешним падингом, защищённую от этого класса атак.

Где ещё встречается HMAC

Кроме подписи вебхуков, HMAC используется для аутентификации API-запросов (когда сам ключ не передаётся по сети, только подпись), а также лежит в основе алгоритма TOTP — того самого, что генерирует шестизначные коды в приложениях-аутентификаторах.

Зачем это нужно

  • Проверять подлинность вебхуков от платёжных и других сторонних сервисов.
  • Подписывать API-запросы без передачи самого секретного ключа по сети.
  • Понимать внутреннюю механику TOTP-кодов и токенов сессий.

Сравнение за постоянное время

Сравнивать полученную подпись с ожидаемой обычным === опасно: такой оператор обычно останавливается на первом расхождении, и время сравнения выдаёт злоумышленнику, сколько первых байт подписи он подобрал верно. Надёжный код обработки вебхуков всегда использует функции сравнения за постоянное время — например, hash_equals в PHP, — которые проверяют все байты независимо от того, где встретилось первое несовпадение.

Попробовать инструмент