Получить доступ

Как правильно хранить пароли пользователей?

JuniorБезопасность
Ещё спрашивают так:
  • Зачем нужна соль?
  • Почему нельзя хранить пароли в SHA-256?
  • Что такое bcrypt и argon2?
Коротко

Не хранить пароль вовсе — только результат медленной функции с солью: argon2id, bcrypt или scrypt. При входе считаем то же самое и сравниваем.

  • Соль — случайное значение для каждого пользователя: одинаковые пароли дают разные хеши, радужные таблицы бесполезны
  • SHA-256 слишком быстрый: видеокарта перебирает миллиарды вариантов в секунду
  • Параметры стоимости подбирают так, чтобы одна проверка шла ~0,1–0,5 секунды

А ещё Плюс: ограничение попыток, проверка по базам утёкших паролей, двухфакторная аутентификация

Так подсказку видит пользователь sotto на живом собеседовании — за пару секунд, пока вы думаете вслух.

Подробно

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

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

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

Как правильно:

  • соль — случайные 16+ байт на каждого пользователя, хранится рядом с хешем. Атакующему приходится перебирать каждого отдельно;
  • медленная функция — специально дорогая по времени и памяти:
    • argon2id — современная рекомендация, настраивается память, итерации и параллелизм; память мешает перебору на видеокартах;
    • bcrypt — проверенный временем, параметр cost (каждая единица удваивает время), ограничение длины пароля 72 байта;
    • scrypt, PBKDF2 (если нужна сертификация FIPS, с большим числом итераций);
  • параметры стоимости хранятся в строке хеша ($argon2id$v=19$m=65536,t=3, p=4$соль$хеш) — можно повышать со временем и перехешировать при следующем входе;
  • перец (pepper) — дополнительный секрет вне базы (в HSM или KMS), по желанию.

Вокруг хранения: ограничение числа попыток входа и задержки, одинаковое сообщение «неверный логин или пароль», сравнение за постоянное время (библиотеки делают сами), проверка новых паролей по базе утёкших (Have I Been Pwned), минимальная длина важнее правил «цифра и спецсимвол», двухфакторная аутентификация, а лучше — passkeys.

Пример

from argon2 import PasswordHasher
ph = PasswordHasher()                     # argon2id с разумными параметрами
stored = ph.hash("correct horse battery staple")
# '$argon2id$v=19$m=65536,t=3,p=4$Z3Vp…$Xh9…' — соль и параметры внутри строки
ph.verify(stored, "correct horse battery staple")   # True, иначе исключение
if ph.check_needs_rehash(stored):
    stored = ph.hash(password)            # параметры усилились — перехешировать

Что хотят услышать

  • Хранить не пароль, а медленный хеш с солью.
  • Зачем соль и почему SHA-256 не подходит.
  • Названия: argon2id, bcrypt, scrypt.
  • Меры вокруг: лимиты попыток, 2FA, утёкшие пароли — плюс.

Частые ошибки

  • Одна соль на всех пользователей.
  • «Шифруем пароли AES» или «хешируем MD5».

Связанные вопросы

Закрытая бета

Подсказки на собеседовании — в реальном времени

sotto слышит вопрос интервьюера и показывает короткий ответ и план, как в блоке «Коротко». Оставьте контакт — пришлём доступ и промокод.

  • Промокод на 2 часа — сверх пробных 30 минут
  • Программа для Windows — скачать сразу, войти — через Яндекс ID или VK ID
  • Прямая связь с разработчиком: что улучшить — сделаем