Password rotation и множественные ключи

В библиотеке используется симметричное шифрование для «запечатывания» (seal) и «распечатывания» (unseal) данных. Ключевой элемент безопасности — секретный пароль, на основе которого формируются криптографические ключи. При компрометации или плановой смене секретов применяется ротация паролей, позволяющая постепенно переходить на новые ключи без нарушения совместимости с уже выданными токенами.

Принцип работы с несколькими ключами

В механизме Iron допускается использование не одного пароля, а массива секретов. Это создаёт основу для безопасной ротации:

  • новый пароль добавляется в начало массива;
  • старые пароли сохраняются на период перехода;
  • при расшифровке система перебирает ключи по очереди.

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

При попытке unseal библиотека последовательно проверяет каждый пароль из списка, пока не найдёт подходящий.

Поведение при шифровании и расшифровке

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

При расшифровке происходит обратный процесс:

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

Это делает возможным мягкое обновление ключей без массовой реэнкриптации данных.

Базовый пример использования массива ключей

import Iron from '@hapi/iron';

const passwords = [
  'new-super-secret-password',
  'old-password-1',
  'old-password-2'
];

const data = {
  user: 'alice',
  role: 'admin'
};

const sealed = await Iron.seal(data, passwords[0], Iron.defaults);

const unsealed = await Iron.unseal(sealed, passwords, Iron.defaults);

В этом примере:

  • passwords[0] используется для создания нового зашифрованного объекта;
  • массив passwords используется для обратного восстановления данных.

Стратегия ротации ключей

Ротация паролей строится на управляемом жизненном цикле ключей.

Добавление нового ключа

Новый секрет вводится в систему путем добавления его в начало массива:

const passwords = [
  'new-key-v3',
  'old-key-v2',
  'old-key-v1'
];

После этого все новые данные начинают шифроваться только с использованием new-key-v3.

Удаление устаревших ключей

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

Постепенная миграция

Типичный цикл ротации:

  1. Добавление нового ключа в массив.
  2. Начало шифрования новых данных только новым ключом.
  3. Поддержка старых ключей для чтения.
  4. Постепенное исчезновение старых данных.
  5. Удаление устаревших ключей.

Поведение при ошибках расшифровки

Если ни один ключ из массива не подходит, операция unseal завершается ошибкой. Это может означать:

  • повреждение данных;
  • удаление нужного ключа;
  • попытку подмены токена.

Поэтому порядок ключей имеет критическое значение: чем выше ключ в массиве, тем выше его приоритет.

Оптимизация порядка ключей

Перебор ключей линейный, поэтому порядок влияет на производительность.

Рекомендуемая структура массива:

  • первый элемент — актуальный ключ;
  • далее — ключи по убыванию актуальности;
  • в конце — самые старые.

Это минимизирует количество проверок при типичном сценарии использования.

Ключи и криптографическая устойчивость

Каждый пароль в Iron не используется напрямую как шифровальный ключ. Из него выводится криптографический материал через алгоритмы хэширования и деривации ключа. Это означает:

  • длина пароля не равна длине ключа;
  • безопасность зависит от энтропии исходного секрета;
  • ротация должна сопровождаться генерацией действительно новых случайных значений.

Слабые или предсказуемые пароли сводят на нет преимущества ротации.

Совместимость при обновлении системы

Механизм множественных ключей особенно важен при:

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

Старые данные остаются читаемыми, пока присутствует хотя бы один соответствующий ключ.

Практика безопасного хранения массива ключей

Список паролей не должен храниться в коде. Обычно он передаётся через:

  • переменные окружения;
  • системы секретов (Vault, KMS);
  • защищённые конфигурационные сервисы.

Пример формирования массива из окружения:

const passwords = process.env.IRON_PASSWORDS.split(',');

Проблемы некорректной ротации

Нарушение порядка или стратегии приводит к типичным сбоям:

  • невозможность расшифровки старых токенов;
  • частичная несовместимость между инстансами сервиса;
  • резкое увеличение нагрузки из-за неэффективного перебора ключей;
  • случайное использование устаревшего ключа для новых данных.

Особенно критична ситуация, когда новый ключ не ставится на первое место массива.

Масштабирование схемы ротации

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

Для масштабируемых систем применяются:

  • централизованные хранилища секретов;
  • синхронизация конфигурации;
  • атомарное обновление массива ключей.

Влияние ротации на безопасность

Регулярная смена ключей уменьшает риски:

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

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