Хеширование паролей — это процесс преобразования исходной строки в
необратимое значение фиксированной длины. Для задач аутентификации
требуется не просто хеш-функция, а алгоритм, устойчивый к перебору
(brute-force) и атакам с использованием радужных таблиц. Именно поэтому
используются адаптивные алгоритмы, такие как bcrypt, которые позволяют
управлять вычислительной сложностью.
Алгоритм bcrypt: ключевые
особенности
bcrypt основан на алгоритме шифрования Blowfish и был разработан с
учётом следующих требований:
- Адаптивная сложность (cost factor) — параметр,
определяющий количество итераций. Увеличение значения экспоненциально
замедляет вычисления.
- Соль (salt) — случайное значение, добавляемое к
паролю перед хешированием, предотвращающее использование заранее
вычисленных таблиц.
- Защита от GPU/ASIC атак — bcrypt намеренно
использует ресурсоёмкие операции с памятью.
Формат результата bcrypt включает:
$2b$10$<22-символьная соль><31-символьный хеш>
Реализации bcrypt в
экосистеме JavaScript
В JavaScript-среде существует несколько популярных реализаций bcrypt,
каждая из которых имеет свои особенности:
node.bcrypt.js (нативная
реализация)
node.bcrypt.js (часто публикуется как пакет
bcrypt) — это обёртка над нативной библиотекой на C++.
Характеристики:
- Использует нативные биндинги Node.js
- Высокая производительность
- Асинхронные методы с использованием libuv (не блокируют event
loop)
- Требует компиляции при установке (node-gyp)
Пример:
const bcrypt = require('bcrypt');
const hash = await bcrypt.hash('password', 10);
const match = await bcrypt.compare('password', hash);
Плюсы:
- Максимальная скорость
- Поддержка асинхронных операций
- Хорошо подходит для production-нагрузки
Минусы:
- Зависимость от нативной сборки
- Возможны проблемы при установке (особенно на Windows или CI)
bcryptjs (чистый JavaScript)
bcryptjs — это полностью JavaScript-реализация
bcrypt без использования нативных модулей.
Характеристики:
- Не требует компиляции
- Работает в любом окружении (Node.js, браузер)
- Синхронные и псевдо-асинхронные методы
Пример:
const bcrypt = require('bcryptjs');
const hash = bcrypt.hashSync('password', 10);
const match = bcrypt.compareSync('password', hash);
Плюсы:
- Простота установки
- Кроссплатформенность
- Подходит для браузера
Минусы:
- Значительно медленнее нативной реализации
- Асинхронность реализована через setImmediate (не настоящая
многопоточность)
bcrypt vs bcryptjs: сравнение
| Характеристика |
bcrypt (node.bcrypt.js) |
bcryptjs |
| Реализация |
C++ + Node bindings |
Чистый JavaScript |
| Производительность |
Высокая |
Ниже |
| Установка |
Требует сборки |
Без сборки |
| Асинхронность |
Настоящая (libuv) |
Эмуляция |
| Работа в браузере |
Нет |
Да |
| Надёжность |
Высокая |
Высокая |
Когда использовать bcrypt
- Серверные приложения на Node.js
- Высокая нагрузка (много запросов на аутентификацию)
- Production-среда
Причина: высокая производительность и настоящая
асинхронность.
Когда использовать bcryptjs
- Клиентские приложения (браузер)
- Прототипы и небольшие проекты
- Ограниченные среды без возможности компиляции
Причина: отсутствие нативных зависимостей.
Внутренние различия в
реализации
Несмотря на одинаковый API, различия кроются в деталях:
- bcrypt (native) использует системные потоки через
libuv → не блокирует основной поток Node.js
- bcryptjs выполняется в одном потоке → может
блокировать event loop при больших нагрузках
- В bcryptjs отсутствуют оптимизации уровня компилятора (SSE,
SIMD)
Безопасность и совместимость
Обе библиотеки:
- Генерируют совместимые хеши
- Поддерживают одинаковый формат (
$2a$,
$2b$)
- Могут проверять хеши друг друга
Это позволяет:
- Начать с bcryptjs и позже перейти на bcrypt без миграции данных
- Использовать bcryptjs на клиенте, а bcrypt на сервере
Влияние cost factor
Параметр cost (или rounds) определяет сложность:
bcrypt.hash(password, 12);
Рост сложности:
- 10 → ~100ms
- 12 → ~400ms
- 14 → ~1.5s
bcryptjs при тех же значениях будет работать заметно медленнее.
Практические рекомендации
- Для серверной аутентификации — использовать
bcrypt
- Для браузера —
bcryptjs
- Не использовать синхронные методы в production
- Подбирать cost factor исходя из допустимого времени ответа (~200–500
мс)
Альтернативы в экосистеме
Помимо bcrypt существуют более современные алгоритмы:
- argon2 — более устойчив к GPU-атакам
- scrypt — память-зависимый алгоритм
Тем не менее, bcrypt остаётся стандартом де-факто благодаря своей
проверенной надёжности и широкой поддержке.
Выбор реализации как
архитектурное решение
Выбор между bcrypt и bcryptjs определяется не только удобством, но и
архитектурой приложения:
- Нативные модули — выбор для backend-инфраструктуры
- Чистый JS — гибкость и переносимость
- Гибридный подход — оптимален для fullstack-приложений
Такое разделение позволяет эффективно балансировать между
производительностью, безопасностью и удобством разработки.