Шифрование паролей в Python с помощью bcrypt

Пароли нельзя хранить в открытом виде. Хеширование превращает пароль в одностороннее значение: его нельзя восстановить обратно, только проверить совпадение. bcrypt добавляет соль и адаптивную сложность, что делает его популярным выбором для хранилища паролей.
Как работает bcrypt
bcrypt — независимая от языка библиотека для хеширования паролей. Она:
- Генерирует соль автоматически при вызове bcrypt.gensalt().
- Возвращает разные хеши для одного и того же пароля из-за уникальной соли.
- Работает с байтовыми строками, поэтому нужно вызвать .encode(‘utf-8’) для входного пароля.
Соль — это случайные данные, добавляемые к паролю перед хешированием. “Rounds” (иногда называют cost) определяет, насколько медленно выполняется хеш-функция — большее значение повышает устойчивость к брутфорсу, но и увеличивает нагрузку на сервер.
Важно: кодирование (encoding) не равняется шифрованию. Кодирование переводит текст в байты, чтобы bcrypt мог их обработать.
Установка и настройка bcrypt
Если ещё не установили, активируйте виртуальное окружение и выполните:
pip install bcryptПримечание: на некоторых системах требуется установленный компилятор или пакеты для билда Python-зависимостей. Для Debian/Ubuntu обычно нужны build-essential и python3-dev.
Шифрование пароля в Python
Простой пример хеширования пароля в скрипте:
import bcrypt
password = "mypasswordstring"
# Перевод строки в байты
password_bytes = password.encode('utf-8')
# Генерация соли и хеширование
hashed_password = bcrypt.hashpw(password_bytes, bcrypt.gensalt())
print(hashed_password) # байтовая строкаКаждый запуск выдаст разный результат — это нормально. Хеш содержит параметр стоимости и соль, поэтому bcrypt.checkpw сможет проверить соответствие без отдельного хранения соли.
Сравнение паролей при аутентификации
При проверке пароля вы сравниваете введённый пользователем пароль с сохранённым хешем:
import bcrypt
# Сохраняемый этап (регистрация)
raw = input("Введите пароль: ")
stored = bcrypt.hashpw(raw.encode('utf-8'), bcrypt.gensalt())
# Аутентификация (вход)
candidate = input("Повторите пароль для проверки: ")
if bcrypt.checkpw(candidate.encode('utf-8'), stored):
print("login success")
else:
print("incorrect password")bcrypt.checkpw безопасно сравнивает байтовую строку с хешем, возвращает True при совпадении.
Интеграция с Flask и базой данных
В веб-приложении замените input() на получение значений из формы. При регистрации:
- Получите пароль из формы.
- Хешируйте и сохраняйте хеш (байтовая строка или кодированная в base64/utf-8) в поле таблицы users.
При входе:
- Получите введённый пароль.
- Сравните через bcrypt.checkpw с хешем из БД.
Пример с SQLAlchemy (упрощённо):
# model
class User(Base):
__tablename__ = 'users'
id = Column(Integer, primary_key=True)
username = Column(String, unique=True)
password_hash = Column(String) # можно хранить как utf-8 декодированный байт-стринг
# регистрация
raw = form.password.data
hash_bytes = bcrypt.hashpw(raw.encode('utf-8'), bcrypt.gensalt()).decode('utf-8')
user = User(username=form.username.data, password_hash=hash_bytes)
session.add(user); session.commit()
# вход
candidate = form.password.data
stored_hash = user.password_hash.encode('utf-8')
if bcrypt.checkpw(candidate.encode('utf-8'), stored_hash):
# успешный входВажно: если вы сохраняете хеш как текст, явно указывайте кодировку при записи/чтении.
Рекомендации по безопасности и hardening
- Настройте rounds (cost) разумно. Обычно используют 10–14, выбирая компромисс между безопасностью и производительностью на вашем сервере.
- Не храните открытые пароли.
- Не пытайтесь “соль” хранить отдельно — bcrypt включает соль в результирующий хеш.
- Не ре-хешируйте уже захешированные пароли при каждой проверке. Храните хеш и используйте checkpw для проверки.
- Добавьте защиту от перебора: rate limiting, блокировки после нескольких неверных попыток, CAPTCHA при подозрении.
- Рассмотрите использование “pepper” — секретного значения, хранящегося отдельно (например, в конфигурации или HSM). Pepper добавляет ещё один уровень защиты при компрометации БД, но усложняет смену секрета.
- Обновление стоимости: при необходимости увеличьте rounds и выполняйте миграцию хешей при следующем входе пользователя (если хеш устарел, пересоздайте новый хеш при успешной аутентификации).
Important: хранение и ротация секретов (pepper, ключи) должна быть частью общей политики безопасности и управления конфигурацией.
Альтернативы и когда bcrypt не подходит
- Argon2 — современный победитель конкурса хеш-функций паролей, более устойчив к атаке на память. Рекомендуется для новых проектов, если библиотека и поддержка платформы доступны.
- scrypt — тоже хороший вариант, ориентирован на ограничение использования памяти.
Когда не использовать bcrypt:
- Для систем с очень жёсткими требованиями к памяти/параллелизму Argon2 может быть предпочтительнее.
- Если вы храните не-пароли (например, API-ключи) и нужен двусторонний механизм — используйте шифрование, а не хеширование.
Когда bcrypt даёт мало защиты (примеры неудач)
- Если база данных утекла и у атакующего есть большая вычислительная мощность и низкий cost — возможен подбор.
- Если приложение не ограничивает попытки входа — перебор становится эффективным.
- Если конфигурация rounds слишком низкая (по умолчанию иногда 12, но это зависит от реализации) — устойчивость падает.
Тесты и критерии приёмки
Критерии приёмки:
- При вводе корректного пароля функция аутентификации возвращает успех.
- При вводе неверного пароля возвращается отказ и не выводится подробная информация.
- Хеш в базе не равен исходному паролю и содержит метаданные (соль, cost).
- Система блокирует IP/учётную запись после N неудачных попыток.
Минимальные тест-кейсы:
- Регистрация -> хранение хеша, вхождение с тем же паролем — удачно.
- Вход с чужим паролем — отклонение.
- Проверка скорости хеширования при выбранном rounds — не превышает допустимой задержки для API.
Чек-листы для ролей
Разработчик:
- Кодирует пароли перед хешированием.
- Не логирует пароли/хеши в логи.
- Использует checkpw для проверки.
DevOps:
- Обеспечивает резервное копирование и защищённый доступ к секретам.
- Мониторит нагрузку при изменении rounds.
Информационная безопасность:
- Определяет политику rounds и pepper.
- Настраивает SLA по безопасности и план реагирования на утечку.
Ментальные модели и эвристики
- Не ищите “обратный” способ — хеширование — односторонняя операция.
- Соль = уникальность на запись. Pepper = секрет приложения.
- Cost: думайте о нём как о ручке регулировки, которая замедляет хеширование — увеличиваете её, чтобы усложнить брутфорс, но платите за это временем CPU.
Глоссарий
- bcrypt: адаптивная хеш-функция паролей.
- соль (salt): случайные данные, добавляемые к паролю перед хешированием.
- rounds / cost: параметр сложности хеша.
- pepper: глобальный секрет, добавляемый к паролю перед хешированием.
Короткое резюме
bcrypt остаётся хорошим выбором для хеширования паролей: он прост, поддерживается в разных языках и включает соль и параметр сложности. Для продакшна настройте cost, защиту от перебора и безопасное хранение хешей. Рассмотрите Argon2 как альтернативу при возможности.
Notes: при переходе на другие хеш-функции планируйте миграцию хешей: проверяйте при входе и пересохраняйте новый хеш после успешной аутентификации.
Похожие материалы
Как выбрать игровую гарнитуру — руководство
Продлить заряд DualSense: советы для PS5
Live Captions на Mac: включение, настройка и советы
Автовключение, перезагрузка и выключение Mac
Как выйти из бета macOS Ventura