Класс KJUR.crypto.Signature

Класс KJUR.crypto.Signature из библиотеки Jsrsasign предназначен для формирования и проверки цифровых подписей на основе различных криптографических алгоритмов. Он реализует высокоуровневый интерфейс поверх механизмов хеширования и асимметричного шифрования, позволяя работать с RSA, ECDSA и другими схемами подписи без необходимости ручного управления низкоуровневыми криптопримитивами.

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


Архитектура и модель работы

KJUR.crypto.Signature построен вокруг классической схемы цифровой подписи:

  1. Выбор алгоритма подписи (например, SHA256withRSA)
  2. Инициализация режима (подпись или проверка)
  3. Последовательная подача данных
  4. Формирование подписи или её проверка

Внутренне класс объединяет:

  • хеш-функцию (SHA-1, SHA-256, SHA-384, SHA-512 и др.)
  • криптосистему асимметричного шифрования (RSA, ECDSA)
  • кодировщики выходных данных (hex, base64)

Поддерживаемые алгоритмы

Наиболее часто используемые строки алгоритмов:

  • SHA1withRSA
  • SHA256withRSA
  • SHA384withRSA
  • SHA512withRSA
  • SHA256withECDSA
  • SHA1withECDSA

Структура строки всегда соответствует формату:

<HASH>with<ALGORITHM>

где:

  • HASH — криптографическая хеш-функция
  • ALGORITHM — асимметричный алгоритм подписи

Инициализация объекта

Создание экземпляра Signature осуществляется через указание алгоритма:

var sig = new KJUR.crypto.Signature({ "alg": "SHA256withRSA" });

Возможные параметры конфигурации:

  • alg — алгоритм подписи
  • prov — криптопровайдер (например, cryptojs/jsrsa)
  • prvkeypem — приватный ключ в PEM-формате (опционально)
  • pubkeypem — публичный ключ в PEM-формате (опционально)

Настройка ключей

Приватный ключ (для подписи)

sig.init(privateKeyPEM);

Приватный ключ может быть представлен в формате:

  • PKCS#1 PEM
  • PKCS#8 PEM

Публичный ключ (для проверки)

sig.init(publicKeyPEM);

или явное указание режима:

sig.init({ "pubkey": publicKeyPEM });

Режим подписи

При создании цифровой подписи используется последовательность:

sig.init(privateKeyPEM);
sig.updateString("данные");
var signature = sig.sign();

Методы добавления данных

updateString

Добавление строки:

sig.updateString("Hello world");

updateHex

Добавление данных в hex-формате:

sig.updateHex("4a6f686e");

updateByteArray

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

sig.updateByteArray([0x4a, 0x6f, 0x68, 0x6e]);

Формирование подписи

После завершения подачи данных вызывается:

var sigValue = sig.sign();

Результат обычно возвращается в формате HEX или Base64 (в зависимости от конфигурации провайдера).


Режим проверки подписи

Проверка цифровой подписи выполняется аналогично, но с публичным ключом:

sig.init(publicKeyPEM);
sig.updateString("данные");
var result = sig.verify(signatureHex);

Возвращаемое значение

  • true — подпись корректна
  • false — подпись не совпадает

Потоковая модель обработки

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

sig.init(privateKeyPEM);
sig.updateString("часть 1 ");
sig.updateString("часть 2");
sig.updateString("часть 3");
var signature = sig.sign();

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


Взаимодействие с хешированием

Алгоритм подписи включает два этапа:

  1. Вычисление хеша от входных данных
  2. Криптографическое преобразование хеша с использованием приватного ключа

Пример для SHA256withRSA:

data → SHA-256 → digest → RSA encrypt (private key) → signature

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


Форматы ключей

RSA ключи

Поддерживаются:

  • PKCS#1 PEM
  • PKCS#8 PEM

Пример:

-----BEGIN PRIVATE KEY-----
...
-----END PRIVATE KEY-----

ECDSA ключи

Используются кривые:

  • secp256r1
  • secp256k1 (в некоторых реализациях)

Пример RSA подписи

var sig = new KJUR.crypto.Signature({ "alg": "SHA256withRSA" });

sig.init(privateKeyPEM);
sig.updateString("message");

var signature = sig.sign();

Пример проверки RSA подписи

var sig = new KJUR.crypto.Signature({ "alg": "SHA256withRSA" });

sig.init(publicKeyPEM);
sig.updateString("message");

var isValid = sig.verify(signature);

Пример ECDSA подписи

var sig = new KJUR.crypto.Signature({ "alg": "SHA256withECDSA" });

sig.init(privateKeyPEM);
sig.updateString("message");

var signature = sig.sign();

Особенности работы с ECDSA

ECDSA требует точного совпадения:

  • хеш-функции
  • параметров кривой
  • формата кодирования подписи (DER)

Подпись обычно возвращается в ASN.1 DER формате, закодированном в HEX или Base64.


Форматы вывода подписи

В зависимости от провайдера и конфигурации:

  • HEX строка
  • Base64 строка
  • бинарный массив (реже)

Преобразование часто выполняется через вспомогательные утилиты Jsrsasign.


Обработка ошибок

Типичные причины ошибок:

  • неверный формат ключа
  • несоответствие алгоритма ключу
  • повреждённые данные подписи
  • неправильный порядок вызова методов (init → update → sign/verify)

Криптографические режимы RSA

В зависимости от конфигурации могут использоваться:

  • PKCS#1 v1.5 padding
  • RSA-PSS (в новых конфигурациях)

Выбор влияет на совместимость с внешними системами и уровень криптостойкости.


Важные особенности реализации

  • Внутренний хешер зависит от выбранного алгоритма
  • Данные не буферизуются полностью в памяти при использовании update-методов
  • Повторное использование экземпляра требует повторного init
  • Проверка подписи выполняется строго по совпадению digest-значения

Использование в многослойных архитектурах

KJUR.crypto.Signature часто применяется в:

  • клиентской подписи запросов API
  • JWT-подобных системах (нестандартные реализации)
  • проверке целостности сообщений
  • криптографических протоколах поверх HTTP

Взаимодействие с другими модулями Jsrsasign

Класс тесно связан с:

  • KJUR.crypto.MessageDigest — вычисление хеша
  • KEYUTIL — загрузка ключей
  • KJUR.asn1 — работа с DER структурами
  • KJUR.crypto.Cipher — вспомогательное шифрование

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

При работе с KJUR.crypto.Signature ключевым аспектом является согласованность всех компонентов криптосхемы:

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

Любое расхождение в этих параметрах приводит к невозможности верификации подписи даже при корректных ключах.