В bcrypt соль представляет собой не просто случайный набор байтов, а строго структурированную строку, содержащую метаданные алгоритма и параметры сложности. Она кодируется в виде строки формата:
$2b$12$C6UzMDM.H6dfI/f/IKcEeO
Структура этой строки:
$2b$ — версия алгоритма bcrypt12$ — cost factor (число раундов, влияющее на
вычислительную сложность)Именно эта строка целиком и передаётся в функцию хеширования как готовая соль.
Ключевой момент: bcrypt.js не требует разбирать соль вручную. Она воспринимается как атомарный объект конфигурации алгоритма.
В bcrypt.js функция hash имеет перегруженную сигнатуру.
Один из поддерживаемых вариантов — передача уже сгенерированной
соли:
bcrypt.hash(password, salt)
где:
password — исходная строка пароляsalt — заранее подготовленная строка соли в формате
bcryptПример:
import bcrypt from "bcryptjs";
const salt = "$2b$10$KIXQ9m3Y7V5Yz1Q8ePz0eu"; // заранее сохранённая соль
const password = "mySecretPassword";
const hash = bcrypt.hashSync(password, salt);
console.log(hash);
В этом случае библиотека не генерирует новую соль, а использует предоставленную. Это означает, что итоговый хеш будет полностью детерминированным при одинаковых входных данных.
Обычно используется другой сценарий:
const salt = bcrypt.genSaltSync(10);
const hash = bcrypt.hashSync(password, salt);
или более короткая форма:
const hash = bcrypt.hashSync(password, 10);
Во втором случае библиотека сама:
Передача готовой соли отключает этот этап и переносит контроль над параметрами на разработчика.
Использование заранее подготовленной соли встречается значительно реже, чем автоматическая генерация, но имеет специфические применения:
Если используется фиксированная соль, один и тот же пароль всегда даёт одинаковый хеш:
const salt = "$2b$10$aaaaaaaaaaaaaaaaaaaaaa";
bcrypt.hashSync("password123", salt);
bcrypt.hashSync("password123", salt); // идентичный результат
Это может использоваться в тестировании или миграциях, где требуется детерминированный результат.
При переносе пользователей из систем с нестандартной схемой хеширования иногда сохраняется исходная соль. В таких случаях bcrypt.js используется как слой совместимости, а не как генератор новых данных.
Переданная соль фиксирует cost factor. Например:
$2b$08$... — быстрее, но слабее$2b$12$... — медленнее, но устойчивееТаким образом можно унифицировать поведение системы без зависимости
от genSalt.
При вызове:
bcrypt.hash(password, salt)
библиотека выполняет следующие шаги:
Важно: итоговый хеш всегда содержит соль внутри себя, даже если она была передана извне.
Нельзя передавать только часть соли:
bcrypt.hashSync(password, "10"); // ошибка логики
bcrypt.js ожидает полную строку формата $2b$....
Если одна и та же соль применяется ко многим паролям, исчезает уникальность хешей:
const salt = "$2b$10$fixedSalt.............";
bcrypt.hashSync("user1pass", salt);
bcrypt.hashSync("user2pass", salt);
Это снижает устойчивость к атаке через предварительно вычисленные таблицы (rainbow tables).
bcrypt уже включает соль внутрь хеша. Разделение этих данных:
Аналогичная логика действует и в асинхронной версии:
bcrypt.hash(password, salt, (err, hash) => {
console.log(hash);
});
или через Promise:
const hash = await bcrypt.hash(password, salt);
В обоих случаях переданная строка соли используется напрямую без генерации новой.
Технически соль можно сформировать через genSalt, а
затем повторно использовать:
const salt = await bcrypt.genSalt(12);
const hash = await bcrypt.hash(password, salt);
Или сохранить её для повторного применения:
const storedSalt = await bcrypt.genSalt(12);
// позже
const hash = await bcrypt.hash(password, storedSalt);
Однако в большинстве сценариев хранения пользователей такой подход не применяется, поскольку bcrypt уже инкапсулирует соль внутри результата хеширования.
При одинаковом пароле:
Пример:
const salt1 = await bcrypt.genSalt(10);
const salt2 = await bcrypt.genSalt(10);
bcrypt.hashSync("password", salt1);
bcrypt.hashSync("password", salt2);
Результаты будут различаться из-за различий в случайной части соли.
| Подход | Генерация соли | Поведение |
|---|---|---|
hash(password, 10) |
автоматическая | безопасный стандарт |
hash(password, salt) |
ручная | полный контроль |
| повторное использование соли | фиксированная | детерминированность |
Соль в bcrypt выполняет сразу несколько функций:
Передача готовой соли не меняет криптографическую модель алгоритма, а лишь фиксирует входные параметры функции EksBlowfish.