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

Если сервис зашифровал запись ключом K1, а после деплоя оставил в памяти только K2, чтение этой записи завершится ошибкой расшифровки. Для ротации без простоя приложению нужно некоторое время уметь читать данные обоими ключами, записывать новые — только актуальным, а старые удалять лишь после проверки данных, резервных копий и всех работающих экземпляров.
Границы разбора: шифрование данных приложения
Здесь речь о симметричном шифровании данных, которые сервис хранит или передаёт между своими компонентами. Ротация ключей TLS, подписи JWT и ключей доступа к API — отдельные задачи: у них другие потребители, сроки жизни и способы распространения новых ключей.
Перед ревью уточните, что именно меняют: ключ шифрования самих данных или ключ, которым шифруют другие ключи. Во втором случае иногда достаточно повторно обернуть ключи данных, а не расшифровывать и заново шифровать весь массив. Возможность и порядок такой операции зависят от KMS или криптографического инструмента; автоматическую ротацию в KMS нельзя без проверки считать миграцией уже сохранённых данных.
Сноска. Ключ шифрования данных (DEK) защищает сами данные. Ключ шифрования ключей (KEK) защищает DEK. Такое разделение называют envelope encryption, или конвертным шифрованием.
Безопасная схема: читать несколькими, писать одним
Во время перехода каждый экземпляр приложения должен знать старый и новый ключи, но выбирать для новых записей только один — текущий. Вместе с шифротекстом храните идентификатор ключа или его версии: тогда приложение понимает, чем расшифровывать конкретную запись, а не перебирает все доступные ключи.
- Подготовьте совместимость. Разверните версию, которая умеет расшифровывать данные K1 и K2, но пока продолжает писать K1. Проверьте чтение записей, зашифрованных каждым ключом, на тестовой среде. Если старые экземпляры не понимают формат с идентификатором ключа, сначала обновите их или спланируйте отдельный совместимый формат.
- Переключите запись. После того как все экземпляры поддерживают оба ключа, смените ключ записи на K2. Проверьте на тестовой записи: новый шифротекст помечен K2 и успешно читается приложением. Не удаляйте поддержку K1 — старые записи ещё могут существовать.
- Мигрируйте сохранённые данные. Запускайте фоновую обработку небольшими порциями: прочитать с указанием K1, зашифровать K2 и сохранить новую версию. Отслеживайте ошибки и пропуски, не блокируя пользовательские запросы долгой транзакцией. Проверка результата — счётчик записей K1 уменьшается, а контрольные чтения проходят.
- Подтвердите завершение и выводите K1. Убедитесь, что приложение больше не создаёт записи K1, обработчик не находит оставшихся данных, а резервные копии и реплики учтены. Только после этого убирайте K1 из рабочего пути чтения; удаление или уничтожение ключа согласуйте с правилами хранения бэкапов и восстановления.
Проверка должна охватывать все экземпляры, очереди и фоновые задачи, а не только один успешно обновлённый сервер. Если в системе есть отложенные сообщения с зашифрованными данными, они тоже могут пережить переключение и потребовать K1.
Три варианта миграции и их цена
| Подход | Что происходит | Цена и риск |
|---|---|---|
| Сразу заменить ключ | Новые экземпляры используют K2; старые записи могут остаться зашифрованными K1. | Просто реализовать, но безопасно только если старые данные не нужны либо отдельная совместимость уже предусмотрена. Иначе часть чтений сломается. |
| Несколько ключей для чтения, один для записи | Приложение выбирает ключ по сохранённому идентификатору; все новые записи шифрует K2. | Удобно для постепенного перехода. Нужно хранить метаданные версии и поддерживать старый ключ до завершения миграции. |
| Фоновая перешифровка | Старые записи постепенно читаются K1 и сохраняются с K2. | Не создаёт массовой нагрузки в одной операции, но требует контроля повторов, конкурентных изменений и остатка данных. |
На практике эти варианты часто сочетают: сначала включают чтение несколькими ключами, затем переключают запись и запускают фоновую миграцию. Главное — не считать сам факт успешного деплоя доказательством, что данные уже перенесены.
«Новый ключ можно включить быстро. Безопасно убрать старый можно только после того, как вы доказали, что ни один живой процесс и ни одна нужная копия данных от него не зависят».
Что искать на ревью
Ревьюеру важны не только вызовы библиотеки шифрования, но и порядок выкладки, формат хранения и сценарий отката. Вот конкретные замечания, которые помогают обнаружить проблемы до продакшена:
- «Где сохраняется идентификатор ключа? По каким данным приложение выберет K1 или K2 при чтении?» Если ответ — «попробуем все ключи подряд», уточните, как ограничен список и как система ведёт себя при неизвестном идентификаторе.
- «Что произойдёт, если старый экземпляр продолжит писать после переключения на K2?» Миграцию нельзя считать законченной, пока совместимые со старым ключом процессы или задачи ещё могут создавать записи K1.
- «Как мигратор обрабатывает запись, которую пользователь изменил одновременно с перешифровкой?» Нужна защита от перезаписи более свежих данных: например, проверка версии записи или иной подход, соответствующий хранилищу.
- «Можно ли безопасно повторить эту порцию после сбоя?» Повторная обработка не должна повреждать данные или бесконечно создавать новые версии. Проверьте, что ошибка на одной записи не останавливает всю очередь без сигнала.
- «Где окажутся ключ и диагностические данные?» Секрет не должен попадать в логи, трассировки, сообщения об ошибках и дампы конфигурации. Для тестов и примеров не используйте настоящие ключи.
- «Какие копии данных останутся зашифрованы K1?» Учтите резервные копии, архивы, реплики, выгрузки и сообщения в очередях. Если для восстановления старого бэкапа нужен K1, его нельзя уничтожать сразу после миграции основной базы.
Ещё один риск — несовместимый откат. Если новая версия уже записала данные только ключом K2, возврат к старой версии, которая знает лишь K1, сломает чтение. План отката должен сохранять поддержку обоих ключей или заранее описывать безопасный переход назад.
Где подход ломается и что измерять
Схема с чтением несколькими ключами работает, пока формат записи однозначно указывает нужную версию, все приложения имеют доступ к необходимым ключам, а миграция не теряет конкурентные обновления. Она ломается, если часть сервисов читает данные по-своему, старые записи не содержат метаданных, а ключ уже уничтожили или сделали недоступным для восстановления.
До запуска зафиксируйте исходное число записей по версиям ключа. Во время миграции следите за остатком K1, скоростью обработки, долей ошибок расшифровки и перешифровки, задержкой пользовательских запросов и нагрузкой на хранилище. После остановки мигратора проверьте, что старых записей не осталось, а тест восстановления из копии действительно проходит. Универсального безопасного размера порции и скорости здесь нет: их подбирают на копии данных с теми же ограничениями хранилища и нагрузки.
Не запускайте массовую перешифровку в запросе пользователя: она увеличивает время ответа и связывает доступность чтения с доступностью старого ключа и миграционной операции. Если миграция прервалась, важны сохранённый прогресс и возможность продолжить обработку, а не повторно начать её вслепую.
Что делать дальше
Сначала составьте карту всех мест, где появляются и читаются зашифрованные данные: сервисы, фоновые задачи, очереди, реплики и резервные копии. Затем проверьте план выкладки на сценарии «часть экземпляров обновилась», «мигратор остановился» и «нужен откат». Следующий практический шаг — провести тестовое восстановление копии данных после ротации и измерить, сколько записей всё ещё требуют K1. Пока этот ответ неизвестен, старый ключ рано выводить из эксплуатации.
Инфографика для маркетплейса: Три главных преимущества товара короткими фразами, выноски в безопасной зоне превью, точный размер площадки.
Спросить за 60 ₽Источники: OWASP Cryptographic Storage Cheat Sheet, NIST SP 800-57 Part 1 Revision 5: Recommendation for Key Management
Частые вопросы
Можно ли просто заменить ключ в настройках и перезапустить приложение?
Нужно ли перешифровывать все данные, если в KMS включена автоматическая ротация?
Что делать, если миграция оборвалась на середине?
Можно ли удалить старый ключ сразу после переключения записи на новый?
Что делать, если у меня другая версия библиотеки или другой KMS?
Какие подводные камни проявляются в продакшене?
Материал носит информационный характер и подготовлен редакцией «Агентуры». Он не является офертой, рекламой или индивидуальной консультацией. Упомянутые продукты, компании и торговые знаки принадлежат их правообладателям. Перед принятием решений, влекущих юридические или финансовые последствия, обратитесь к профильному специалисту.