AES (Advanced Encryption Standard) представляет собой симметричный алгоритм блочного шифрования, основанный на сети подстановок и перестановок. В библиотеке CryptoJS он реализуется в соответствии со стандартом FIPS-197 и используется как основной механизм защиты данных на стороне JavaScript.
AES работает с блоками данных размером 128 бит и поддерживает три варианта длины ключа: 128, 192 и 256 бит. Различие между ними заключается не только в длине ключа, но и в количестве раундов преобразований:
Каждый раунд включает последовательность операций: SubBytes, ShiftRows, MixColumns и AddRoundKey. Увеличение числа раундов напрямую влияет на устойчивость к криптоанализу, но также увеличивает вычислительную стоимость.
Ключ в AES определяет исходное состояние шифрования и сложность его подбора. В CryptoJS ключи передаются в виде строки или WordArray, однако важно понимать внутреннюю природу их безопасности.
Ключ длиной 128 бит обеспечивает 2¹²⁸ возможных комбинаций. Это значение считается устойчивым к brute-force атакам при текущем уровне вычислительных возможностей.
Характерные особенности:
Ключ 192 бит увеличивает пространство поиска до 2¹⁹².
Особенности:
Ключ 256 бит обеспечивает 2²⁵⁶ комбинаций, что считается максимально устойчивым в рамках AES.
Особенности:
AES не использует ключ напрямую для каждого раунда. Вместо этого он расширяется в набор раундовых ключей.
В CryptoJS этот процесс скрыт, но логически включает:
Для AES-256 процесс расширения сложнее, так как исходный ключ длиннее и требует большего числа итераций генерации.
Библиотека CryptoJS предоставляет высокоуровневый интерфейс:
const CryptoJS = require("crypto-js");
const ciphertext = CryptoJS.AES.encrypt(
"секретные данные",
"ключ"
).toString();
const bytes = CryptoJS.AES.decrypt(ciphertext, "ключ");
const originalText = bytes.toString(CryptoJS.enc.Utf8);
Однако такой подход использует строковый ключ, который автоматически проходит через PBKDF1/PBKDF2-подобное преобразование внутри библиотеки (в зависимости от версии и режима).
Для более строгого контроля используется WordArray:
const key = CryptoJS.enc.Utf8.parse("0123456789abcdef"); // 16 байт = AES-128
const encrypted = CryptoJS.AES.encrypt("данные", key, {
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
});
Размер ключа напрямую определяет используемый стандарт AES:
CryptoJS автоматически определяет вариант алгоритма по длине ключа.
AES сам по себе работает только с 128-битными блоками, но режим определяет, как эти блоки связываются между собой.
Наиболее используемые режимы в CryptoJS:
Пример CBC:
const encrypted = CryptoJS.AES.encrypt("данные", key, {
mode: CryptoJS.mode.CBC,
iv: CryptoJS.enc.Utf8.parse("1234567890123456")
});
IV (инициализационный вектор) не влияет на стойкость ключа, но критически важен для уникальности шифротекста.
Использование прямых строковых ключей снижает стойкость. В практических системах применяется KDF (Key Derivation Function).
CryptoJS поддерживает PBKDF2:
const key = CryptoJS.PBKDF2("пароль", "соль", {
keySize: 256 / 32,
iterations: 1000
});
Несмотря на различие в теоретической стойкости, в реальных условиях безопасность AES чаще определяется не длиной ключа, а:
AES-128 не считается слабым. Основные криптоаналитические атаки на AES не являются практическими при корректной реализации.
AES-256 не гарантирует «двойную безопасность» в прикладном смысле, но увеличивает запас устойчивости против теоретических атак, включая квантовые модели (Grover’s algorithm снижает эффективную стойкость до 2¹²⁸ для AES-256).
Частые проблемы:
Пример опасной практики:
CryptoJS.AES.encrypt("data", "password");
Без PBKDF2 такой подход делает систему уязвимой к словарным атакам.
В веб-контексте различия в производительности часто минимальны, но в массовых операциях (стриминг, большие массивы данных) AES-128 заметно быстрее.
CryptoJS не использует аппаратное ускорение AES-NI, как это делают нативные реализации в современных браузерах и Node.js crypto module. Это приводит к: