Очевидная идея, которая проваливается
Вы хотите доказать, что сообщение исходит от того, кто владеет общим секретом, и что оно не изменено. Интуитивный подход — хешировать секрет вместе с сообщением: tag = SHA256(секрет + сообщение). Это кажется надёжным: метка зависит от секрета, так что атакующий, не знающий секрета, не может её произвести. К сожалению, для самых распространённых хеш-функций эта конструкция взломана.
Атака расширения длины
Хеши семейства Меркла-Дамгарда, включающего , -1 и SHA-256, обрабатывают ввод блоками и несут внутреннее состояние. Их конечный вывод и есть это внутреннее состояние. Это утекает нечто опасное: по SHA256(секрет + сообщение) и длине секрет + сообщение атакующий может задать внутреннее состояние хеша равным вашей метке и продолжить хеширование, вычислив
SHA256(секрет + сообщение + заполнение + данные_атакующего)
как действительную метку для расширенного сообщения, так и не зная секрета. Он может дописать данные и произвести метку, которая пройдёт проверку. Для API, где сообщение — это набор подписанных параметров, это может означать дописывание &admin=true к запросу с прохождением проверки подписи. Наивное hash(секрет + сообщение) небезопасно.
Как HMAC это исправляет
(RFC 2104) не просто конкатенирует. Он хеширует дважды, подмешивая ключ двумя разными способами:
HMAC(K, m) = H( (K ⊕ opad) || H( (K ⊕ ipad) || m ) )
Сообщение хешируется с ключом под внутренним заполнением (ipad), а этот результат хешируется снова с ключом под внешним заполнением (opad). Поскольку внешний хеш оборачивает внутренний, значение, которое видит атакующий, — не сырое внутреннее состояние, которое он мог бы расширить; это вывод второго шага хеширования с ключом секрета. Расширение длины перестаёт работать, и у безопасности HMAC есть надёжное доказательство, опирающееся лишь на разумность базового хеша.
Поэтому каждая зрелая система использует HMAC (или другой подходящий MAC) вместо самодельного хеширования с ключом. Заметьте, что SHA-3 и BLAKE не подвержены расширению длины, поэтому могут снабжаться ключом более прямо, но HMAC остаётся переносимым и широко поддерживаемым стандартом.
Урок
Используйте HMAC с сильным хешем (HMAC-SHA256 — обычный выбор по умолчанию) и секретом высокой энтропии. Не изобретайте собственную схему хеширования с ключом: изъян не очевиден снаружи, что как раз и делает его опасным.
Инструмент HMAC вычисляет HMAC-SHA256 и связанные варианты по сообщению и ключу, чтобы вы увидели метку и сравнили её, всё в вашем браузере, без отправки чего-либо.