PBKDF2 (Password-Based Key Derivation Function 2) — одна из наиболее широко используемых функций формирования ключей на основе пароля. Формально она описана в рекомендациях NIST SP 800-132 и RFC 8018 (PKCS #5 v2.1). Основная идея PBKDF2 заключается в многократном применении криптографической хеш-функции к паролю вместе со случайной солью для получения стойкого криптографического ключа.
NIST SP 800-132 определяет PBKDF2 как рекомендованный механизм для защиты паролей и генерации ключевого материала, при этом акцент делается на:
PBKDF2 не является алгоритмом хеширования паролей в узком смысле, а относится к классу key derivation functions (KDF), предназначенных для преобразования пароля в криптографический ключ фиксированной длины.
PBKDF2 строится на основе итеративного применения функции HMAC:
DK = PBKDF2(PRF, Password, Salt, c, dkLen)
где:
Упрощённо процесс можно описать как многократное повторение HMAC над результатами предыдущих вычислений, что делает каждый следующий шаг дороже по времени.
Ключевой параметр PBKDF2 — количество итераций c. Именно
он определяет устойчивость к перебору.
Рост числа итераций линейно увеличивает время вычисления, но не увеличивает требования к памяти.
NIST SP 800-132 подчёркивает несколько важных характеристик:
Однако в более поздних рекомендациях NIST (в частности SP 800-63B) отмечается, что PBKDF2 допустим, но не является наиболее устойчивым вариантом по сравнению с memory-hard функциями (например, scrypt или Argon2).
В Node.js PBKDF2 реализован через модуль crypto:
const crypto = require('crypto');
crypto.pbkdf2('password', 'salt', 100000, 64, 'sha256', (err, derivedKey) => {
if (err) throw err;
console.log(derivedKey.toString('hex'));
});
Синхронная версия:
const key = crypto.pbkdf2Sync('password', 'salt', 100000, 64, 'sha256');
Эта реализация соответствует стандарту PKCS #5 v2.1 и совместима с PBKDF2-реализациями в других языках.
bcrypt.js реализует алгоритм bcrypt, который принципиально отличается от PBKDF2:
Несмотря на различия, оба алгоритма решают одну задачу — безопасное хеширование паролей.
Совместимость между ними отсутствует на уровне формата:
Причина заключается в различной структуре выходного значения и способе хранения параметров.
PBKDF2:
bcrypt:
В современных системах это приводит к разной устойчивости к специализированным атакам:
PBKDF2 обычно хранится в виде:
iterations:salt:derivedKey
или в Base64/hex кодировке.
bcrypt использует собственный формат:
$2b$12$<salt><hash>
Где:
$2b$ — версия алгоритма12 — cost factorsalt встроен в строкуЭта разница делает невозможной прямую интероперабельность.
PBKDF2 часто применяется в следующих сценариях:
bcrypt.js применяется:
PBKDF2 остаётся допустимым, но его ограничения связаны с архитектурой:
bcrypt частично компенсирует эти недостатки за счёт структуры EksBlowfish, но также не является наиболее современным решением.
В современных криптографических практиках всё чаще рассматриваются альтернативы:
Тем не менее PBKDF2 сохраняет статус стандарта NIST и широко используется в корпоративных и государственных системах.
В некоторых архитектурах PBKDF2 и bcrypt используются совместно:
Такой подход позволяет разделить:
При этом важно учитывать, что миграция между ними невозможна без повторного хеширования паролей в момент входа пользователя.
bcrypt.js, несмотря на устаревающую архитектуру, предоставляет более унифицированный формат хранения и проверки паролей, что делает его удобнее в веб-среде.