Внутреннее представление данных в CryptoJS строится вокруг структуры WordArray. Это не строка и не массив байтов в привычном JavaScript-смысле, а специализированный контейнер, оптимизированный для криптографических операций.
WordArray хранит данные в виде массива 32-битных слов:
sigBytes, указывающее
фактическую длину значимых байтовТакой подход позволяет эффективно выполнять побитовые операции, хеширование и шифрование без лишних преобразований.
const wordArray = CryptoJS.lib.WordArray.create([0x12345678, 0x90abcdef], 8);
Здесь:
8 — количество значимых байтCryptoJS не работает напрямую со строками в криптографических алгоритмах. Любая строка сначала преобразуется в WordArray через кодировку.
Основные кодировки находятся в CryptoJS.enc:
Каждая кодировка реализует два ключевых метода:
parse() — строка → WordArraystringify() — WordArray → строкаUTF-8 является стандартной кодировкой для большинства криптографических операций, так как корректно обрабатывает Unicode.
const message = "Hello CryptoJS";
const wordArray = CryptoJS.enc.Utf8.parse(message);
const original = CryptoJS.enc.Utf8.stringify(wordArray);
Внутри происходит побайтовое кодирование символов Unicode в UTF-8 последовательность.
Hex (шестнадцатеричное представление) используется для визуализации бинарных данных и совместимости с низкоуровневыми системами.
const hexString = "48656c6c6f";
const wordArray = CryptoJS.enc.Hex.parse(hexString);
const hex = CryptoJS.enc.Hex.stringify(wordArray);
Особенность Hex:
Base64 применяется для безопасной передачи бинарных данных в текстовых протоколах (JSON, HTTP, email).
const wordArray = CryptoJS.enc.Utf8.parse("CryptoJS");
const base64 = CryptoJS.enc.Base64.stringify(wordArray);
const parsed = CryptoJS.enc.Base64.parse(base64);
const text = CryptoJS.enc.Utf8.stringify(parsed);
Base64 увеличивает размер данных примерно на 33%, но обеспечивает совместимость с текстовыми форматами.
WordArray выступает центральным звеном между всеми представлениями данных.
const wa = CryptoJS.enc.Utf8.parse("data");
const hex = CryptoJS.enc.Hex.stringify(wa);
const wa = CryptoJS.enc.Hex.parse(hex);
const base64 = CryptoJS.enc.Base64.stringify(wa);
Любое преобразование строится по цепочке:
Строка → WordArray → другой формат
В современных JavaScript-приложениях часто требуется взаимодействие с Web APIs и бинарными буферами.
CryptoJS не работает напрямую с ArrayBuffer, но преобразование возможно вручную.
function uint8ToWordArray(u8Array) {
const words = [];
for (let i = 0; i < u8Array.length; i++) {
words[i >>> 2] |= u8Array[i] << (24 - (i % 4) * 8);
}
return CryptoJS.lib.WordArray.create(words, u8Array.length);
}
function wordArrayToUint8(wa) {
const u8 = new Uint8Array(wa.sigBytes);
for (let i = 0; i < wa.sigBytes; i++) {
const byte = (wa.words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff;
u8[i] = byte;
}
return u8;
}
Такой мост необходим при работе с:
WordArray нельзя напрямую безопасно сериализовать в JSON, так как структура содержит внутренние поля и 32-битные слова.
JSON.stringify(wordArray);
Результат:
const base64 = CryptoJS.enc.Base64.stringify(wordArray);
const json = JSON.stringify({
data: base64
});
Восстановление:
const parsed = JSON.parse(json);
const wa = CryptoJS.enc.Base64.parse(parsed.data);
Base64 является стандартным решением для сериализации криптографических данных.
Одной из частых ошибок является неправильный выбор кодировки при преобразовании.
const wa = CryptoJS.enc.Latin1.parse("Привет");
Latin1 не поддерживает кириллицу, что приводит к искажению данных.
Правильный вариант:
const wa = CryptoJS.enc.Utf8.parse("Привет");
Latin1:
UTF-8:
Иногда требуется преобразовать данные между нестандартными форматами вручную.
const utf8Wa = CryptoJS.enc.Utf8.parse("data");
const hex = CryptoJS.enc.Hex.stringify(utf8Wa);
const base64 = CryptoJS.enc.Base64.stringify(utf8Wa);
const latin1 = CryptoJS.enc.Latin1.stringify(utf8Wa);
Каждое представление интерпретирует один и тот же WordArray по-разному.
Каждая кодировка реализует одинаковый интерфейс:
parse(string) → WordArraystringify(WordArray) → stringparse: function(hex) {
const words = [];
for (let i = 0; i < hex.length; i += 2) {
words.push(parseInt(hex.substr(i, 2), 16));
}
return WordArray.create(words);
}
При использовании алгоритмов шифрования преобразования происходят автоматически:
const encrypted = CryptoJS.AES.encrypt("text", "key");
const base64 = encrypted.toString();
Здесь результат по умолчанию возвращается в Base64, так как это безопасный текстовый формат.
Дешифрование:
const bytes = CryptoJS.AES.decrypt(base64, "key");
const original = bytes.toString(CryptoJS.enc.Utf8);
Игнорирование sigBytes приводит к захвату мусорных
данных из последнего 32-битного слова.
wordArray.toString()
Без указания кодировки по умолчанию используется Hex, что часто приводит к неожиданному результату.
В реальных системах часто применяется единый слой преобразования:
Такая схема минимизирует ошибки кодировок и упрощает взаимодействие между системами.