При работе с библиотекой password-hash в JavaScript результатом хеширования пароля становится строка фиксированного формата, предназначенная для хранения и последующей проверки. Основная идея заключается в объединении всех критически важных параметров в одной строке, чтобы обеспечить воспроизводимость проверки и исключить необходимость хранения отдельных полей в базе данных.
Выходная строка формируется по схеме:
algorithm:iterations:salt:hash
или в более упрощённом варианте, если количество итераций фиксировано:
algorithm:salt:hash
Каждый элемент имеет строго определённое назначение:
algorithm — идентификатор алгоритма хеширования iterations — число итераций (если используется PBKDF2 или аналогичный алгоритм) salt — криптографическая соль hash — итоговый хеш пароля
Разделителем выступает двоеточие :. В некоторых
реализациях допускается альтернативный разделитель (например,
$), но в контексте данной библиотеки стандартом считается
именно :.
Поле algorithm необходимо для обеспечения обратной
совместимости. Даже если система в будущем перейдёт на более стойкий
алгоритм, старые записи останутся валидными.
Примеры значений:
pbkdf2argon2idbcryptПри проверке пароля библиотека сначала извлекает это поле и выбирает соответствующий механизм верификации.
Поле iterations определяет вычислительную сложность
алгоритма.
Пример:
pbkdf2:100000:...
Чем выше значение, тем:
В некоторых реализациях это поле может отсутствовать, если алгоритм фиксирует параметры внутри себя (например, bcrypt).
salt — это случайная строка, генерируемая для каждого
пароля индивидуально. Она предотвращает использование радужных таблиц и
делает одинаковые пароли различными на уровне хеша.
Особенности соли:
Пример:
pbkdf2:100000:Qx7m9Pz8aL...:...
hash — результат применения выбранного алгоритма к
паролю с использованием соли и заданного числа итераций.
Это значение:
Пример итоговой строки:
pbkdf2:100000:Qx7m9Pz8aL:8f3a91c4d9b7e2a1f0c6
Объединение всех параметров в одной строке решает несколько задач:
Упрощение хранения Достаточно одного поля в базе данных вместо нескольких колонок.
Самодостаточность данных Каждая строка содержит всё необходимое для проверки пароля.
Гибкость обновлений алгоритмов Можно менять алгоритм без миграции старых записей.
Совместимость версий Разные версии системы могут корректно обрабатывать один и тот же формат.
Процесс проверки включает разбиение строки на компоненты:
const [algorithm, iterations, salt, hash] = stored.split(':');
Далее выполняется повторное хеширование введённого пароля с
использованием извлечённых параметров. Полученный результат сравнивается
с сохранённым hash.
Важно учитывать, что сравнение должно выполняться в константное время для защиты от timing-атак.
При использовании бинарных данных возникает необходимость кодирования:
Пример Base64-формата:
argon2id:3:U2FsdFN0cmluZw==:bXlIYXNoVmFsdWU=
При этом важно соблюдать единый стандарт кодирования внутри системы.
Несмотря на универсальность, строковый формат имеет ограничения:
Для решения этих проблем иногда вводят версионность формата:
v1:pbkdf2:100000:salt:hash
Добавление версии позволяет изменять формат без потери совместимости.
Пример расширенного формата:
v2:argon2id:3:Qx7m9Pz8aL:8f3a91c4d9b7e2a1f0c6
Поле версии:
При парсинге строки необходимо учитывать:
Пример базовой проверки:
if (parts.length < 4) {
throw new Error('Invalid hash format');
}
Структура algorithm:salt:hash является компромиссом
между:
Она позволяет унифицировать работу с разными криптографическими алгоритмами без изменения логики приложения, сводя всю сложность к одной строке фиксированного формата.