В криптографической библиотеке CryptoJS результат шифрования представлен не просто строкой, а структурой CipherParams. Это объект, который инкапсулирует ключевые данные: зашифрованный текст, соль, вектор инициализации (IV), алгоритм и другие параметры, необходимые для корректного восстановления исходного состояния.
Работа с CipherParams становится особенно важной тогда, когда зашифрованные данные нужно передавать между системами, сохранять в базе данных или сериализовать в текстовый формат (например, JSON или строку URL-safe). Именно на этом этапе возникает необходимость преобразования CipherParams в строку и обратно без потери информации.
Объект CipherParams в CryptoJS обычно содержит следующие поля:
На практике чаще всего используется только ciphertext, но для корректной расшифровки в сложных сценариях важны и остальные поля.
CryptoJS предоставляет встроенный механизм сериализации через
форматтеры. Самый простой способ — использование метода
toString().
const encrypted = CryptoJS.AES.encrypt("секретные данные", "ключ");
const serialized = encrypted.toString();
По умолчанию используется формат OpenSSL-подобной строки, закодированной в Base64. Результат выглядит как непрозрачная строка:
U2FsdGVkX1+...
Эта строка уже содержит:
Но важно понимать: структура скрыта внутри формата.
CryptoJS использует концепцию Formatter — объект, который определяет, как CipherParams превращается в строку и обратно.
CryptoJS.AES.encrypt("text", "passphrase").toString();
Он включает:
Пример внутренней структуры:
Salted__ + salt + ciphertext
Можно явно задать формат:
const encrypted = CryptoJS.AES.encrypt("text", "key");
const hex = encrypted.ciphertext.toString(CryptoJS.enc.Hex);
Однако это уже не полный CipherParams, а только ciphertext.
Чтобы сериализовать всё целиком:
const hexString = encrypted.toString(CryptoJS.format.Hex);
const base64 = encrypted.toString(CryptoJS.format.Base64);
Base64 удобен для передачи через API, JSON и URL.
Чтобы восстановить исходный объект, нужно использовать соответствующий форматтер.
const encrypted = CryptoJS.AES.encrypt("text", "key");
const serialized = encrypted.toString();
const parsed = CryptoJS.AES.decrypt(serialized, "key");
const original = parsed.toString(CryptoJS.enc.Utf8);
Здесь происходит:
Каждый форматтер в CryptoJS содержит метод parse, который превращает строку обратно в CipherParams.
Пример (условно):
const cipherParams = CryptoJS.format.OpenSSL.parse(serialized);
Результат:
{
ciphertext: WordArray,
salt: WordArray
}
После этого можно вручную расшифровать:
const key = CryptoJS.PBKDF2("password", cipherParams.salt, {
keySize: 256/32,
});
const decrypted = CryptoJS.AES.decrypt(cipherParams, key);
В реальных системах часто требуется собственный формат, например JSON.
const encrypted = CryptoJS.AES.encrypt("data", "key");
const json = JSON.stringify({
ciphertext: encrypted.ciphertext.toString(CryptoJS.enc.Base64),
iv: encrypted.iv && encrypted.iv.toString(),
salt: encrypted.salt && encrypted.salt.toString()
});
const obj = JSON.parse(json);
const cipherParams = CryptoJS.lib.CipherParams.create({
ciphertext: CryptoJS.enc.Base64.parse(obj.ciphertext),
iv: CryptoJS.enc.Hex.parse(obj.iv),
salt: CryptoJS.enc.Hex.parse(obj.salt)
});
const decrypted = CryptoJS.AES.decrypt(cipherParams, "key")
.toString(CryptoJS.enc.Utf8);
Частая ошибка — сериализовать только ciphertext:
encrypted.ciphertext.toString()
Это приводит к потере:
В результате расшифровка становится невозможной без внешнего контекста.
Сериализация CipherParams напрямую влияет на безопасность системы:
На практике часто используют один из двух подходов:
const stored = encrypted.toString();
Плюсы:
Минусы:
{
ct: "...",
iv: "...",
s: "..."
}
Плюсы:
Минусы:
const encrypted = CryptoJS.AES.encrypt("hello", "password");
// сериализация
const serialized = encrypted.toString();
// передача / хранение
// восстановление
const decrypted = CryptoJS.AES.decrypt(serialized, "password");
const result = decrypted.toString(CryptoJS.enc.Utf8);
Частые проблемы:
Ручная сериализация нужна в случаях:
CipherParams — это не просто контейнер, а полноценное описание криптографического состояния. Сериализация превращает его в переносимый формат, а десериализация восстанавливает контекст, необходимый для корректной работы алгоритма шифрования и дешифрования.