Сериализация зашифрованных данных в CryptoJS опирается на внутреннюю
модель представления криптографических результатов и механизм
преобразования этих структур в строки и обратно. В библиотеке нет
единственного «формата шифрования» — вместо этого используется
комбинация объектов CipherParams, сериализаторов
(format) и представлений бинарных данных
(WordArray), которые вместе определяют, как именно будет
выглядеть результат шифрования и как он будет восстановлен при
расшифровке.
Вся криптография в CryptoJS строится вокруг структуры
WordArray. Это внутреннее представление бинарных данных в
виде массива 32-битных слов.
Ключевые особенности:
Типичная структура:
words: массив 32-битных целых чиселsigBytes: количество значимых байтовИменно WordArray используется для:
Преобразования:
Hex:
CryptoJS.enc.Hex.stringify(wordArray)Base64:
CryptoJS.enc.Base64.stringify(wordArray)UTF-8:
CryptoJS.enc.Utf8.stringify(wordArray)Обратное преобразование выполняется через parse.
Результат любого шифрования в CryptoJS инкапсулируется в объект
CipherParams.
Он содержит:
ciphertext — зашифрованные данные (WordArray)key — ключ (опционально, обычно не сериализуется)iv — вектор инициализацииsalt — соль (если используется режим OpenSSL)algorithm — алгоритмmode и padding — режим работы и
дополнениеПример структуры:
{
ciphertext: WordArray,
salt: WordArray,
iv: WordArray,
algorithm: AES,
mode: CBC,
padding: PKCS7
}
Этот объект не предназначен для прямой передачи — он должен быть сериализован.
Наиболее распространённый формат сериализации в CryptoJS — OpenSSL-совместимый.
При использовании:
CryptoJS.AES.encrypt("text", "password")
результат автоматически преобразуется в строку:
U2FsdGVkX1...
Строка включает:
Salted__ (8 байт)Фактическая структура в бинарном виде:
Salted__ + salt + ciphertext
Далее всё это кодируется в Base64.
При использовании строкового пароля CryptoJS применяет алгоритм derivation ключа EVP_BytesToKey.
Вход:
Выход:
Особенности:
Это объясняет, почему одинаковый пароль даёт разные ciphertext при разных salt.
CryptoJS использует объект format, который определяет,
как CipherParams превращается в строку и обратно.
Базовый формат:
CryptoJS.format.OpenSSL
Он реализует два метода:
stringify(cipherParams)parse(str)Преобразует:
Логика:
Обратный процесс:
Salted__Используется для удобства отладки:
ciphertext.toString(CryptoJS.enc.Hex)
Особенности:
Подходит только для простых сценариев.
Более компактный, чем hex:
ciphertext.toString(CryptoJS.enc.Base64)
Особенности:
Для сложных сценариев используется ручная сериализация в JSON.
Пример:
const encrypted = CryptoJS.AES.encrypt("text", "password");
const json = {
ct: encrypted.ciphertext.toString(CryptoJS.enc.Base64),
iv: encrypted.iv && encrypted.iv.toString(),
s: encrypted.salt && encrypted.salt.toString()
};
Особенности:
При десериализации требуется восстановить
CipherParams:
const cipherParams = CryptoJS.lib.CipherParams.create({
ciphertext: CryptoJS.enc.Base64.parse(json.ct),
iv: CryptoJS.enc.Hex.parse(json.iv),
salt: CryptoJS.enc.Hex.parse(json.s)
});
После этого возможно:
CryptoJS.AES.decrypt(cipherParams, password)
Режимы шифрования влияют на необходимость хранения дополнительных параметров:
Поэтому сериализация часто расширяется:
{
ct,
iv,
salt,
mode,
tag
}
CryptoJS допускает замену форматов:
CryptoJS.AES.encrypt("text", "password", {
format: MyCustomFormat
});
Это позволяет:
CryptoJS не поддерживает потоковое шифрование на уровне format, но допускает поэтапное накопление WordArray:
.finalize()Сериализация применяется только после завершения процесса.
В реальных приложениях итоговый формат часто включает:
{
v: 1,
alg: "AES",
mode: "CBC",
iter: 1000,
salt: "...",
iv: "...",
ct: "..."
}
Такой подход позволяет: