Политика паролей должна определяться до момента хеширования, а не после него. Любая попытка «сначала захешировать, потом проверить» приводит к фиксации слабых, предсказуемых или даже намеренно вредных значений в базе, после чего исправить ситуацию становится значительно сложнее. В связке с bcrypt.js это особенно важно, потому что алгоритм рассчитан на дорогую вычислительную операцию, и повторное изменение стратегии защиты уже существующих паролей требует миграции данных или принудительной смены паролей.
bcrypt.js применяется как реализация адаптивного хеширования паролей,
где ключевым параметром является cost factor (число раундов
соль+хеширования). Но сам по себе bcrypt не решает задачу качества
пароля. Он лишь гарантирует, что даже хороший или плохой пароль будет
храниться в виде устойчивого к перебору хеша. Поэтому вся логика
«допуска или запрета» должна выполняться до вызова
hash.
Перед тем как пароль попадёт в bcrypt, он должен пройти несколько уровней проверки:
bcrypt.js не участвует в этих этапах. Его задача начинается строго после того, как входное значение признано допустимым.
Минимальный уровень политики обычно включает:
Чрезмерно строгие правила (например, обязательные символы всех
категорий) часто приводят к обратному эффекту — пользователи начинают
генерировать предсказуемые шаблоны вроде Aa1!Aa1!.
Типичный поток обработки выглядит следующим образом:
Пример проверки перед хешированием:
function validatePassword(password) {
if (typeof password !== 'string') {
throw new Error('Пароль должен быть строкой');
}
if (password.length < 10) {
throw new Error('Пароль слишком короткий');
}
if (/^\d+$/.test(password)) {
throw new Error('Пароль не должен состоять только из цифр');
}
if (/^(password|123456|qwerty)$/i.test(password)) {
throw new Error('Слишком распространённый пароль');
}
return true;
}
Только после успешного прохождения проверки выполняется хеширование:
import bcrypt from 'bcryptjs';
async function createPasswordHash(password) {
validatePassword(password);
const saltRounds = 12;
const hash = await bcrypt.hash(password, saltRounds);
return hash;
}
Хеш bcrypt необратим. После выполнения операции:
Если политика меняется, единственный путь — заставить пользователя сменить пароль. Поэтому логика контроля должна находиться строго до хеширования.
Часто игнорируемый, но критически важный этап — нормализация строки перед проверкой и хешированием.
Проблемы, которые решает нормализация:
Пример:
function normalizePassword(password) {
return password
.normalize('NFKC')
.trim();
}
Нормализация должна выполняться до любых проверок и до bcrypt.hash, иначе возможны ситуации, когда одинаковые пароли дают разные хеши.
Политика безопасности часто включает проверку пароля на наличие в базах утечек. Это не обязанность bcrypt.js, но важный элемент перед хешированием.
Распространённые подходы:
Логика остаётся той же: проверка до хеширования.
bcrypt.js предоставляет параметр cost factor:
const saltRounds = 10;
Повышение значения:
Но важно понимать: увеличение saltRounds не компенсирует слабый пароль. Это лишь замедляет взлом, но не устраняет саму уязвимость.
Современные системы часто комбинируют:
Пример подхода:
При этом политика паролей остаётся неизменной для всех уровней — меняется только стоимость хеширования.
Распространённые ошибки при работе с bcrypt.js:
1. Хеширование до валидации Пароль сразу передаётся в bcrypt без проверки качества.
2. Проверка хеша вместо пароля Попытка анализировать результат bcrypt.hash для оценки сложности.
3. Отсутствие нормализации Одинаковые по смыслу пароли дают разные хеши из-за Unicode-различий.
4. Слишком слабая политика Ограничение только длины без проверки предсказуемости.
5. Жёсткая политика без анализа UX Пользователи обходят правила предсказуемыми шаблонами.
При изменении требований возникает проблема уже сохранённых паролей. bcrypt.js решает это частично через повторное хеширование при входе:
if (bcrypt.getRounds(hash) < 12) {
const newHash = await bcrypt.hash(password, 12);
}
Таким образом, политика постепенно обновляется без массового сброса паролей.
Корректная последовательность:
Любое отклонение от этого порядка снижает устойчивость системы.
bcrypt.js отвечает за стойкость хранения, но не за качество входных данных. Политика паролей — это слой до криптографии, а не внутри неё. Чем раньше происходит отсеивание слабых значений, тем меньше вычислительных и организационных затрат возникает в дальнейшем.