Преобразование данных: строки, байты, hex, Base64

Библиотека Crypto-js оперирует не обычными строками JavaScript, а специальным типом — WordArray. Это ключевая структура, через которую проходят все криптографические операции.

WordArray представляет собой массив 32-битных слов (words) и количество значимых байтов (sigBytes). Такое представление позволяет эффективно обрабатывать бинарные данные и выполнять побитовые операции.

var wordArray = CryptoJS.lib.WordArray.create([0x12345678, 0x90abcdef], 8);
  • words — массив чисел (по 4 байта каждое)
  • sigBytes — фактическая длина данных в байтах

Преобразование строк в WordArray

По умолчанию строка интерпретируется как UTF-8:

var data = CryptoJS.enc.Utf8.parse("Hello");

Результат — объект WordArray, пригодный для шифрования или хэширования.

Альтернативные кодировки:

  • Latin1 (ISO-8859-1):
var data = CryptoJS.enc.Latin1.parse("Hello");
  • UTF-16 (Big Endian):
var data = CryptoJS.enc.Utf16.parse("Hello");
  • UTF-16 Little Endian:
var data = CryptoJS.enc.Utf16LE.parse("Hello");

Преобразование WordArray в строку

Обратное преобразование выполняется методом toString() с указанием кодировки:

var str = wordArray.toString(CryptoJS.enc.Utf8);

Примеры:

wordArray.toString(CryptoJS.enc.Hex);
wordArray.toString(CryptoJS.enc.Base64);
wordArray.toString(CryptoJS.enc.Latin1);

Если кодировка не указана, по умолчанию используется Hex.


Hex-представление

Hex (шестнадцатеричная строка) — один из основных форматов представления бинарных данных.

Преобразование строки в Hex:

var hex = CryptoJS.enc.Hex.stringify(
    CryptoJS.enc.Utf8.parse("Hello")
);

Обратное преобразование:

var wordArray = CryptoJS.enc.Hex.parse("48656c6c6f");
var str = wordArray.toString(CryptoJS.enc.Utf8);

Hex широко используется для:

  • хранения хэшей
  • передачи бинарных данных в текстовом виде
  • отладки криптографических операций

Base64-представление

Base64 применяется для компактного текстового представления бинарных данных.

Кодирование:

var base64 = CryptoJS.enc.Base64.stringify(
    CryptoJS.enc.Utf8.parse("Hello")
);

Результат:

SGVsbG8=

Декодирование:

var wordArray = CryptoJS.enc.Base64.parse("SGVsbG8=");
var str = wordArray.toString(CryptoJS.enc.Utf8);

Base64 используется:

  • в HTTP-заголовках (например, Authorization)
  • при передаче бинарных данных через JSON
  • в криптографических протоколах

Работа с байтами

Crypto-js не предоставляет прямого API для работы с массивами байтов (Uint8Array), но их можно преобразовать.

WordArray → Uint8Array:

function wordArrayToUint8Array(wordArray) {
    var words = wordArray.words;
    var sigBytes = wordArray.sigBytes;
    var u8 = new Uint8Array(sigBytes);

    for (var i = 0; i < sigBytes; i++) {
        u8[i] = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff;
    }

    return u8;
}

Uint8Array → WordArray:

function uint8ArrayToWordArray(u8Array) {
    var words = [];
    for (var i = 0; i < u8Array.length; i++) {
        words[i >>> 2] |= u8Array[i] << (24 - (i % 4) * 8);
    }
    return CryptoJS.lib.WordArray.create(words, u8Array.length);
}

Это необходимо при интеграции с:

  • Web Crypto API
  • бинарными файлами
  • сетевыми протоколами

Особенности кодировок

UTF-8

  • Переменная длина символов (1–4 байта)
  • Поддержка всех Unicode-символов
  • Стандарт для веба

Latin1

  • 1 байт на символ
  • Ограничен 256 символами
  • Может искажать Unicode-строки

UTF-16

  • 2 или 4 байта на символ
  • Используется внутри JavaScript
  • Требует явного указания при преобразованиях

Неправильный выбор кодировки приводит к:

  • повреждению данных
  • неверным хэшам
  • ошибкам дешифрования

Автоматические преобразования

Многие функции Crypto-js автоматически принимают строки:

var hash = CryptoJS.SHA256("Hello");

Внутри происходит:

  1. Преобразование строки в UTF-8 WordArray
  2. Выполнение операции
  3. Возврат результата как WordArray

Для явного контроля лучше выполнять преобразования вручную:

var data = CryptoJS.enc.Utf8.parse("Hello");
var hash = CryptoJS.SHA256(data);

Работа с бинарными данными

При работе с файлами или сетевыми пакетами важно избегать промежуточных строк:

  • строки могут изменить байты (из-за кодировки)
  • бинарные данные должны передаваться как есть

Рекомендуемый подход:

  1. Использовать Uint8Array
  2. Преобразовывать в WordArray
  3. Выполнять криптографические операции
  4. Конвертировать результат в нужный формат (Hex/Base64)

Частые ошибки

1. Потеря данных при неправильной кодировке

CryptoJS.enc.Utf8.parse(binaryData) // ошибка

2. Двойное кодирование

CryptoJS.enc.Base64.stringify(
    CryptoJS.enc.Base64.parse(data)
)

3. Игнорирование sigBytes

  • лишние байты в конце
  • некорректные результаты

4. Использование строк вместо WordArray в сложных сценариях


Сравнение форматов

Формат Размер Читаемость Применение
UTF-8 средний высокая текст
Hex большой высокая отладка, хэши
Base64 меньше Hex средняя передача данных
Binary минимальный низкая внутренняя обработка

Практическая схема преобразований

Типичный поток обработки данных:

Строка (UTF-8)
    ↓ parse
WordArray
    ↓ crypto operation
WordArray
    ↓ stringify
Hex / Base64 / строка

Для бинарных данных:

Uint8Array
    ↓ convert
WordArray
    ↓ crypto
WordArray
    ↓ convert
Uint8Array / Base64

Контроль над представлением данных

Ключевая идея работы с Crypto-js — явное управление форматом данных на каждом этапе:

  • вход: определить кодировку
  • обработка: использовать WordArray
  • выход: выбрать подходящий формат

Это исключает:

  • неявные преобразования
  • несовместимость систем
  • ошибки при шифровании и хэшировании