Promise-ориентированный API в bcrypt.js позволяет выполнять хеширование и проверку паролей без использования коллбеков, опираясь на стандартный механизм Promise и синтаксис async/await. Это упрощает управление асинхронным кодом и делает цепочки операций более читаемыми, особенно в серверных приложениях Node.js.
В основе асинхронного поведения bcrypt.js лежит перегрузка функций: при отсутствии коллбека библиотека возвращает Promise, что позволяет использовать её в современных архитектурах без дополнительной обёртки.
Основные функции библиотеки поддерживают Promise-режим:
bcrypt.hash(data, saltRounds)bcrypt.compare(data, encrypted)bcrypt.genSalt(saltRounds)Если коллбек не передаётся, результатом вызова становится Promise, который резолвится либо итоговым значением, либо ошибкой.
const bcrypt = require('bcryptjs');
bcrypt.hash('password123', 10)
.then(hash => {
console.log(hash);
})
.catch(err => {
console.error(err);
});
Promise-ориентированный интерфейс делает код линейным и избавляет от вложенных коллбеков, характерных для классического Node.js.
Хеширование пароля — одна из наиболее ресурсоёмких операций в bcrypt. В отличие от простых криптографических функций, bcrypt специально замедлен за счёт параметра cost factor (число раундов), чтобы усложнить brute-force атаки.
Использование async/await позволяет интегрировать этот процесс в поток выполнения без блокировки логики приложения:
const bcrypt = require('bcryptjs');
async function createUserPassword(password) {
const hash = await bcrypt.hash(password, 12);
return hash;
}
Число 12 определяет уровень сложности. Каждый
дополнительный шаг увеличивает вычислительную стоимость примерно в два
раза.
При хешировании bcrypt автоматически генерирует соль, если она не была передана явно. В Promise-версии это поведение сохраняется.
const hash = await bcrypt.hash('securePassword', 10);
Внутри происходит:
Результат содержит всю необходимую информацию для последующей проверки пароля, включая соль и cost factor.
Сравнение введённого пароля с хешем также реализовано в асинхронном виде:
const bcrypt = require('bcryptjs');
async function verifyPassword(password, hash) {
const match = await bcrypt.compare(password, hash);
return match;
}
Функция compare автоматически извлекает соль из хеша и
выполняет повторное вычисление, после чего сравнивает результаты в
безопасном режиме, предотвращающем timing-атаки.
При использовании async/await ошибки становятся обычными исключениями, что упрощает контроль потока выполнения:
async function safeHash(password) {
try {
const hash = await bcrypt.hash(password, 10);
return hash;
} catch (err) {
throw new Error('Ошибка хеширования');
}
}
В Promise-цепочках аналогичная логика реализуется через
catch.
bcrypt.js написан на чистом JavaScript и не использует нативные биндинги C/C++. Это влияет на характер асинхронности:
Это отличает bcrypt.js от реализации bcrypt, которая
использует нативные расширения и может распределять нагрузку более
эффективно через libuv thread pool.
Promise-интерфейс особенно полезен в следующих случаях:
Пример в HTTP-обработчике:
app.post('/register', async (req, res) => {
const { password } = req.body;
const hash = await bcrypt.hash(password, 10);
await saveUser({ password: hash });
res.sendStatus(201);
});
bcrypt.js хорошо сочетается с другими асинхронными операциями:
bcrypt.hash(password, 10)
.then(hash => database.save(hash))
.then(() => sendResponse())
.catch(err => handleError(err));
Такой подход позволяет выстраивать линейные цепочки обработки данных без вложенных структур.
При выборе параметра cost factor важно учитывать баланс между безопасностью и производительностью:
Асинхронный интерфейс не ускоряет само хеширование, но предотвращает блокировку основного потока, что критично для серверов с большим количеством одновременных запросов.
Оба подхода эквивалентны по функциональности, но отличаются читаемостью:
async/await:
const hash = await bcrypt.hash(password, 10);
Promise:
bcrypt.hash(password, 10).then(hash => hash);
В сложных сценариях с несколькими последовательными операциями async/await обеспечивает более предсказуемую структуру кода и упрощает обработку ошибок через try/catch.