Хеширование строк и бинарных данных

Библиотека Jsrsasign предоставляет набор криптографических примитивов, включая функции хеширования, реализованные через модуль KJUR.crypto.MessageDigest. Хеш-функции применяются для получения фиксированного дайджеста данных произвольной длины и широко используются в задачах проверки целостности, цифровых подписей и криптографических протоколов.

Поддерживаются алгоритмы семейства SHA (SHA-1, SHA-224, SHA-256, SHA-384, SHA-512), а также MD5. Основное внимание в современных сценариях уделяется SHA-256 и выше, как более устойчивым к криптоанализу.


MessageDigest как базовый механизм хеширования

Класс KJUR.crypto.MessageDigest реализует универсальный интерфейс для вычисления хеша:

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

Базовая структура использования

const md = new KJUR.crypto.MessageDigest({alg: "sha256"});
md.updateString("data");
const hash = md.digest();

Метод digest() возвращает результат в виде шестнадцатеричной строки. Внутренне данные проходят через UTF-8 кодирование при использовании строкового ввода.


Хеширование строковых данных

При работе со строками применяется метод updateString, который интерпретирует вход как текстовые данные.

SHA-256 для строки

const md = new KJUR.crypto.MessageDigest({alg: "sha256"});
md.updateString("cryptographic message");
const result = md.digest();

Формируемый хеш всегда зависит от точного байтового представления строки, включая кодировку UTF-8.

Упрощённые утилиты

Jsrsasign предоставляет вспомогательные методы в KJUR.crypto.Util:

const hash = KJUR.crypto.Util.sha256("cryptographic message");

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


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

Хеширование бинарных данных требует корректной передачи массива байтов. В браузерных окружениях это обычно ArrayBuffer или Uint8Array.

Пример обработки Uint8Array

const data = new Uint8Array([0x01, 0x02, 0x03]);

const md = new KJUR.crypto.MessageDigest({alg: "sha256"});
md.updateHex(BAuto.toHex(data)); 
const hash = md.digest();

Для бинарных потоков часто применяется преобразование в hex-строку, поскольку Jsrsasign оперирует строковыми представлениями байтов.

Хеширование ArrayBuffer

function arrayBufferToHex(buffer) {
    const bytes = new Uint8Array(buffer);
    return Array.from(bytes)
        .map(b => ("0" + b.toString(16)).slice(-2))
        .join("");
}

Инкрементальное хеширование

MessageDigest поддерживает поэтапную подачу данных. Это важно при обработке больших объёмов информации или потоков.

Постепенное добавление данных

const md = new KJUR.crypto.MessageDigest({alg: "sha512"});

md.updateString("part1 ");
md.updateString("part2 ");
md.updateString("part3");

const digest = md.digest();

Каждый вызов updateString или updateHex изменяет внутреннее состояние алгоритма без финализации.


Форматы вывода хеша

Результат хеширования может быть представлен в нескольких форматах:

  • hexadecimal (hex) — стандартное представление
  • base64 — используется в протоколах передачи данных
  • raw binary — реже применяется напрямую

Hex представление (по умолчанию)

const md = new KJUR.crypto.MessageDigest({alg: "sha256"});
md.updateString("data");
const hex = md.digest();

Base64 формат

const md = new KJUR.crypto.MessageDigest({alg: "sha256"});
md.updateString("data");
const base64 = md.digest("b64");

Поддержка формата передаётся параметром метода digest.


Хеширование с использованием SHA-1 и SHA-512

SHA-1

const hash = KJUR.crypto.Util.sha1("message");

SHA-1 применяется преимущественно в устаревших системах и протоколах совместимости.

SHA-512

const md = new KJUR.crypto.MessageDigest({alg: "sha512"});
md.updateString("message");
const hash = md.digest();

SHA-512 обеспечивает увеличенный размер выхода и повышенную криптостойкость по сравнению с SHA-256.


HMAC на основе хеш-функций

HMAC используется для аутентификации сообщений с использованием секретного ключа. В Jsrsasign он реализуется через KJUR.crypto.Mac.

HMAC-SHA256

const mac = new KJUR.crypto.Mac({alg: "HmacSHA256", pass: "secretKey"});
mac.updateString("message");
const result = mac.doFinal();

Ключ участвует в процессе хеширования, обеспечивая защиту от подмены данных.


Обработка больших данных и потоков

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

Типичная схема:

  • чтение блока данных
  • обновление состояния MessageDigest
  • переход к следующему блоку
  • финализация
const md = new KJUR.crypto.MessageDigest({alg: "sha256"});

md.updateHex(chunk1);
md.updateHex(chunk2);
md.updateHex(chunk3);

const finalHash = md.digest();

Кодировки и влияние на результат

Корректность хеша зависит от кодировки входных данных. Строки в Jsrsasign интерпретируются как UTF-8 последовательности байтов.

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

  • ASCII-строки совпадают с UTF-8
  • символы Unicode могут занимать несколько байтов
  • скрытые символы влияют на итоговый хеш

Сравнение алгоритмов по характеристикам

SHA-256:

  • баланс скорости и стойкости
  • стандарт де-факто для современных систем

SHA-512:

  • более высокая криптостойкость
  • увеличенный размер результата
  • эффективен на 64-битных архитектурах

SHA-1:

  • устаревший алгоритм
  • используется в совместимых системах

MD5:

  • высокая скорость
  • слабая криптостойкость
  • применяется только для некритичных задач контроля целостности

Типовые сценарии применения хеширования

Хеширование в Jsrsasign используется в следующих контекстах:

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

Особенности внутренней реализации

Jsrsasign реализует криптографические функции на JavaScript без нативных зависимостей. Это обеспечивает:

  • переносимость между средами (браузер, Node.js)
  • предсказуемое поведение алгоритмов
  • независимость от платформенных криптографических API

При этом производительность ниже, чем у нативных реализаций, что особенно заметно при обработке больших потоков данных.