Кратко

  • Соль HKDF обычно не является секретом. Она может усилить независимость извлечения, но не создаёт недостающую энтропию, не аутентифицирует исходный материал и не замедляет перебор паролей.
  • Параметр info действует на стадии Expand и связывает результат с протоколом, версией, ролью или назначением. Для проверки нужны отдельные сведения о происхождении IKM и соли, точной кодировке контекста и жизненном цикле результата.

Одинаковый результат доказывает не всё

Клиент и сервер получили одинаковые 32 байта. Тест совместимости пройден, и в отчёте появляется фраза «выработка ключей подтверждена». Но если в вычисление не вошло различие между ключом шифрования, IV и ключом защиты заголовка, совпадение доказывает лишь одинаковость операции. Оно не доказывает назначение результата.

HKDF устраняет эту неясность архитектурно. Сначала из исходного ключевого материала получается псевдослучайный промежуточный ключ. Затем из него выводятся значения для конкретных задач. Hugo Krawczyk дал формальное обоснование такой конструкции, а RFC 5869 он написал совместно с Pasi Eronen. Его профиль IETF также связывает его с RFC 2104 о HMAC — основе HKDF. Сборник наград ACM за 2025 год отмечает вклад Krawczyk в теорию и практические протоколы защищённой связи.

Эти сведения нужны не для героической биографии. Они показывают путь одной инженерной границы в современные протоколы: промежуточный секрет ещё не является ключом с разрешённой функцией.

Extract концентрирует, но не создаёт

Первая стадия HKDF вычисляет:

PRK = HMAC-Hash(salt, IKM)

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

Возможность пропустить Extract зависит от класса входа. Хороший псевдослучайный ключ в некоторых приложениях можно передать прямо в Expand. Общее значение Diffie–Hellman таким входом автоматически не считается: RFC 5869 рекомендует не пропускать извлечение, потому что представление этого значения не является равномерным ключом HMAC.

NIST SP 800-56C Rev. 2 тоже различает извлечение, расширение и извлечение с последующим расширением в методах установления ключей. Разделение стадий — не оформление API, а способ зафиксировать, какое предположение об источнике уже выполнено до назначения результата алгоритму.

Публичный — не значит выбранный атакующим

RFC 5869 определяет соль как необязательное несекретное случайное значение. При отсутствии используется нулевая строка длиной в выход хеш-функции. Протокол может передать соль открыто, получить её из аутентифицированных публичных nonce или использовать фиксированное значение, если это допускает модель.

Польза соли не основана на сокрытии. Она может разделять применения хеш-функции, поддерживать извлечение, менее зависимое от конкретного источника, и усиливать условия анализа. Однако соль должна быть независима от IKM. Если стороны вносят значения для её построения, протокол обязан не дать противнику незаметно выбрать их.

Поэтому метрики salt=yes недостаточно. Следует различать отсутствие и нулевое значение по умолчанию, постоянную соль версии протокола, свежую аутентифицированную публичную соль и значение под внешним контролем. Они могут быть одинаково видимыми, но обосновывают разную уверенность.

RFC 8188 показывает разницу в шифрованном кодировании HTTP-контента. Передаваемая соль поступает в HKDF-Extract, а фиксированная строка с названием кодирования — в info для Expand. Оба параметра открыты, потому что различает их не секретность, а роль в доказательстве.

Парольной соли нужна цена попытки

Уникальная соль при хранении паролей мешает повторно использовать предвычисленные таблицы для многих учётных записей и разводит одинаковые пароли. Но небольшое пространство человеческого выбора сохраняется. Для защиты от автономного перебора каждая попытка должна намеренно требовать времени или памяти.

В HKDF нет коэффициента работы и memory-hard стадии. RFC 5869 прямо говорит: Extract может концентрировать имеющуюся энтропию, но не усиливает её, а механизм замедления для паролей в схему не входит. PBKDF2 принимает число итераций. Argon2 задаёт затраты памяти, число проходов и параллелизм. Они тоже не превращают слабый пароль в сильный секрет, но повышают цену проверки словаря — в отличие от одного быстрого вызова HKDF.

Фраза «мы добавили соль» поэтому ничего не завершает. Нужно выяснить, какая конструкция получила соль, к какому классу относится исходный материал, сколько стоит одна догадка, требовалась ли уникальность или независимость и какой компонент это обеспечивал.

info назначает ключ на должность

HKDF-Expand получает PRK, info и длину. В info могут входить номер протокола, алгоритм, идентичность, роль или длина. Параметр связывает результат с приложением и контекстом, не позволяя одинаковому IKM незаметно породить материал для разных доменов.

Соль не заменяет эту связь. RFC 5869 не рекомендует выдавать PRK как финальный результат даже при подходящей длине, поскольку тогда обходится info. Переносить контекст в Extract вместо этого тоже не рекомендуется. PRK — общий промежуточный секрет, а не готовый ключ отправки, IV или экспортный секрет.

TLS 1.3 превращает правило в формат данных. HKDF-Expand-Label добавляет префикс tls13 , метку и контекст, который может включать хеш транскрипта рукопожатия. Названия finished, key и iv реально входят в криптографическое вычисление.

QUIC использует quic key, quic iv и quic hp для ключа AEAD, вектора инициализации и защиты заголовка. RFC 9001 указывает, что эти метки также разделяют домены QUIC и TLS. Запись «HKDF-SHA256 успешно» выбрасывает свидетельство о назначении байтов.

HPKE вводит в LabeledExtract и LabeledExpand строку HPKE-v1, идентификатор набора алгоритмов и функциональную метку. Так секрет связывается со схемой, версией и suite. MLS использует собственный префикс MLS 1.0 и расписание отдельных секретов для эпохи группы. Читаемая надпись сама по себе не создаёт границу: все реализации должны однозначно кодировать поля и проверять версию и набор алгоритмов.

Четыре квитанции вывода ключа

Первая — происхождение IKM. Аутентифицированный Diffie–Hellman, случайный ключ, заранее общий секрет, пароль и результат другой KDF могут совпадать по длине, но иметь разные свойства энтропии и контроля противника.

Вторая — происхождение соли: правило генерации, версия, состояние аутентификации, политика повторения и основание независимости от IKM. Несекретность описывает конфиденциальность, но не целостность источника.

Третья — закодированный контекст. Следует хранить несекретный отпечаток фактических префикса, версии, suite, метки, направления, хеша транскрипта и длины. Удобное имя в интерфейсе не обнаружит двусмысленную конкатенацию или различия кодировок.

Четвёртая — хранение результата. Нужно назвать ключ, IV, PRK, экспортный или возобновляющий секрет, допустимые операции, эпоху и момент удаления. Правильная KDF не исправляет повтор nonce и сохранение старого ключа.

Только эти четыре квитанции задают верный масштаб совпадению результатов. Оно подтверждает совместимую операцию, но не аутентификацию стороны, качество источника, верность назначения или уничтожение прежнего секрета.

Источники