Хэширование паролей в Node.js с bcrypt

К чему служит эта статья
Краткое практическое руководство по тому, как правильно генерировать соль и хешировать пароли в Node.js с помощью библиотеки bcrypt. Подойдёт разработчикам, инженерам безопасности и DevOps-инженерам, которые внедряют аутентификацию и хотят улучшить хранение паролей.
Важно: хеширование и соль снижают риск компрометации, но не заменяют проверку сложности пароля, мониторинг утечек и общий план безопасности.
Что такое хэширование паролей
Хэширование паролей — это процесс пропуска простого пароля через криптографический алгоритм, который выдаёт уникальное значение фиксированной длины, называемое хешем. Хороший хеш-функция детерминирована: один и тот же вход даёт одинаковый выход, что делает её уязвимой к перебору, если не применять дополнительные меры.
Определение: Хеш — это необратимое представление данных фиксированной длины, полученное из входной строки.
Что такое соль
Соль — это случайная строка, добавляемая к паролю перед хешированием. Соль гарантирует, что одинаковые пароли у разных пользователей дают разные хеши. Это предотвращает использование заранее вычисленных таблиц (rainbow tables) и значительно усложняет массовый перебор.
Совет: храните соль вместе с хешем (bcrypt делает это автоматически — соль включается в результирующую строку).
Почему bcrypt
bcrypt специально разработан для хеширования паролей: он медленнее общих хешей (SHA), что затрудняет перебор, и поддерживает настройку «стоимости» (work factor, rounds). Это делает атаки методом перебора более дорогостоящими для злоумышленников.
Как использовать bcrypt для хеширования и проверки пароля
Ниже — шаги и примеры, которые помогут быстро внедрить bcrypt в Node.js-проект.
Установка bcrypt
Установите пакет через npm или yarn.
Using npm:
npm install bcrypt
Using yarn:
yarn add bcrypt
Импорт bcrypt
const bcrypt = require("bcrypt")
Генерация соли
Вызывайте bcrypt.genSalt() с параметром стоимости (cost factor, rounds). Чем выше значение, тем больше времени займёт хеширование и тем надёжнее защита от грубой силы. Обычно используют значения в диапазоне 5–15; часто применяют 10 как разумный компромисс.
Пример:
bcrypt.genSalt(10, (err, salt) => {
// use salt to hash password
})
Хеширование пароля
Передайте исходный пароль и соль в bcrypt.hash(). После получения хеша сохраните его в базе данных — соль уже включена в результирующую строку.
bcrypt.genSalt(10, (err, salt) => {
bcrypt.hash(plaintextPassword, salt, function(err, hash) {
// Store hash in the database
});
})
Альтернатива — сгенерировать соль и хеш в одном вызове:
bcrypt.hash(plaintextPassword, 10, function(err, hash) {
// store hash in the database
});
Сравнение паролей
Для аутентификации используйте bcrypt.compare(), передавая пользовательский пароль и хеш из БД. Если результат true — пароль совпадает.
bcrypt.compare(plaintextPassword, hash, function(err, result) {
if (result) {
// password is valid
}
});
Async/await и промисы
Библиотека поддерживает async/await и промисы. Оставляем примеры оригинального синтаксиса — они корректны и удобны.
async function hashPassword(plaintextPassword) {
const hash = await bcrypt.hash(plaintextPassword, 10);
// Store hash in the database
}
// compare password
async function comparePassword(plaintextPassword, hash) {
const result = await bcrypt.compare(plaintextPassword, hash);
return result;
}
function hashPassword(plaintextPassword) {
bcrypt.hash(plaintextPassword, 10)
.then(hash => {
// Store hash in the database
})
.catch(err => {
console.log(err)
})
}
function comparePassword(plaintextPassword, hash) {
bcrypt.compare(plaintextPassword, hash)
.then(result => {
return result
})
.catch(err => {
console.log(err)
})
}Проверка надёжности и периоды обновления
Хеширование — это только часть защиты. Обязательно:
- Валидируйте минимальную длину и сложность пароля (строки, цифры, спецсимволы по политике).
- Принуждайте пользователя к смене пароля при компрометации учётной записи.
- Периодически пересматривайте параметр стоимости (rounds) и, при необходимости, пересчитывайте хеши (migration).
Когда такой подход не подходит
- Если пароли слабые (например, «123456»), даже соль и bcrypt не спасут — нужно требовать сложность.
- Если система требует очень высокую скорость обработки миллионы проверок в секунду (встроенные сервисы аутентификации могут использовать специализированные решения).
- При неверной реализации (например, хранение открытых паролей или передачи пароля по HTTP) — проблема не в bcrypt, а в архитектуре.
Альтернативные подходы
- Argon2 — современный алгоритм-победитель конкурса хеширования паролей: устойчив к GPU-атак и гибко настраивается по памяти и времени.
- scrypt — позволяет задать объём потребляемой памяти, усложняя атаки на специализированном оборудовании.
- PBKDF2 — стандартный и широко поддерживаемый, но требует правильной настройки итераций.
Выбор: для новых проектов рассмотрите Argon2; bcrypt остаётся надёжным, проверенным и простым в использовании.
Эвристики и образ мышления
- Относитесь к паролю как к секрету: никогда не храните его в логах или в явном виде.
- Соль — не секрет: она уникализирует хеши; храните её вместе с хешем.
- Pepper — дополнительный секрет, хранящийся отдельно (например, в окружении сервера), может усилить защиту от взлома БД.
- Баланс стоимости: увеличивайте rounds по мере роста мощности серверов и угроз.
Мини‑методология внедрения (шаги)
- Выбрать библиотеку (bcrypt/Argon2).
- Настроить минимальную политику паролей.
- Реализовать хеширование перед сохранением (bcrypt.hash).
- Сравнение при входе (bcrypt.compare).
- Логирование неудачных попыток и защита от перебора (rate limiting, lockout).
- План миграции хешей при изменении алгоритма или параметров.
Чек-листы по ролям
- Разработчик:
- Реализовал bcrypt.hash при регистрации.
- Использует bcrypt.compare при логине.
- Не логирует пароли.
- DevOps:
- Обеспечил защищённое хранение переменных окружения (pepper).
- Настроил резервное копирование и шифрование БД.
- Инженер по безопасности:
- Провёл ревью параметра rounds.
- Запланировал тесты нагрузки и миграцию хешей.
Критерии приёмки
- Пароль пользователя сохраняется в базе только в виде хеша.
- Сравнение пароля возвращает true для корректных паролей и false для остальных.
- Процесс регистрации и логина защищён TLS.
- Есть автоматическое ограничение попыток входа.
Рекомендации по усилению безопасности
- Используйте HTTPS/TLS для всех запросов аутентификации.
- Храните pepper в секретном хранилище (Vault, KMS) вне БД.
- Включите мониторинг утечек и уведомления о подозрительной активности.
- Реализуйте многофакторную аутентификацию (MFA) для критичных операций.
Краткий глоссарий
- Хеш: необратимый результат криптографической функции.
- Соль: случайная строка, добавляемая к паролю перед хешированием.
- Pepper: дополнительный секрет, хранимый отдельно от БД.
- Rounds/Cost factor: параметр, определяющий трудоёмкость хеширования.
Тестовые сценарии и приёмочные критерии
- Зарегистрировать нового пользователя: в БД появляется валидный bcrypt-хеш.
- Войти с корректным паролем: bcrypt.compare возвращает true.
- Войти с неверным паролем: возвращается false и инкрементируется счётчик неудач.
- Попытка SQL-инъекции не должна раскрыть хеш или соль.
Краткое резюме
bcrypt — удобный и надёжный способ хеширования паролей в Node.js. Соль и правильная конфигурация rounds делают атаки перебором значительно дороже. Дополняйте хеширование политиками сложности паролей, TLS, хранением pepper и мониторингом, чтобы получить надежную систему аутентификации.
Важно: любой механизм хеширования требует регулярного пересмотра конфигурации по мере роста вычислительных мощностей и появления новых угроз.
Похожие материалы
Несколько аккаунтов Skype: Multi Skype Launcher
Журнал для работы: повысить продуктивность
Персональные звуки уведомлений на Android
Скачивание шоу Hulu для офлайн‑просмотра
Microsoft Start: персонализированная новостная лента