Проверка подписи: verify

Библиотека Jsrsasign предоставляет полноценный набор инструментов для работы с криптографией на стороне JavaScript, включая создание и проверку цифровых подписей. Основная функция для проверки подписи — verify, которая используется в различных контекстах: RSA, ECDSA, HMAC, JWT и X.509 сертификаты.


Базовый принцип проверки подписи

Цифровая подпись в большинстве сценариев состоит из трёх компонентов:

  • исходное сообщение (data)
  • подпись (signature)
  • публичный ключ (public key)

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


Проверка RSA подписи через KJUR.crypto.Signature

В Jsrsasign работа с RSA-подписями чаще всего осуществляется через класс KJUR.crypto.Signature.

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

sig.init(publicKeyPem);
sig.updateString("Hello world");

const isValid = sig.verify(signatureHex);

Ключевые этапы:

  • init(publicKeyPem) — инициализация публичным ключом в формате PEM
  • updateString() — загрузка данных, которые были подписаны
  • verify(signatureHex) — проверка подписи в hex-формате

Если используется Base64 подпись, её необходимо предварительно декодировать или преобразовать.


Проверка ECDSA подписи

Для алгоритмов на эллиптических кривых используется тот же интерфейс, но с другим алгоритмом:

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

sig.init(publicKeyPem);
sig.updateString("Important message");

const isValid = sig.verify(signatureHex);

ECDSA требует точного соответствия кривой, указанной в ключе, иначе проверка завершится ошибкой.


Использование KEYUTIL для работы с ключами

Jsrsasign предоставляет утилиту KEYUTIL, которая позволяет преобразовывать ключи между форматами.

Загрузка публичного ключа:

const pubKey = KEYUTIL.getKey(publicKeyPem);

После этого ключ можно использовать в Signature:

const sig = new KJUR.crypto.Signature({ alg: "SHA256withRSA" });
sig.init(pubKey);
sig.updateString("Data");

const result = sig.verify(signatureHex);

Проверка подписи с бинарными данными

Если данные представлены не строкой, а байтовым массивом:

sig.updateHex(binaryHexData);
const isValid = sig.verify(signatureHex);

Важно соблюдать единый формат входных данных: либо строковый, либо hex.


Проверка подписи X.509 сертификата

Jsrsasign умеет извлекать публичный ключ из сертификата:

const cert = new X509();
cert.readCertPEM(certPem);

const publicKey = cert.getPublicKey();

Далее проверка выполняется стандартным способом:

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

sig.init(publicKey);
sig.updateString("Message");

const isValid = sig.verify(signatureHex);

Проверка JWT подписи (JWS)

Одним из самых частых сценариев использования verify является проверка JWT.

const isValid = KJUR.jws.JWS.verifyJWT(token, publicKey, {
    alg: ["RS256"]
});

Расшифровка процесса:

  • токен автоматически разбивается на header, payload и signature
  • извлекается алгоритм
  • выполняется проверка подписи по публичному ключу

Дополнительно можно получить payload:

const payloadObj = KJUR.jws.JWS.readSafeJSONString(b64utoutf8(payload));

Форматы подписи и частые ошибки

Jsrsasign чувствителен к формату подписи:

  • HEX (чаще всего для RSA/ECDSA)
  • Base64URL (в JWT)
  • DER (ASN.1 структура)

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

  • несоответствие алгоритма (SHA256withRSA vs SHA1withRSA)
  • неправильная кодировка подписи
  • использование строки вместо hex или наоборот
  • несовпадение публичного ключа

Проверка подписи через low-level API

Низкоуровневый вариант через KJUR.crypto.Signature позволяет гибко управлять процессом:

const sig = new KJUR.crypto.Signature({
    alg: "SHA256withRSA",
    prov: "cryptojs/jsrsa"
});

sig.init(publicKey);
sig.updateString(data);

const verified = sig.verify(signatureHex);

Параметр prov указывает криптографический backend.


Работа с несколькими алгоритмами

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

function verifySignature(alg, key, data, sigHex) {
    const signature = new KJUR.crypto.Signature({ alg });
    signature.init(key);
    signature.updateString(data);
    return signature.verify(sigHex);
}

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

  • SHA256withRSA
  • SHA384withRSA
  • SHA256withECDSA
  • SHA1withRSA (устаревший)

Проверка целостности данных через verify

Функция verify фактически отвечает за криптографическую гарантию:

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

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


Внутренняя логика verify

Процесс проверки включает:

  1. Хеширование входного сообщения
  2. Декодирование подписи
  3. Криптографическое сравнение с публичным ключом
  4. Возврат boolean результата

При RSA используется модульная экспонентация, при ECDSA — проверка точек на кривой.


Типовые сценарии использования

  • проверка JWT токенов в веб-приложениях
  • валидация подписанных API запросов
  • проверка цифровых сертификатов
  • защита сообщений от подмены
  • проверка firmware или конфигураций

Особенности работы в браузере и Node.js

Jsrsasign одинаково работает в обеих средах, но:

  • в браузере чаще используется cryptojs/jsrsa
  • в Node.js возможна интеграция с native crypto через обёртки
  • производительность выше в Node при больших объёмах данных

Обработка результата verify

Функция всегда возвращает boolean:

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

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