Утилиты KJUR.crypto.Util для работы с данными

В криптографических библиотеках работа с данными почти всегда упирается не в алгоритмы как таковые, а в корректные преобразования между различными представлениями одного и того же байтового набора. В контексте Jsrsasign эти задачи централизованы в пространстве имён KJUR.crypto.Util, где собраны низкоуровневые функции для работы с бинарными строками, шестнадцатеричным кодированием, Base64 и представлениями UTF-8.


Перед тем как рассматривать утилиты, важно понимать базовую модель данных, принятую в библиотеке.

В Jsrsasign бинарные данные часто представлены не как Uint8Array, а как raw string — строка, где каждый символ соответствует байту (0–255). Это исторически обусловленный подход, позволяющий эффективно работать с бинарными данными в среде JavaScript до появления широкого распространения ArrayBuffer.

Такое представление требует постоянных преобразований:

  • hex ↔︎ raw string
  • base64 ↔︎ raw string
  • UTF-8 string ↔︎ raw string
  • ArrayBuffer ↔︎ raw string

Именно для этого используется KJUR.crypto.Util.


Преобразования между HEX и бинарными строками

HEX → raw string

Одна из самых часто используемых операций — преобразование шестнадцатеричного представления в бинарную строку:

KJUR.crypto.Util.hextorstr("616263"); // "abc"

Каждая пара hex-символов интерпретируется как байт. Это критически важно при работе с:

  • DER/ASN.1 структурами
  • сертификатами X.509
  • ключами RSA/EC

raw string → HEX

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

KJUR.crypto.Util.rstrtohex("abc"); // "616263"

Используется при сериализации бинарных данных в человекочитаемый формат или при подготовке данных для криптографических операций.


Практическая особенность

При работе с криптографическими структурами часто возникает необходимость постоянного переключения между HEX и raw string. Ошибка в одном месте приводит к полностью некорректной подписи или невозможности валидации сертификата.


Base64 и Base64URL преобразования

Base64 является стандартным способом представления бинарных данных в текстовом виде. В криптографических протоколах дополнительно используется Base64URL, отличающийся безопасностью для URL.


HEX ↔︎ Base64

KJUR.crypto.Util.hextob64("616263"); // "YWJj"
KJUR.crypto.Util.b64tohex("YWJj");   // "616263"

Base64URL

Base64URL используется в JWT, JOSE и веб-криптографии.

KJUR.crypto.Util.hextob64u("616263");
KJUR.crypto.Util.b64utohex("YWJj");

Особенности Base64URL:

  • + заменяется на -
  • / заменяется на _
  • padding = может отсутствовать

Работа с UTF-8 строками

JavaScript строки хранятся в UTF-16, что делает прямую работу с байтами некорректной без преобразования.

UTF-8 string → raw string

KJUR.crypto.Util.utf8tob64u("тест");

или через промежуточные представления:

KJUR.crypto.Util.utf8tob64("data");

raw string → UTF-8 string

KJUR.crypto.Util.b64toutf8("...base64...");

Значение в криптографии

UTF-8 преобразования необходимы при:

  • создании цифровых подписей над текстом
  • обработке JWT payload
  • формировании сообщений для HMAC

Любое несоответствие кодировки приводит к изменению байтового представления и, как следствие, к неверной подписи.


Работа с ArrayBuffer и Uint8Array

Современные API браузера и Node.js используют ArrayBuffer и Uint8Array, поэтому Jsrsasign предоставляет мост между моделями данных.

ArrayBuffer → HEX

KJUR.crypto.Util.abtohex(arrayBuffer);

HEX → ArrayBuffer

KJUR.crypto.Util.hextoab("616263");

Uint8Array ↔︎ raw string

Хотя raw string остаётся внутренним стандартом Jsrsasign, часто требуется взаимодействие с WebCrypto:

KJUR.crypto.Util.u8stohex(uint8Array);
KJUR.crypto.Util.hextou8s("616263");

Генерация случайных значений

В криптографии случайность является фундаментальной характеристикой. KJUR.crypto.Util содержит функции для генерации псевдослучайных данных.

Случайная hex-строка

KJUR.crypto.Util.getRandomHexOfNbytes(16);

Результат — строка из 32 hex-символов.


Случайная бинарная строка

KJUR.crypto.Util.getRandomString(16);

Используется для:

  • генерации ключей
  • nonce
  • salt значений

Криптографический аспект

Важно учитывать, что качество случайности зависит от окружения. В браузере используется window.crypto, в Node.js — crypto.randomBytes.


Канонические преобразования данных

При криптографических операциях важно сохранять строгую каноничность представления.

Типичная проблема

Одинаковые данные могут иметь разные представления:

  • UTF-8 строка
  • raw string
  • base64
  • hex

Без строгой нормализации невозможно гарантировать идентичность входных данных при подписи и проверке.


Пример нормализации

var hex = KJUR.crypto.Util.utf8tob64u("data");
var raw = KJUR.crypto.Util.b64utobstr(hex);
var normalizedHex = KJUR.crypto.Util.rstrtohex(raw);

Особенности производительности

Преобразования в KJUR.crypto.Util являются синхронными и выполняются в JavaScript-слое без нативной оптимизации. Это создаёт несколько важных характеристик:

  • операции над большими данными могут быть затратными
  • частые конверсии внутри циклов существенно замедляют выполнение
  • предпочтительно минимизировать количество переходов между форматами

Типичные ошибки при использовании утилит

Потеря кодировки

Частая проблема возникает при попытке обработать UTF-8 строку как raw string:

KJUR.crypto.Util.rstrtohex("текст");

Результат будет некорректным из-за различий UTF-16 и бинарного представления.


Неправильное использование Base64URL

Использование обычного Base64 вместо Base64URL в JWT приводит к:

  • ошибкам декодирования
  • несовпадению подписи
  • отказу верификации токена

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

b64(b64(data))

Такие ошибки возникают при неправильной цепочке преобразований и приводят к потере исходного бинарного смысла.


Роль Util в общей архитектуре Jsrsasign

KJUR.crypto.Util не является высокоуровневым API. Его задача — обеспечить единый слой абстракции для:

  • криптографических примитивов
  • ASN.1 структур
  • цифровых подписей
  • работы с сертификатами
  • JWT и JOSE операций

Все более сложные модули Jsrsasign опираются на эти функции как на базовый слой представления данных.


Взаимодействие с криптографическими модулями

Утилиты активно используются внутри:

  • KJUR.crypto.Signature
  • KJUR.asn1
  • KEYUTIL
  • JWT обработчиков

Любая операция подписи фактически проходит через цепочку преобразований:

  1. входные данные (UTF-8 / string)
  2. нормализация (raw string)
  3. хеширование
  4. кодирование результата (hex/base64)
  5. упаковка результата

Значение единообразного представления данных

В криптографии корректность результата определяется не только алгоритмом, но и точностью входных байтов. KJUR.crypto.Util обеспечивает предсказуемость этих преобразований, устраняя неоднозначности между строками JavaScript и бинарными данными.

Отсутствие такого слоя приводило бы к необходимости вручную реализовывать:

  • UTF-8 encoder/decoder
  • Base64/Base64URL преобразования
  • бинарные операции
  • работу с hex

что существенно увеличивает вероятность ошибок в криптографическом коде.