Миграции при смене алгоритма хеширования

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

На практике это приводит к ситуациям, когда требуется переход, например, с быстрых хеш-функций на адаптивные алгоритмы с высокой вычислительной стоимостью или с одной схемы параметров на другую (увеличение числа итераций, изменение памяти, параметров соли).

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


Формат хранения хеша как основа миграции

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

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

Пример структурированного формата:

$argon2id$v=19$m=65536,t=3,p=4$<salt>$<hash>

или

bcrypt$12$<salt><hash>

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

Ключевой принцип: хранение метаданных алгоритма вместе с хешем делает миграцию управляемой и обратимо-инкрементальной.


Версионирование алгоритмов

Для поддержки миграций вводится концепция версионности. Каждый алгоритм или набор параметров получает свой идентификатор:

  • v1 — старый алгоритм (например, SHA-256 с солью)
  • v2 — bcrypt с cost 10
  • v3 — Argon2id с заданными параметрами

В базе данных либо в самой строке хеша хранится версия:

v2$bcrypt$10$<salt>$<hash>

или

$2b$10$<salt><hash>

Версионность позволяет системе:

  • поддерживать несколько алгоритмов одновременно
  • постепенно переводить пользователей на новые схемы
  • избегать массового пересчёта данных

Подход “rehash on login”

Наиболее распространённая стратегия миграции заключается в пересчёте хеша при следующем входе пользователя.

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

  1. Пользователь вводит пароль.
  2. Система определяет алгоритм старого хеша.
  3. Пароль проверяется старым алгоритмом.
  4. При успешной проверке создаётся новый хеш с актуальным алгоритмом.
  5. Новый хеш сохраняется в базе, заменяя старый.

Преимущества:

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

Недостатки:

  • пользователи, не заходящие в систему, остаются на старом алгоритме
  • миграция растягивается во времени

Параллельная поддержка алгоритмов

В переходный период система должна уметь работать одновременно с несколькими алгоритмами.

Логика проверки выглядит следующим образом:

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

Пример псевдологики:

if (hash.startsWith("argon2id")) {
    verifyArgon2(password, hash)
} else if (hash.startsWith("bcrypt")) {
    verifyBcrypt(password, hash)
} else {
    verifyLegacySHA(password, hash)
}

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


Массовая миграция через фоновые задачи

В системах с высокой активностью пользователей применяется дополнительный подход — фоновая миграция.

Процесс:

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

Однако из-за отсутствия открытого пароля у большинства пользователей этот метод ограничен и обычно комбинируется с “rehash on login”.


Изменение параметров алгоритма без смены алгоритма

Миграция не всегда означает смену алгоритма. Часто достаточно изменить его параметры:

  • увеличение cost-фактора bcrypt
  • увеличение памяти и итераций Argon2
  • переход от fast к slow режиму

В таких случаях применяется проверка “устаревания хеша”:

if (needsRehash(storedHash)) {
    newHash = hash(password, currentParams)
    updateDatabase(newHash)
}

Функция needsRehash сравнивает параметры текущего хеша с рекомендованными.


Проблема обратной совместимости

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

  • все пользователи были переведены на новый формат
  • истёк период активности старых данных
  • завершён аудит системы

Иначе возникает риск блокировки части пользователей.


Использование “pepper” при переходе между алгоритмами

Дополнительный слой безопасности — серверный секрет (pepper), который не хранится в базе данных.

При миграции алгоритмов важно:

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

Это снижает риск компрометации при частичной несовместимости схем.


Порядок миграции в реальных системах

Практическая последовательность обновления выглядит следующим образом:

  1. Ввод нового алгоритма и добавление его поддержки
  2. Обновление функции регистрации новых пользователей
  3. Добавление логики проверки устаревших хешей
  4. Включение “rehash on login”
  5. Мониторинг распределения версий хешей
  6. Постепенное отключение старых алгоритмов

Контроль состояния обычно реализуется через метрики:

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

Ошибки при миграции алгоритмов

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

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

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


Совместимость в распределённых системах

В микросервисной архитектуре миграция усложняется необходимостью синхронизации:

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

Особое внимание требуется при использовании общего API авторизации, где разные сервисы могут находиться на разных этапах миграции.


Контроль качества миграции

Оценка успешности перехода основывается на:

  • снижении доли устаревших хешей
  • отсутствии ошибок проверки паролей
  • стабильности времени отклика
  • отсутствию резких всплесков нагрузки

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