Детерминированность против стохастичности в контексте безопасности

В классической криптографии под детерминированностью понимается свойство функции выдавать одинаковый результат при одинаковых входных данных. Для обычных хеш-функций это базовая характеристика: один и тот же вход всегда даёт один и тот же хеш.

В контексте паролей такая предсказуемость становится уязвимостью. Если функция полностью детерминирована, злоумышленник может заранее вычислить хеши популярных паролей и сопоставлять их с базой данных — так работают радужные таблицы.

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


Стохастичность как источник криптографической стойкости

Стохастичность в криптографии — это намеренное введение случайности в процесс преобразования данных. В случае bcrypt.js она реализуется через генерацию соли (salt).

Соль — это случайная строка, которая добавляется к паролю до выполнения хеширования. Благодаря этому одинаковые пароли почти никогда не приводят к одинаковым хешам.

Ключевая особенность:

  • алгоритм хеширования остаётся детерминированным
  • входные данные становятся уникальными за счёт случайной соли
  • результат перестаёт быть воспроизводимым без знания соли

Именно сочетание детерминизма и стохастичности создаёт криптографическую устойчивость bcrypt.


Роль соли в bcrypt.js

В bcrypt.js соль не является дополнительным параметром «для усложнения». Она — обязательная часть алгоритма.

Структура работы выглядит следующим образом:

  1. генерируется случайная соль
  2. соль объединяется с паролем
  3. выполняется многократное хеширование
  4. результат включает в себя и соль, и сам хеш

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


Почему одинаковый пароль даёт разные хеши

Если два пользователя используют одинаковый пароль, bcrypt.js всё равно создаёт разные хеши. Причина в том, что для каждого вызова используется новая случайная соль.

Пример логики:

  • пароль: password123
  • соль A → хеш A
  • соль B → хеш B

Хотя исходная строка идентична, итоговые значения полностью различаются.

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


Детерминизм внутри bcrypt и его ограничение

Несмотря на внешнюю случайность, bcrypt остаётся строго детерминированным алгоритмом при фиксированных входных параметрах:

  • пароль
  • соль
  • cost factor (work factor)

Если все три значения совпадают, результат всегда одинаков.

Это означает:

  • bcrypt не «случайный» в математическом смысле
  • стохастичность возникает только на уровне генерации соли
  • сам алгоритм полностью воспроизводим

Такое разделение критично: оно позволяет проверять пароль без хранения исходного значения.


Cost factor и вычислительная предсказуемость

Важной частью модели bcrypt является параметр cost factor — степень вычислительной сложности.

Он задаёт количество итераций внутреннего шифрования. При одинаковых входных данных:

  • увеличение cost factor линейно увеличивает время вычисления
  • результат остаётся детерминированным
  • атаки перебора становятся существенно дороже

Это добавляет ещё один уровень «контролируемой предсказуемости»: алгоритм всегда ведёт себя одинаково, но его стоимость выполнения заранее известна и регулируема.


Проблема радужных таблиц и роль стохастичности

Без соли хеширование паролей подвержено атаке радужных таблиц — предварительно вычисленных наборов значений.

В детерминированной системе:

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

bcrypt.js разрушает эту модель:

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

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


Формат итогового значения bcrypt

Результирующая строка bcrypt содержит несколько компонентов:

  • версия алгоритма
  • cost factor
  • соль
  • хеш

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

При проверке выполняется повторное детерминированное вычисление с извлечённой солью и сравнением результата.


Сравнение с полностью детерминированными хешами

Обычные криптографические функции вроде SHA-256:

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

bcrypt.js:

  • добавляет обязательную случайную соль
  • сохраняет детерминированность внутри вычисления
  • делает внешний результат стохастическим

Разница заключается не в алгоритме хеширования как таковом, а в модели входных данных.


Иллюзия случайности и криптографическая строгость

Стохастичность bcrypt не означает непредсказуемость самого алгоритма. Случайность ограничена только этапом генерации соли. После этого процесс становится полностью детерминированным.

Такое сочетание даёт важный эффект:

  • невозможность восстановления исходного пароля из хеша
  • невозможность массового сопоставления хешей
  • сохранение проверяемости через повторное вычисление

В результате система одновременно остаётся проверяемой и непредсказуемой на уровне входных данных.