Параметры HKDF: соль, info, хеш

HKDF (HMAC-based Extract-and-Expand Key Derivation Function) в Web Crypto API используется через SubtleCrypto.deriveKey или SubtleCrypto.deriveBits и представляет собой механизм получения криптографически стойких ключей из исходного материала.

В объекте алгоритма HKDF всегда задаются три ключевых параметра: salt, info, hash. Каждый из них влияет на безопасность, уникальность и контекст получаемого ключа.


Вызов выглядит через конфигурацию алгоритма:

{
  name: "HKDF",
  hash: "SHA-256",
  salt: Uint8Array,
  info: Uint8Array
}

Использование происходит в составе deriveKey:

const derivedKey = await crypto.subtle.deriveKey(
  {
    name: "HKDF",
    hash: "SHA-256",
    salt: saltBuffer,
    info: infoBuffer
  },
  baseKey,
  { name: "AES-GCM", length: 256 },
  false,
  ["encrypt", "decrypt"]
);

Соль (salt)

salt — случайное или псевдослучайное значение, которое добавляется на этапе «extract» в HKDF. Его задача — сделать результат деривации устойчивым к предвычислениям и атакам на основе словарей.

Ключевые свойства salt:

  • Должен быть уникальным для каждой деривации при одинаковом входном ключевом материале
  • Может быть публичным, не требует секретности
  • Существенно снижает риск повторного использования ключей
  • Рекомендуемая длина — равна длине выхода хеш-функции (например, 32 байта для SHA-256)

Пример создания salt:

const salt = crypto.getRandomValues(new Uint8Array(16));

Особенности:

  • Пустой salt допустим, но снижает криптостойкость
  • Повторное использование salt с тем же input key material приводит к одинаковым результатам HKDF
  • В системах с множеством пользователей salt часто привязывается к идентификатору сессии или контекста

info

info — контекстная строка или структура данных, используемая на этапе «expand». Этот параметр не влияет на стойкость напрямую, но критически важен для разделения ключей по назначению.

Роль info:

  • Связывает ключ с конкретным контекстом (например, «encryption», «authentication», «session-1»)
  • Обеспечивает domain separation
  • Предотвращает повторное использование ключей в разных протоколах
  • Позволяет безопасно получать разные ключи из одного и того же исходного материала

Требования:

  • Может быть пустым, но это не рекомендуется
  • Представляется как ArrayBuffer или TypedArray
  • Должен быть согласован между сторонами протокола

Пример:

const info = new TextEncoder().encode("chat encryption key");

Практические сценарии:

  • Разделение ключей: info = "encryption" и info = "integrity"
  • Привязка к сессии: info = "session-12345"
  • Привязка к роли: info = "client" / info = "server"

Даже при одинаковых salt и исходном ключе различие в info полностью меняет результат HKDF.


Хеш-функция (hash)

Параметр hash определяет криптографическую хеш-функцию, используемую внутри HKDF как HMAC-примитив.

Поддерживаемые значения:

  • "SHA-256"
  • "SHA-384"
  • "SHA-512"

Роль hash:

  • Используется на этапе extract (через HMAC)
  • Определяет стойкость и длину внутреннего состояния
  • Влияет на максимальную энтропию выходных ключей

Выбор алгоритма:

  • SHA-256 — стандартный выбор для большинства приложений
  • SHA-512 — используется при повышенных требованиях к стойкости
  • SHA-384 — компромисс между скоростью и безопасностью

Влияние на HKDF:

  • Чем сильнее хеш, тем выше криптографическая устойчивость
  • Длина выходного ключевого материала ограничена внутренним состоянием хеша
  • Изменение hash полностью меняет результат деривации даже при одинаковых salt и info

Взаимодействие salt, info и hash

Эти три параметра работают в разных этапах HKDF:

  • salt участвует в этапе extract (формирование псевдослучайного ключа)
  • hash определяет криптографический фундамент HMAC
  • info применяется на этапе expand для генерации контекстных ключей

Изменение любого параметра приводит к полностью другому результату:

  • одинаковый input key material + разный salt → разные ключи
  • одинаковый salt + разный info → разные ключи для разных назначений
  • одинаковые salt и info + разный hash → полностью несовместимые ключи

Типичные ошибки при использовании HKDF

Использование статического salt

const salt = new Uint8Array(16); // плохая практика

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


Игнорирование info

Отсутствие контекстной привязки приводит к ситуации, когда один и тот же ключ используется в разных целях:

info: new Uint8Array(0)

Это увеличивает риск повторного использования ключей в несовместимых протоколах.


Несогласованность hash между сторонами

Если одна сторона использует SHA-256, а другая SHA-512, результат HKDF будет несовместим, несмотря на совпадение всех остальных параметров.


Пример полного использования HKDF

const baseKey = await crypto.subtle.importKey(
  "raw",
  new TextEncoder().encode("master secret"),
  "HKDF",
  false,
  ["deriveKey"]
);

const salt = crypto.getRandomValues(new Uint8Array(16));
const info = new TextEncoder().encode("encryption key");

const key = await crypto.subtle.deriveKey(
  {
    name: "HKDF",
    hash: "SHA-256",
    salt,
    info
  },
  baseKey,
  {
    name: "AES-GCM",
    length: 256
  },
  false,
  ["encrypt", "decrypt"]
);

Особенности представления данных в Web Crypto API

Все параметры HKDF в Web Crypto API должны быть представлены в виде бинарных структур:

  • saltArrayBuffer или TypedArray
  • infoArrayBuffer или TypedArray
  • строки требуют явного кодирования через TextEncoder

Ошибки в кодировке часто приводят к несовместимости между клиентами, особенно при различиях в UTF-8 представлении строк.


Криптографическая роль параметров в модели безопасности

  • salt защищает от атак с предварительным вычислением
  • info обеспечивает разделение контекста и предотвращает повторное использование ключей
  • hash задаёт уровень криптографической стойкости и определяет фундамент алгоритма

Совместное использование этих параметров формирует из HKDF инструмент контролируемой и предсказуемой деривации ключей с жёсткой контекстной привязкой