Отличия bcrypt.js от нативного node.bcrypt.js под капотом

bcrypt.js и node.bcrypt.js реализуют один и тот же криптографический алгоритм — bcrypt, основанный на Blowfish-шифре с адаптивной стоимостью вычислений (cost factor). Однако их фундаментальное отличие заключается не в математике хэширования, а в уровне реализации и окружении выполнения.

bcrypt.js — это чистая JavaScript-реализация алгоритма bcrypt. node.bcrypt.js — это обёртка над нативной C/C++ реализацией (bindings к библиотеке libbcrypt через node-gyp).

Это различие определяет поведение библиотек во всех ключевых аспектах: производительность, переносимость, модель выполнения и взаимодействие с системными ресурсами.


Нативная реализация node.bcrypt.js: C++ слой и системные зависимости

node.bcrypt.js использует нативный код, который компилируется под конкретную платформу во время установки пакета.

Ключевые особенности:

  • криптографические операции выполняются в C/C++ слое
  • используется библиотека bcrypt (исторически OpenBSD bcrypt)
  • сборка через node-gyp, зависящая от Python, make и C++ toolchain
  • выполнение хэширования происходит вне JavaScript-интерпретатора

Влияние на производительность

Нативный код:

  • значительно быстрее при вычислении хэшей
  • эффективнее использует CPU инструкции
  • снижает нагрузку на V8

Асинхронные вызовы реализованы через libuv thread pool, что означает:

  • хэширование не блокирует event loop напрямую
  • но занимает системные потоки из общего пула Node.js

Синхронные методы (например hashSync) блокируют поток выполнения полностью.


bcrypt.js: чистая JavaScript-реализация

bcrypt.js реализует весь алгоритм bcrypt на JavaScript без использования нативных расширений.

Это приводит к принципиально иному поведению:

  • отсутствует необходимость в компиляции
  • нет зависимостей от системных библиотек
  • одинаковое поведение на всех платформах (Node.js, браузер, edge-окружения)

Внутреннее устройство

bcrypt.js эмулирует:

  • Blowfish key schedule
  • EksBlowfishSetup (expensive key setup)
  • экспоненциальное увеличение вычислительной сложности через cost factor

Вся криптография выполняется средствами JavaScript, что делает библиотеку:

  • полностью переносимой
  • независимой от платформы
  • но существенно более медленной

Производительность: разрыв в вычислительной стоимости

Разница в скорости — ключевой фактор выбора между реализациями.

node.bcrypt.js

  • использует оптимизированные C++ операции
  • выполняет хэширование в десятки раз быстрее
  • эффективен при высоких нагрузках (API, микросервисы)

bcrypt.js

  • медленнее из-за интерпретируемого JavaScript
  • рост времени вычисления особенно заметен при cost ≥ 10
  • может быть в 10–100 раз медленнее в зависимости от окружения

Причина — отсутствие низкоуровневых оптимизаций CPU и SIMD-инструкций.


Влияние на event loop и модель конкурентности

node.bcrypt.js

  • асинхронные вызовы уходят в thread pool libuv
  • event loop остаётся свободным
  • возможна деградация при исчерпании thread pool (по умолчанию 4 потока)

bcrypt.js

  • вычисления выполняются в основном потоке JavaScript
  • полностью блокирует event loop при хэшировании
  • особенно критично в серверных приложениях

Это делает bcrypt.js потенциально непригодным для высоконагруженных backend-систем без дополнительной изоляции (worker threads).


Портируемость и среда выполнения

bcrypt.js

Главное преимущество — универсальность:

  • работает в браузере
  • работает в Node.js без сборки
  • подходит для edge runtime (Cloudflare Workers, Deno-совместимые среды)
  • не требует native modules

node.bcrypt.js

Ограничения:

  • требует Node.js runtime
  • требует сборки C++ аддона
  • может ломаться при смене версии Node.js или платформы
  • плохо подходит для serverless с ограничениями на native modules

Безопасность реализации

Обе библиотеки реализуют один и тот же алгоритм bcrypt, поэтому:

  • стойкость к brute-force идентична при одинаковом cost factor
  • выходной формат хэша совместим

Однако различия есть в окружении выполнения:

node.bcrypt.js

  • использует проверенные криптографические C-библиотеки
  • меньше риск ошибок реализации на уровне алгоритма
  • зависит от корректности сборки нативного кода

bcrypt.js

  • полностью независимая реализация алгоритма
  • повышенная вероятность ошибок на уровне JS-оптимизаций
  • больше поверхность атаки через реализацию (implementation risk), а не сам алгоритм

Генерация соли и источники энтропии

node.bcrypt.js

  • использует crypto.randomBytes
  • опирается на системный CSPRNG (cryptographically secure PRNG)

bcrypt.js

  • также использует crypto модуль Node.js, если доступен
  • в браузере — window.crypto.getRandomValues
  • в fallback-сценариях зависит от окружения (что критично учитывать)

Совместимость хэшей

Формат bcrypt-хэша одинаков:

$2a$10$..............................

Обе реализации:

  • генерируют совместимые строки
  • могут проверять хэши друг друга
  • поддерживают одинаковую структуру salt + cost + hash

Разница не в формате, а в скорости и окружении выполнения.


Размер и зависимость проекта

node.bcrypt.js

  • включает native bindings
  • увеличивает размер node_modules
  • требует build tools
  • может усложнять CI/CD

bcrypt.js

  • чистый JS пакет
  • минимальные зависимости
  • легко устанавливается и деплоится

Поведение при ошибках и стабильность

node.bcrypt.js

  • ошибки могут возникать на этапе компиляции
  • возможны проблемы ABI совместимости
  • чувствителен к версии Node.js

bcrypt.js

  • ошибки ограничены JavaScript runtime
  • более предсказуемое поведение в разных средах
  • проще дебажить

Практическое различие под нагрузкой

При массовых операциях:

  • node.bcrypt.js масштабируется через системные потоки
  • bcrypt.js масштабируется только через горизонтальное увеличение процессов или worker threads

Это приводит к разной архитектуре приложений:

  • node.bcrypt.js — server-centric модель
  • bcrypt.js — environment-agnostic модель

Итоговое инженерное различие

Разделение можно описать на уровне системной инженерии:

  • node.bcrypt.js — это высокопроизводительная обёртка над нативной криптографией, оптимизированная для серверного Node.js окружения
  • bcrypt.js — это переносимая программная реализация алгоритма bcrypt, оптимизированная под универсальность, а не скорость

Они решают одну задачу разными слоями абстракции: один через системные ресурсы, другой — через чистую вычислительную модель JavaScript runtime