HMAC — это механизм формирования кода аутентификации сообщения на основе криптографической хеш-функции и секретного ключа. Его основная задача заключается не только в проверке целостности данных, но и в подтверждении их подлинности.
В отличие от обычных хеш-функций, которые являются публичными и не используют секретов, HMAC строится вокруг идеи наличия общего секретного ключа между двумя сторонами. Это делает невозможным подделку сообщения без знания ключа, даже если алгоритм хеширования полностью известен.
В основе HMAC лежит комбинация:
Формально HMAC можно выразить так:
HMAC(K, m) = H((K ⊕ opad) || H((K ⊕ ipad) || m))
где:
Конструкция HMAC использует два этапа хеширования:
Внутренний хеш: сообщение объединяется с ключом и внутренним паддингом
Внешний хеш: результат первого хеширования снова обрабатывается вместе с ключом и внешним паддингом
Такой подход решает несколько проблем:
Перед использованием ключ приводится к фиксированной длине, равной размеру блока хеш-функции:
Это обеспечивает корректную работу XOR-операций с ipad и opad.
Библиотека CryptoJS предоставляет готовую реализацию HMAC, скрывая все низкоуровневые операции.
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-512:
const hmac = CryptoJS.HmacSHA512(message, secretKey);
Чем сильнее базовая хеш-функция, тем выше криптографическая стойкость всего HMAC.
Внутри библиотеки процесс выглядит как последовательность операций над WordArray:
CryptoJS реализует HMAC как обёртку над базовыми хеш-алгоритмами, не дублируя их логику, а используя единый интерфейс трансформации данных.
HMAC обладает рядом криптографически важных свойств:
1. Устойчивость к коллизиям хеш-функции Даже если у базовой функции есть слабости, HMAC сохраняет устойчивость при корректной длине ключа.
2. Защита от подделки сообщений Без знания ключа невозможно сгенерировать корректный MAC.
3. Устойчивость к length extension атаке Обычные хеш-функции вроде SHA-256 уязвимы к таким атакам, но HMAC полностью их блокирует за счёт двойного хеширования.
4. Линейная зависимость от ключа и сообщения Любое изменение входных данных приводит к радикальному изменению результата.
HMAC применяется там, где требуется проверка подлинности данных:
Использование слабых ключей Короткие или предсказуемые ключи снижают стойкость всей схемы.
Повторное использование ключа в разных системах Это создаёт риск утечки через побочные каналы.
Использование MD5 без необходимости Даже в HMAC MD5 считается устаревшим для новых систем.
Сравнение строк без защиты от timing-атак При проверке HMAC важно использовать constant-time сравнение, иначе возможна утечка информации о ключе.
Обычный хеш:
H(message)
HMAC:
H(key + message + key)
Разница принципиальна:
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();
Такой подход позволяет обрабатывать потоковые данные без необходимости хранить всё сообщение в памяти целиком.