bcrypt.hash в bcrypt.js — основной способ создания
криптографически стойкого хеша пароля в асинхронном режиме с
использованием callback-функции. Асинхронный вариант критически важен
для Node.js-приложений, так как позволяет не блокировать event loop при
вычислении дорогостоящего хеша.
bcrypt.hash(data, saltOrRounds, callback)
Где:
data — исходная строка (обычно пароль)saltOrRounds — либо готовая соль, либо число раундов
генерации солиcallback — функция обратного вызоваCallback имеет стандартную форму:
function(err, hash)
err — ошибка (если произошла)hash — итоговый bcrypt-хешНаиболее распространённый сценарий — хеширование пароля пользователя при регистрации.
const bcrypt = require('bcryptjs');
const password = 'user_password_123';
bcrypt.hash(password, 10, (err, hash) => {
if (err) {
console.error('Ошибка хеширования:', err);
return;
}
console.log('Хеш пароля:', hash);
});
Число 10 обозначает количество раундов соль-генерации
(cost factor). Чем выше значение, тем медленнее вычисление и выше
устойчивость к перебору.
В bcrypt соль не просто случайная строка — она генерируется на основе количества раундов:
bcrypt.hash(password, 12, callback)
Каждое увеличение на 1 примерно удваивает время вычисления хеша.
Асинхронный стиль требует обязательной обработки ошибки первым параметром:
bcrypt.hash(password, 10, (err, hash) => {
if (err) {
// обработка ошибок (например, логирование)
return;
}
// безопасное использование hash
});
Типичные причины ошибок:
Иногда требуется явное управление солью:
bcrypt.genSalt(12, (err, salt) => {
if (err) return;
bcrypt.hash(password, salt, (err, hash) => {
if (err) return;
console.log(hash);
});
});
Такой подход полезен, когда:
bcrypt.hash выполняется вне основного потока JavaScript, используя внутренние механизмы C++ binding (через bcrypt-реализацию). Это означает:
Однако при высокой нагрузке:
const bcrypt = require('bcryptjs');
function registerUser(email, password, callback) {
bcrypt.hash(password, 10, (err, hash) => {
if (err) return callback(err);
const user = {
email,
passwordHash: hash
};
// имитация сохранения в БД
callback(null, user);
});
}
bcrypt.hash(password, 10, (err, hash) => {
console.log(hash); // опасно: err не проверяется
});
bcrypt.hash(password, 4, callback);
Такое значение делает хеш уязвимым к перебору.
Длинные синхронные операции внутри callback могут нивелировать преимущество асинхронности.
bcrypt намеренно медленный алгоритм. Его цель — защита от brute-force атак.
Факторы влияния:
При масштабировании систем обычно применяются:
При большом количестве вызовов:
bcrypt.hash(password, 12, callback);
возможны:
Поэтому bcrypt часто выносится в отдельные воркеры или микросервисы.
bcrypt.hash ожидает:
string или Buffer в качестве пароляНекорректные значения:
bcrypt.hash(null, 10, callback); // ошибка
bcrypt.hash(undefined, 10, callback); // ошибка
Перед вызовом обычно выполняется валидация:
if (typeof password !== 'string' || password.length === 0) {
return callback(new Error('Invalid password'));
}
Каждый вызов bcrypt.hash генерирует уникальную соль
автоматически (если передано число rounds), поэтому:
bcrypt.hash('password', 10, ...)
bcrypt.hash('password', 10, ...)
дают разные результаты, что обеспечивает:
app.post('/register', (req, res) => {
const { password } = req.body;
bcrypt.hash(password, 10, (err, hash) => {
if (err) {
return res.status(500).send('Ошибка сервера');
}
// сохранение hash в БД
res.status(201).json({ success: true });
});
});
При этом в сложных цепочках callback-версия приводит к:
Каждый вызов bcrypt.hash полностью независим:
Это важно учитывать при массовой обработке данных (например, миграции пользователей).