Как правильно хранить пароли пользователей
Почему пароли нельзя хранить открытым текстом или простым MD5, что такое соль и какие алгоритмы хеширования использовать сегодня.
Базы данных утекают — даже у больших компаний. Поэтому пароли нужно хранить так, чтобы утечка базы не превращалась в утечку паролей.
Плохие варианты
- Открытым текстом. Любой, кто получил базу, видит все пароли. А люди часто используют один пароль на разных сайтах.
- Шифрованием. Если есть ключ для расшифровки, он обычно лежит рядом — и утекает вместе с базой.
- Быстрым хешем (MD5, SHA-1, SHA-256). Хеш нельзя «расшифровать», но его можно подобрать: видеокарта перебирает миллиарды MD5 в секунду. Посмотрите, как быстро это делается, в задаче Взлом MD5.
Что такое соль
Соль — случайная строка, уникальная для каждого пользователя, которая добавляется к паролю перед хешированием и хранится рядом с хешем. Она даёт два эффекта:
- одинаковые пароли у разных людей дают разные хеши;
- заранее посчитанные таблицы хешей (rainbow tables) становятся бесполезны.
Правильный способ
Использовать медленные функции, созданные для паролей: Argon2id, scrypt или bcrypt. Они специально тратят много времени и памяти на один хеш, поэтому перебор становится в тысячи раз дороже. Соль они добавляют сами.
from werkzeug.security import generate_password_hash, check_password_hash
h = generate_password_hash("correct horse battery staple") # scrypt + соль
check_password_hash(h, "correct horse battery staple") # TrueВ PHP то же самое делают password_hash и password_verify.
Что ещё важно
- Ограничивайте число попыток входа — и с одного IP, и для одного аккаунта.
- Не вводите странные правила вроде «ровно 8 символов» — длина важнее спецсимволов.
- Отвечайте одинаково, существует аккаунт или нет, — чтобы по ответу нельзя было собрать список пользователей.
Практика
Задачи Политика паролей и Повторное использование паролей показывают обе стороны: как пишут проверки и почему одинаковые пароли на разных сайтах опасны.