PBES2 и его параметры итераций

PBES2 в контексте JSON Web Encryption (JWE) в библиотеке jose используется как механизм ключевого шифрования на основе пароля. В отличие от асимметричных схем, где ключи основаны на паре публичный/приватный, PBES2 опирается на симметричный секрет — пароль, из которого с помощью функции деривации ключа (KDF) формируется ключ шифрования ключа контента.

PBES2 реализует комбинацию PBKDF2 (Password-Based Key Derivation Function 2) и HMAC для генерации ключа достаточной криптографической стойкости. Основная идея заключается в том, что пароль сам по себе не используется напрямую для шифрования, а преобразуется в ключ через многократные итерации хэширования.


В JWE PBES2 относится к алгоритмам alg (algorithms for key management). Примеры:

  • PBES2-HS256+A128KW
  • PBES2-HS384+A192KW
  • PBES2-HS512+A256KW

Структура имени:

  • PBES2 — базовый механизм (Password-Based Encryption Scheme 2)
  • HS256 / HS384 / HS512 — алгоритм HMAC для PBKDF2
  • A128KW / A192KW / A256KW — алгоритм обёртки ключа (AES Key Wrap)

Таким образом, PBES2 отвечает за получение KEK (Key Encryption Key), а AES-KW используется для обёртки CEK (Content Encryption Key).


Роль итераций PBKDF2

Ключевым параметром PBES2 является количество итераций PBKDF2.

Итерации определяют, сколько раз функция хэширования применяется при выводе ключа из пароля:

  • больше итераций → выше криптостойкость
  • больше итераций → выше нагрузка на CPU
  • меньше итераций → быстрее, но слабее защита

Формально PBKDF2:

= (P, S, c, )

где:

  • P — пароль
  • S — salt (соль)
  • c — количество итераций
  • dkLen — длина ключа

Значение параметра iterations в jose

В библиотеке jose параметр iterations задаётся через protected header или через опции при шифровании.

Пример:

import { compactEncrypt } from 'jose'

const encoder = new TextEncoder()

const jwe = await new compactEncrypt(
  encoder.encode('секретное сообщение')
)
  .setProtectedHeader({
    alg: 'PBES2-HS256+A128KW',
    enc: 'A256GCM'
  })
  .encrypt(password)

При этом библиотека автоматически генерирует:

  • salt
  • iteration count (если не задан)
  • derived key via PBKDF2

Контроль итераций

В jose можно явно управлять параметрами PBES2 через дополнительные настройки.

Ключевые параметры:

  • p2c — PBES2 Count (число итераций)
  • p2s — PBES2 Salt Input

Пример настройки:

import { CompactEncrypt } from 'jose'

const jwe = await new CompactEncrypt(
  new TextEncoder().encode('data')
)
  .setProtectedHeader({
    alg: 'PBES2-HS256+A128KW',
    enc: 'A256GCM',
    p2c: 200000,
    p2s: crypto.getRandomValues(new Uint8Array(16))
  })
  .encrypt(password)

Влияние p2c (iterations) на безопасность

PBES2 устойчивость напрямую зависит от параметра p2c.

Упрощённая зависимость:

c

где c — число итераций PBKDF2.

Однако рост безопасности не линейный в практическом смысле. Он ограничен:

  • вычислительной мощностью атакующего
  • возможностью GPU/ASIC атак
  • временем легитимной расшифровки

Практические диапазоны iterations

В современных реализациях обычно используются значения:

  • 10 000 — минимально допустимый уровень (устаревший)
  • 100 000 — базовый безопасный уровень
  • 300 000 – 600 000 — рекомендуемый баланс
  • 1 000 000+ — высокая безопасность, но заметная нагрузка

Внутренний процесс PBES2 в jose

Процесс шифрования выглядит следующим образом:

  1. Генерация случайного CEK (Content Encryption Key)

  2. Генерация salt (p2s)

  3. Применение PBKDF2:

    • вход: пароль + salt
    • итерации: p2c
    • HMAC: SHA-256/384/512
  4. Получение KEK (Key Encryption Key)

  5. Обёртка CEK через AES Key Wrap

  6. Шифрование данных CEK

  7. Формирование JWE структуры


Вычислительная стоимость итераций

PBKDF2 имеет линейную сложность по числу итераций:

T(c) = O(c)

где c — iterations.

Это означает, что увеличение итераций в 10 раз увеличивает время деривации примерно в 10 раз.


Ошибки при выборе iterations

Слишком низкое значение

  • ускоряет brute-force атаки
  • снижает устойчивость к GPU cracking
  • делает PBES2 формальностью без реальной защиты

Слишком высокое значение

  • задержка при каждом шифровании/дешифровании
  • нагрузка на сервер при массовых запросах
  • ухудшение UX в клиентских приложениях

Особенности реализации в jose

Библиотека jose:

  • автоматически генерирует p2s, если не задан
  • может использовать случайные значения iterations
  • поддерживает строгую проверку параметров при декодировании
  • валидирует alg соответствие PBES2

При декодировании:

import { compactDecrypt } from 'jose'

const { plaintext } = await compactDecrypt(jwe, password)

jose:

  • извлекает p2c и p2s из заголовка
  • повторяет PBKDF2 с теми же параметрами
  • сравнивает ключи и расшифровывает CEK

PBES2 и криптографическая модель угроз

PBES2 устойчив к:

  • словарным атакам при достаточном p2c
  • rainbow tables (из-за salt)
  • предварительно вычисленным хэшам

Но остаётся уязвимым к:

  • слабым паролям
  • утечке salt и ciphertext (что нормально по модели)
  • оффлайн перебору при низких iterations

Связь PBES2 с выбором HMAC

Алгоритм HMAC влияет на стойкость PBKDF2:

  • HS256 → быстрее, но менее устойчив к теоретическим атакам
  • HS512 → медленнее, но более криптостойкий

Влияние на вычисления:

T _{cost} c


Рекомендации по параметрам PBES2

Для современных приложений на jose обычно используется:

  • alg: PBES2-HS256+A256KW
  • iterations: 200 000 – 600 000
  • salt length: 16 bytes и выше
  • random generation через crypto.getRandomValues

При серверных нагрузках возможна адаптация:

  • динамическое снижение p2c для batch-операций
  • повышение p2c для пользовательских данных высокой важности

Итоговая модель PBES2 в jose

PBES2 можно рассматривать как композицию:

= (, , c) + +

где каждая часть отвечает за отдельный слой безопасности:

  • PBKDF2 — усиление пароля
  • AES-KW — защита ключа контента
  • JWE — структура и транспортировка зашифрованных данных