Криптографическое шифрование в JavaScript через библиотеку CryptoJS часто используется для защиты данных на клиентской стороне, однако базовые схемы симметричного шифрования не решают задачу проверки целостности. Шифрование скрывает содержимое, но не гарантирует, что оно не было изменено.
Конфиденциальность обеспечивается алгоритмами вроде AES, где исходный текст преобразуется в зашифрованный вид. Однако целостность требует дополнительного механизма, который позволяет определить факт модификации данных.
В CryptoJS стандартные режимы шифрования, такие как CBC, не включают встроенной аутентификации сообщения. Это означает, что любое изменение зашифрованного текста может привести к непредсказуемым результатам при расшифровке без явного сигнала о повреждении.
Типичный пример использования AES в CryptoJS:
const CryptoJS = require("crypto-js");
const secretKey = "my-secret-key";
const plaintext = "confidential data";
const encrypted = CryptoJS.AES.encrypt(plaintext, secretKey).toString();
const decrypted = CryptoJS.AES.decrypt(encrypted, secretKey)
.toString(CryptoJS.enc.Utf8);
console.log(encrypted);
console.log(decrypted);
На первый взгляд результат выглядит корректным: данные зашифрованы и восстановлены. Однако структура AES-CBC в CryptoJS не защищает от изменения ciphertext.
Зашифрованная строка может быть изменена без знания ключа. Даже минимальное изменение одного символа приводит к изменению результата расшифровки:
const altered = encrypted.replace(/.{5}$/, "AAAAA");
const result = CryptoJS.AES.decrypt(altered, secretKey)
.toString(CryptoJS.enc.Utf8);
console.log(result);
Возможные последствия:
Причина заключается в том, что режим CBC обеспечивает только конфиденциальность, но не аутентификацию блоков.
При использовании только шифрования отсутствует механизм проверки:
Это делает систему уязвимой к атакам, связанным с подменой и модификацией зашифрованных сообщений.
Особенно критичны ситуации, когда расшифрованные данные сразу используются в логике приложения без дополнительной проверки.
Для защиты данных используется механизм кода аутентификации сообщения (MAC). На практике часто применяется HMAC на основе SHA-256.
Пример формирования защищённой структуры:
const message = "confidential data";
const key = "encryption-key";
const hmacKey = "auth-key";
const encrypted = CryptoJS.AES.encrypt(message, key).toString();
const signature = CryptoJS.HmacSHA256(encrypted, hmacKey).toString();
При расшифровке необходимо выполнить проверку подписи до обработки данных:
const recalculated = CryptoJS.HmacSHA256(encrypted, hmacKey).toString();
if (recalculated !== signature) {
throw new Error("Integrity check failed");
}
const decrypted = CryptoJS.AES.decrypt(encrypted, key)
.toString(CryptoJS.enc.Utf8);
Такой подход позволяет обнаруживать любые изменения ciphertext до его расшифровки.
Корректной криптографической практикой считается схема «сначала шифрование, затем MAC»:
При расшифровке:
Любое отклонение MAC делает дальнейшую обработку бессмысленной.
CryptoJS не предоставляет защищённый режим аутентифицированного шифрования (AEAD) на уровне AES-GCM в стандартном API. Поэтому разработчик вынужден вручную комбинировать алгоритмы.
Это приводит к ряду проблем:
Наиболее критичной ошибкой является расшифровка до проверки целостности, что открывает поверхность для атак на обработку ошибок и формат данных.
При изменении ciphertext:
Пример:
try {
const data = CryptoJS.AES.decrypt(altered, secretKey)
.toString(CryptoJS.enc.Utf8);
console.log(data);
} catch (e) {
console.log("decryption error");
}
Однако отсутствие исключения не означает корректность результата, что создаёт ложное ощущение безопасности.
Симметричное шифрование в CryptoJS реализует только преобразование данных, не включая проверку источника или структуры сообщения. Любая модификация ciphertext приводит к детерминированным или частично детерминированным изменениям plaintext, что позволяет атакующему влиять на результат расшифровки.
Для безопасного использования CryptoJS требуется добавление внешнего слоя контроля целостности. В противном случае шифрование остаётся односторонним механизмом защиты конфиденциальности без гарантии подлинности данных.
Использование HMAC или аналогичных механизмов становится обязательным компонентом архитектуры при работе с данными, где возможна их передача или хранение в недоверенной среде.