Пароли сами по себе не подходят для использования в качестве криптографических ключей, поскольку обладают низкой энтропией, предсказуемой структурой и часто повторяются в различных системах. Прямое применение строки пароля в алгоритмах шифрования приводит к уязвимостям, связанным с перебором, словарными атаками и утечками через радужные таблицы. Для устранения этих проблем применяется класс алгоритмов, называемых KDF (Key Derivation Function) — функций вывода ключа.
Функция вывода ключа преобразует пользовательский пароль в криптографически стойкий ключ фиксированной длины. Основная задача заключается не только в преобразовании строки в бинарный формат, но и в значительном усложнении процесса подбора исходного пароля.
Ключевые свойства корректно реализованного KDF:
Использование пароля напрямую в AES или других симметричных алгоритмах приводит к нескольким проблемам:
Криптографический ключ должен быть случайным по свойствам и иметь равномерное распределение битов, чего обычные пароли не обеспечивают.
В библиотеке Crypto-js чаще всего используется PBKDF2 (Password-Based Key Derivation Function 2). Алгоритм основан на многократном применении HMAC с заданной хэш-функцией.
Основная идея заключается в итеративном усложнении вычисления ключа:
Формально PBKDF2 строится на следующем принципе:
= (P, S, c, dkLen)
где:
Соль представляет собой случайную последовательность байт, добавляемую к паролю перед вычислением хэша. Основная функция соли — предотвращение предварительно вычисленных атак.
Без соли одинаковые пароли дают одинаковые ключи, что создаёт уязвимость при массовом анализе данных. Соль делает каждый результат уникальным даже при совпадающих паролях.
Свойства корректной соли:
Количество итераций напрямую влияет на вычислительную сложность алгоритма. Каждая итерация увеличивает время генерации ключа как для легитимного пользователя, так и для атакующего.
Модель роста сложности:
T c
где:
Рост итераций линейно увеличивает стоимость перебора, что делает массовые атаки экономически нецелесообразными.
Библиотека Crypto-js предоставляет встроенную реализацию PBKDF2, использующую различные хэш-функции, включая SHA1, SHA256 и SHA512.
Пример использования:
import CryptoJS from "crypto-js";
const password = "strong_password";
const salt = CryptoJS.lib.WordArray.random(16);
const key = CryptoJS.PBKDF2(password, salt, {
keySize: 256 / 32,
iterations: 100000,
hasher: CryptoJS.algo.SHA256
});
console.log(key.toString());
В данном процессе:
Результат PBKDF2 всегда нормализуется до заданной длины. Это необходимо для согласованности с алгоритмами шифрования, которые требуют строго определённого размера ключа (AES-128, AES-256 и т.д.).
Формирование ключа можно представить как усечение или расширение результата хэш-функции через итеративное накопление блоков.
Сгенерированный ключ используется в алгоритмах шифрования, например AES. В связке Crypto-js процесс выглядит следующим образом:
const iv = CryptoJS.lib.WordArray.random(16);
const encrypted = CryptoJS.AES.encrypt("secret data", key, {
iv: iv
});
Использование KDF обеспечивает, что даже слабый пароль превращается в криптографически приемлемый ключ.
Основная ценность KDF заключается в усложнении офлайн-атаки. При наличии зашифрованного текста атакующий вынужден проверять каждый пароль через полный процесс PBKDF2, включая все итерации.
Сложность атаки определяется как:
C N c
где:
Таким образом, увеличение итераций напрямую увеличивает стоимость атаки.
Практическая настройка PBKDF2 требует баланса между безопасностью и производительностью.
Основные параметры:
Слишком малое количество итераций снижает стойкость, слишком большое ухудшает производительность системы.
На практике встречаются критические ошибки:
Каждая из этих ошибок существенно снижает уровень защиты всей системы.
KDF является промежуточным слоем между пользовательским вводом и криптографическими операциями. Его роль заключается в нормализации и усилении входных данных перед использованием в шифровании или аутентификации.
Без этого слоя вся криптографическая система наследует слабость человеческого фактора, что делает её уязвимой независимо от качества используемого алгоритма шифрования.