Синхронная проверка пароля: bcrypt.compareSync

Назначение синхронной проверки пароля

Метод bcrypt.compareSync используется для синхронного сравнения открытого пароля с ранее захешированным значением. Он выполняет проверку совпадения без асинхронного ожидания и блокирует поток выполнения до завершения операции.

С точки зрения безопасности алгоритм остаётся тем же, что и в асинхронных методах: применяется bcrypt-хеширование с солью и параметром стоимости (cost factor). Разница заключается исключительно в модели выполнения.


Как работает compareSync

Внутренний процесс проверки включает несколько этапов:

  1. Из переданного хеша извлекаются параметры:

    • версия bcrypt
    • cost factor
    • соль
  2. Открытый пароль повторно хешируется с использованием тех же параметров.

  3. Результат нового хеширования сравнивается с исходным хешем.

  4. Возвращается булево значение:

    • true — пароль совпадает
    • false — пароль неверен

Фактически происходит повторное вычисление bcrypt-хеша, а не простое сравнение строк.


Базовый пример использования

const bcrypt = require('bcryptjs');

const password = 'mySecretPassword';

// заранее сохранённый хеш (обычно хранится в базе данных)
const hash = '$2a$10$K7QJ1zq8v9x1nQ9dQ0l3Feu8b1w8V0v1xXzYzQmQmQmQmQmQmQmQ';

// синхронная проверка
const isMatch = bcrypt.compareSync(password, hash);

console.log(isMatch); // true или false

Особенности синхронного выполнения

compareSync работает в блокирующем режиме. Это означает, что поток Node.js останавливается до завершения вычислений.

Блокировка возникает из-за того, что bcrypt:

  • использует вычислительно дорогую функцию хеширования
  • намеренно замедлен для защиты от перебора
  • выполняет несколько итераций в зависимости от cost factor

Влияние на event loop

В среде Node.js синхронные операции bcrypt напрямую влияют на производительность приложения.

При использовании compareSync:

  • event loop блокируется
  • другие запросы не обрабатываются до завершения вычислений
  • увеличивается задержка ответа при высокой нагрузке

Это особенно критично в веб-серверах и API.


Сравнение с асинхронной проверкой

Характеристика compareSync compare (async)
Выполнение синхронное асинхронное
Блокировка event loop да нет
Производительность ниже при нагрузке выше
Простота выше требует callback/Promise

Когда допустимо использовать compareSync

Синхронная проверка оправдана только в ограниченных сценариях:

  • CLI-утилиты
  • скрипты миграции данных
  • тестирование
  • одноразовые операции без параллельных запросов

В серверных приложениях использование синхронной версии приводит к деградации масштабируемости.


Типичные ошибки при использовании

1. Использование в HTTP-обработчиках

app.post('/login', (req, res) => {
  const match = bcrypt.compareSync(req.body.password, user.hash);
  res.send(match);
});

Проблема заключается в блокировке обработки других запросов во время вычисления.


2. Хранение слишком слабого cost factor

Слишком низкое значение cost factor снижает время хеширования, но уменьшает устойчивость к brute-force атакам.


3. Повторное сравнение без необходимости

bcrypt уже включает соль и защиту от rainbow table атак, повторные проверки или кэширование результата сравнения не дают выигрыша в безопасности.


Внутренние особенности реализации

bcrypt использует алгоритм EksBlowfish, в котором:

  • ключ расширяется многократно
  • применяется итеративное шифрование
  • время вычисления регулируется cost factor (обычно от 10 до 14)

compareSync фактически вызывает ту же криптографическую процедуру, что и hashSync, но с уже заданной солью.


Производительность и cost factor

Время выполнения резко зависит от cost factor:

  • cost = 8 → быстро, но менее безопасно
  • cost = 12 → стандарт для большинства приложений
  • cost = 14+ → высокая нагрузка на CPU

Каждое увеличение cost на 1 примерно удваивает время вычисления.


Безопасные практики использования

  • избегается использование compareSync в веб-серверах с высокой нагрузкой
  • предпочтение отдаётся асинхронному bcrypt.compare
  • cost factor подбирается с учётом нагрузки системы
  • не выполняется повторное хеширование одного и того же значения без необходимости

Поведение при несовпадении паролей

При несовпадении bcrypt всё равно выполняет полное вычисление хеша. Это сделано намеренно для защиты от timing attacks, поскольку время выполнения не зависит от частичного совпадения строк.


Обработка ошибок

compareSync может выбрасывать исключения в случаях:

  • повреждённого хеша
  • некорректного формата строки
  • неподдерживаемой версии bcrypt
try {
  const result = bcrypt.compareSync(password, hash);
} catch (err) {
  console.error('Ошибка проверки пароля:', err.message);
}

Криптографическая устойчивость

С точки зрения безопасности compareSync не уступает асинхронной версии. Различие исключительно в модели исполнения, а не в криптографическом алгоритме.

Основные свойства:

  • устойчивость к brute-force атакам
  • использование уникальной соли
  • адаптивная сложность вычислений
  • защита от rainbow tables