Вы поддерживаете существующее приложение с установленной базой пользователей. Со временем было решено, что текущая техника хеширования паролей устарела и нуждается в обновлении. Кроме того, по причинам UX, вы не хотите, чтобы существующие пользователи были вынуждены обновить свой пароль. Все обновление хэширования паролей должно происходить за экраном.
Предположим «упрощенную» модель базы данных для пользователей, которая содержит:
- МНЕ БЫ
- Эл. адрес
- пароль
Как можно решить такое требование?
Мои нынешние мысли:
- создать новый метод хеширования в соответствующем классе
- обновить таблицу пользователей в базе данных для хранения дополнительного поля пароля
- Как только пользователь успешно войдет в систему с использованием устаревшего хэша пароля, заполните второе поле пароля обновленным хэшем
Это оставляет меня с проблемой, что я не могу разумно провести различие между пользователями, которые имеют и теми, кто не обновил свой хэш пароля и, следовательно, будет вынужден проверить оба. Это кажется ужасно ошибочным.
Кроме того, это в основном означает, что старая техника хэширования может быть вынуждена оставаться неопределенно долго, пока каждый пользователь не обновит свой пароль. Только в этот момент я могу начать удалять старую проверку хэширования и удалять лишнее поле базы данных.
Здесь я в основном ищу несколько советов по дизайну, так как мое текущее «решение» грязное, неполное, а что нет, но если для описания возможного решения требуется реальный код, не стесняйтесь использовать любой язык.
Ответы:
Я бы предложил добавить новое поле "hash_method", возможно, с 1 для обозначения старого метода и 2 для обозначения нового метода.
Разумно говоря, если вы заботитесь о такого рода вещах и ваше приложение является относительно долгоживущим (что, по-видимому, уже есть), это, вероятно, произойдет снова, поскольку криптография и информационная безопасность - это развивающаяся, довольно непредсказуемая область. Было время, когда простой прогон через MD5 был стандартным, если хеширование вообще использовалось! Тогда можно подумать, что они должны использовать SHA1, и теперь есть соление, глобальная соль + индивидуальная случайная соль, SHA3, различные методы генерации случайных чисел с криптографией ... это не просто остановит, так что вы можете хорошо это исправить в расширяемом, повторяемом виде.
Итак, допустим, теперь у вас есть что-то вроде (в псевдо-javascript для простоты, я надеюсь):
Теперь, понимая, что есть лучший метод, вам просто нужно провести небольшой рефакторинг:
Никакие секретные агенты или программисты не пострадали в производстве этого ответа.
источник
newHash(oldHash, salt)
илиnewHash(password, salt)
Если вам нужно как можно быстрее развернуть новую схему хеширования для всех пользователей (например, потому что старая действительно небезопасна), существует способ мгновенной «миграции» каждого пароля.
Идея в основном состоит в том, чтобы хэшировать хэш . Вместо того, чтобы ждать, пока пользователи предоставят свой существующий пароль (
p
) при следующем входе в систему, вы немедленно используете новый алгоритм хеширования (H2
) для существующего хэша, уже созданного старым алгоритмом (H1
):После этого преобразования вы все еще можете выполнять проверку пароля; вам просто нужно вычислить
H2(H1(p'))
вместо предыдущегоH1(p')
всякий раз, когда пользователь пытается войти с паролемp'
.В теории, эта техника может быть применена к нескольким миграциям (
H3
,H4
и т.д.). На практике вы захотите избавиться от старой хеш-функции, как из-за производительности, так и из-за читабельности. К счастью, это довольно просто: при следующем успешном входе в систему просто вычислите новый хэш пароля пользователя и замените существующий хэш пароля:Вам также понадобится дополнительный столбец, чтобы запомнить, какой хеш вы храните: пароль или старый хеш. В неудачном случае утечки базы данных этот столбец не должен облегчать работу взломщика; независимо от его значения, злоумышленнику все равно придется изменить
H2
алгоритм безопасности , а не старыйH1
.источник
Ваше решение (дополнительный столбец в базе данных) вполне приемлемо. Единственная проблема с ним - та, о которой вы уже упоминали: старая хеш-функция все еще используется для пользователей, которые не прошли аутентификацию после изменения.
Чтобы избежать этой ситуации, вы можете подождать, пока ваши самые активные пользователи переключатся на новый алгоритм хеширования, а затем:
Удалите учетные записи пользователей, которые не проходят аутентификацию слишком долго. Нет ничего плохого в удалении аккаунта пользователя, который не заходил на сайт в течение трех лет.
Отправьте электронное письмо оставшимся пользователям из числа тех, кто некоторое время не проходил аутентификацию, сообщая, что их может заинтересовать что-то новое. Это поможет еще больше сократить количество учетных записей, использующих старое хэширование.
Будьте осторожны: если у вас есть опция без спама, пользователи могут проверить ваш сайт, не отправляйте электронное письмо пользователям, которые его проверили.
Наконец, через несколько недель после шага 2 уничтожьте пароль для пользователей, которые все еще используют старую технику. Когда и если они попытаются пройти аутентификацию, они увидят, что их пароль неверен; если они все еще заинтересованы в вашем сервисе, они могут сбросить его.
источник
Вероятно, у вас никогда не будет более пары типов хэшей, поэтому вы можете решить эту проблему, не расширяя базу данных.
Если методы имеют разную длину хеш-функции и длина хеш-функции каждого метода постоянна (скажем, при переходе от md5 к hmac-sha1), вы можете отличить метод от длины хеш-функции. Если они имеют одинаковую длину, вы можете сначала вычислить хеш, используя новый метод, а затем старый метод, если первый тест не пройден. Если у вас есть поле (не показано), в котором указано, когда пользователь последний раз обновлялся / создавался, вы можете использовать его в качестве индикатора того, какой метод использовать.
источник
Я сделал что-то подобное, и есть способ узнать, является ли это новым хешем, и сделать его еще более безопасным. Я полагаю, что безопаснее - это хорошо для вас, если вы нашли время обновить хэш ;-)
Добавьте новый столбец в вашу таблицу БД под названием «соль» и, хорошо, используйте его в качестве произвольно сгенерированной соли для каждого пользователя. (в значительной степени предотвращает атаки радужного стола)
Таким образом, если мой пароль «pass123», а случайная соль - 3333, мой новый пароль будет хешем «pass1233333».
Если у пользователя есть соль, вы знаете, что это новый хеш. Если соль пользователя равна нулю, вы знаете, что это старый хеш.
источник
Независимо от того, насколько хороша ваша стратегия миграции, если база данных уже была украдена (и вы не можете отрицательно доказать, что этого никогда не было), пароли, хранящиеся с помощью небезопасных хеш-функций, могут быть уже скомпрометированы. Единственное смягчение для этого требует, чтобы пользователи изменили свои пароли.
Это не проблема, которая может быть решена (только) написанием кода. Решение состоит в том, чтобы информировать пользователей и клиентов о рисках, которым они подверглись. Как только вы захотите открыто рассказать об этом, вы можете выполнить миграцию, просто сбросив пароль каждого пользователя, потому что это самое простое и безопасное решение. Все альтернативы на самом деле скрывают тот факт, что вы облажались.
источник