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

«Как правильно хранить пароли пользователей в базе данных?» — вопрос из категории Безопасность, который задают на 10% собеседований Python Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

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

Процесс выглядит так:

  1. Генерация "соли" (Salt): Для каждого пользователя создается уникальная случайная строка — соль.
  2. Хеширование: Пароль пользователя объединяется с солью, и результат пропускается через криптографическую хеш-функцию.
  3. Хранение: В базе данных сохраняется только хеш и соль. Исходный пароль не хранится нигде.

Почему это безопасно?

  • Необратимость: Из хеша невозможно восстановить исходный пароль.
  • Защита от радужных таблиц: Соль гарантирует, что даже у пользователей с одинаковыми паролями будут абсолютно разные хеши, что делает предварительно вычисленные таблицы хешей (rainbow tables) бесполезными.

Рекомендуемые алгоритмы:

  • Argon2 (победитель конкурса Password Hashing Competition, современный стандарт)
  • bcrypt (очень надежный и широко используемый)
  • scrypt или PBKDF2

Важно: Следует избегать устаревших алгоритмов, таких как MD5 или SHA-1, так как они не являются безопасными для хранения паролей.

Пример на Python с bcrypt:

import bcrypt

# Пароль, полученный от пользователя при регистрации
password = b"S3cuRe_P@ssw0rd!"

# 1. Генерируем соль и создаем хеш
salt = bcrypt.gensalt()
hashed_password = bcrypt.hashpw(password, salt)

# В БД сохраняем hashed_password (он уже содержит соль)
# print(hashed_password) -> b'$2b$12$....'

# --- Проверка пароля при входе ---

# Пароль, введенный пользователем
user_input = b"S3cuRe_P@ssw0rd!"

# 2. Сравниваем введенный пароль с хешем из БД
if bcrypt.checkpw(user_input, hashed_password):
    print("Пароль верный")
else:
    print("Пароль неверный")