Хранение параметров деривации вместе с шифртекстом

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

Функция sjcl.encrypt(password, data) возвращает JSON-строку, внутри которой находятся как криптографические параметры, так и сам зашифрованный текст. Типичная структура выглядит следующим образом:

  • iv — вектор инициализации
  • salt — криптографическая соль
  • iter — количество итераций KDF
  • ks — размер ключа (в битах)
  • ts — размер тега аутентификации
  • mode — режим шифрования (обычно ccm)
  • adata — дополнительные аутентифицированные данные
  • cipher — используемый алгоритм (обычно aes)
  • ct — ciphertext (зашифрованные данные)

Параметры деривации ключа напрямую связаны с iter, salt и ks. Именно их наличие позволяет восстановить ключ без внешних конфигураций.

Роль salt и невозможность предвычисления

salt генерируется случайным образом при каждом шифровании и служит для защиты от атак с использованием радужных таблиц. В контексте PBKDF2 (основной KDF в SJCL) соль вводит уникальность даже при повторяющихся паролях.

Ключевой принцип заключается в том, что одинаковый пароль при разных salt всегда даёт разные производные ключи:

K = (P, S, iter, ks)

где:

  • ( P ) — пароль
  • ( S ) — salt
  • ( iter ) — число итераций
  • ( ks ) — размер ключа

Хранение iter как защита от устаревания параметров

Параметр iter играет критическую роль в адаптации стойкости системы к вычислительным возможностям атакующего. Его сохранение вместе с шифртекстом решает проблему эволюции безопасности.

Если бы значение итераций задавалось глобально в приложении, изменение политики безопасности приводило бы к невозможности расшифровать старые данные или необходимости поддерживать несколько конфигураций. Встроенное хранение решает эту проблему:

  • старые сообщения используют старое число итераций
  • новые сообщения автоматически усиливаются без миграции данных
  • расшифровка всегда использует параметры, с которыми создавался шифртекст

Связь ks и совместимость форматов

Поле ks (key size) фиксирует длину ключа, используемого алгоритмом AES. SJCL поддерживает различные варианты (128, 192, 256 бит), и хранение этого параметра необходимо для корректной интерпретации битовой длины результата KDF.

Без ks восстановление ключа было бы неоднозначным: один и тот же пароль и salt могут использоваться для разных уровней криптостойкости.

Инкапсуляция KDF как часть формата сообщения

В SJCL криптографический формат фактически самодокументируем:

  • все параметры KDF включены в JSON
  • алгоритм восстановления ключа однозначно определяется полями
  • приложение не хранит внешнего состояния криптоконфигурации

Это приближает формат к принципу «ciphertext carries its own environment».

Такая модель особенно важна для распределённых систем, где:

  • шифрование выполняется на клиенте
  • расшифрование происходит в другом сервисе
  • версии библиотек могут отличаться

Проблема миграции параметров

Со временем параметры KDF неизбежно устаревают. Например, значение iter, достаточное в момент шифрования, может стать недостаточным через несколько лет.

Так как параметры встроены в шифртекст, обновление политики безопасности не требует изменения уже сохранённых данных. Вместо этого применяется стратегия:

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

Таким образом достигается постепенная миграция без массовой перекодировки хранилищ.

Безопасность хранения параметров KDF

Сами по себе параметры salt, iter и ks не являются секретными. Их раскрытие не снижает криптографическую стойкость при условии использования стойкого пароля.

  • salt должен быть уникальным, но не секретным
  • iter определяет стоимость атаки, но не раскрывает пароль
  • ks фиксирует размер ключа, но не влияет на энтропию

Секретом остаётся только пароль, из которого строится ключ.

Формирование полного пакета шифртекста

При вызове sjcl.encrypt происходит следующая последовательность:

  1. Генерация случайного salt
  2. Применение PBKDF2 для получения ключа
  3. Генерация iv
  4. Шифрование данных в режиме CCM
  5. Формирование аутентификационного тега
  6. Сериализация всех параметров в JSON

Итоговый объект становится полностью автономным контейнером криптографического состояния.

Декодирование без внешних зависимостей

Функция sjcl.decrypt(password, json) извлекает все параметры автоматически:

  • парсит JSON
  • извлекает salt и iter
  • повторно применяет PBKDF2
  • восстанавливает ключ
  • расшифровывает ciphertext
  • проверяет целостность через MAC

Отсутствие внешней конфигурации делает процесс воспроизводимым при любом переносе данных между системами.

Практическое значение самодостаточного хранения параметров

Модель хранения параметров деривации внутри шифртекста обеспечивает несколько системных свойств:

  • переносимость между платформами и версиями
  • устойчивость к изменению криптографической политики
  • отсутствие централизованного управления параметрами
  • совместимость старых и новых данных в одном хранилище

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