Криптографические функции выработки ключей (KDF — Key Derivation
Functions) решают задачу преобразования пароля в криптографически
стойкий ключ фиксированной длины. В экосистеме JavaScript и в библиотеке
Stanford JS Crypto Library (SJCL) чаще всего используются два подхода:
PBKDF2 и scrypt. Оба алгоритма предназначены для защиты от атак
перебором, но их устойчивость и стоимость вычислений в разных средах
существенно различаются.
Пароль как источник энтропии обладает низкой стойкостью и не подходит
для прямого использования в симметричных алгоритмах шифрования. KDF
решает три задачи:
- нормализация длины ключа под требования алгоритма (AES, HMAC и
др.)
- усложнение перебора за счёт увеличения вычислительной стоимости
- введение соли для защиты от радужных таблиц
В SJCL оба алгоритма реализуют эту модель, но с разной философией
нагрузки: PBKDF2 ориентирован на вычислительную сложность, scrypt — на
вычислительную и память одновременно.
PBKDF2 в SJCL
PBKDF2 (Password-Based Key Derivation Function 2) основан на
многократном применении HMAC (обычно HMAC-SHA256 или HMAC-SHA1). В SJCL
он реализуется через sjcl.misc.pbkdf2.
Основная идея — увеличение времени вычисления ключа путём
итераций:
var password = "example_password";
var salt = sjcl.random.randomWords(4);
var derivedKey = sjcl.misc.pbkdf2(password, salt, 10000, 256);
Основные параметры PBKDF2
- Пароль — исходная строка или битовый массив
- Соль — случайное значение для уникализации
результата
- Итерации — число повторений HMAC (ключевой параметр
сложности)
- Длина ключа — итоговый размер в битах
Характер вычислительной
модели
PBKDF2 увеличивает стоимость атаки линейно:
- удвоение числа итераций ≈ удвоение времени вычисления
- не требует значительного объёма памяти
Это делает алгоритм:
- удобным для серверов с контролируемой нагрузкой
- предсказуемым по производительности
- менее устойчивым к GPU/ASIC ускорению
scrypt в SJCL
scrypt разработан с целью противодействия аппаратному ускорению атак.
В SJCL он доступен через sjcl.misc.scrypt.
Пример использования:
var password = "example_password";
var salt = sjcl.random.randomWords(4);
var params = {
N: 16384,
r: 8,
p: 1
};
var derivedKey = sjcl.misc.scrypt(password, salt, params.N, params.r, params.p, 32);
Параметры scrypt
scrypt вводит три ключевых параметра:
- N (cost factor) — определяет количество итераций и
размер памяти (должен быть степенью двойки)
- r (block size) — влияет на размер внутренних блоков
памяти
- p (parallelization factor) — степень параллелизма
вычислений
Характер вычислительной
модели
scrypt сочетает две формы нагрузки:
- вычислительная (CPU-bound)
- память-ориентированная (memory-hard)
Ключевая особенность — значительное потребление памяти,
затрудняющее:
- GPU-ускорение
- ASIC-реализации
- параллельные атаки с высокой плотностью потоков
Рост стоимости атаки нелинеен: увеличение N приводит к
экспоненциальному росту требований к памяти.
Сравнение архитектур
PBKDF2 и scrypt
Вычислительная нагрузка
PBKDF2:
- зависит только от количества итераций
- оптимизируется за счёт параллельных вычислений
- хорошо масштабируется на CPU
scrypt:
- требует значительных объёмов памяти
- ограничивает параллелизм аппаратно
- хуже масштабируется на GPU
Устойчивость к аппаратным
атакам
PBKDF2:
- уязвим к GPU ускорению
- эффективен только при увеличении итераций
- не использует memory-hard свойства
scrypt:
- устойчив к GPU и ASIC за счёт памяти
- атака требует пропорционально больших ресурсов памяти
- считается более современным подходом
Производительность в
JavaScript
В среде браузера и Node.js наблюдаются различия:
PBKDF2:
- стабилен по времени выполнения
- предсказуем при ограниченных ресурсах
- подходит для массовых операций (логины, токены)
scrypt:
- значительно тяжелее по памяти
- может влиять на отзывчивость UI в браузере
- требует аккуратной настройки параметров N, r, p
Сценарии применения
Аутентификация пользователей
PBKDF2 чаще используется в системах, где:
- важна совместимость
- нагрузка высокая
- контроль над параметрами ограничен
Причина — стабильная производительность и широкая поддержка.
Хранение паролей с
высокой угрозой атак
scrypt применяется там, где:
- возможны оффлайн-атаки на хеши
- существует риск использования GPU-кластеров
- требуется максимальная стойкость при компрометации базы данных
Браузерные приложения
PBKDF2:
- предпочтителен для клиентских вычислений
- меньше влияет на производительность интерфейса
scrypt:
- применяется ограниченно
- требует оптимизации параметров для предотвращения блокировки потока
выполнения
Серверные системы
PBKDF2:
- подходит для масштабируемых систем
- легко контролировать нагрузку
scrypt:
- используется для хранения критичных секретов
- требует балансировки между безопасностью и ресурсами
Настройка параметров в SJCL
PBKDF2
Основной параметр — количество итераций:
- 1000 — минимальный уровень (устаревший)
- 10000–100000 — практический диапазон
- 100000+ — повышенная безопасность при достаточных ресурсах
scrypt
Рекомендованные диапазоны:
- N = 2^14 … 2^20
- r = 8 или 16
- p = 1 при стандартных нагрузках
Рост N резко увеличивает требования к памяти, что ограничивает
злоупотребление вычислениями.
Практическая разница в
атакующей модели
PBKDF2 защищает за счёт времени:
- атакующий вынужден повторять HMAC тысячи или миллионы раз
scrypt защищает за счёт времени и памяти:
- атакующий должен выделить значительный объём RAM на каждую
параллельную попытку
- GPU теряет преимущество из-за нехватки памяти на поток
Использование в контексте
SJCL
В SJCL оба алгоритма встроены в единый криптографический набор:
- PBKDF2 — базовый и универсальный механизм
- scrypt — усиленный механизм для сценариев повышенной угрозы
Выбор между ними определяется балансом:
- производительность
- доступные ресурсы
- модель атакующего
- критичность защищаемых данных