Класс KJUR.jws.JWS

KJUR.jws.JWS является центральным классом библиотеки jsrsasign для работы с JSON Web Signature (JWS). Он реализует создание, разбор, проверку и управление цифровыми подписями в формате JWS, определённом спецификацией RFC 7515. Класс предоставляет высокоуровневый API поверх криптографических примитивов библиотеки и скрывает большую часть низкоуровневой работы с кодированием, сериализацией и криптографическими операциями.


Структура JWS

JWS представляет собой компактную строку, состоящую из трёх частей:

BASE64URL(header) + "." + BASE64URL(payload) + "." + BASE64URL(signature)
  • Header — JSON-объект с параметрами алгоритма и метаданными
  • Payload — полезная нагрузка (данные токена)
  • Signature — криптографическая подпись

Пример структуры:

eyJalg...header...XQ.eyJzdWIiOiIxMjM0NTY3ODkwIn0.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

Роль KJUR.jws.JWS

Класс KJUR.jws.JWS отвечает за:

  • генерацию JWS с использованием симметричных и асимметричных алгоритмов
  • проверку подписи JWS
  • разбор (parsing) JWS строки
  • работу с алгоритмами HS256, RS256, ES256 и другими
  • управление структурой токена

Класс работает в связке с:

  • KJUR.crypto (криптографические операции)
  • KJUR.jws.JWS.JWSHeader (обработка заголовков)
  • KJUR.jws.IntDate (временные поля, опционально)

Создание JWS

Основной способ создания JWS — метод sign.

Общий синтаксис

KJUR.jws.JWS.sign(
  alg,        // алгоритм подписи
  header,     // объект или JSON строка
  payload,    // данные
  key         // ключ (секрет или приватный ключ)
)

Пример HMAC (HS256)

const jws = KJUR.jws.JWS.sign(
  "HS256",
  { alg: "HS256", typ: "JWT" },
  JSON.stringify({ sub: "1234567890", name: "Ivan", admin: true }),
  "secret123"
);

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


Пример RSA (RS256)

const jws = KJUR.jws.JWS.sign(
  "RS256",
  { alg: "RS256", typ: "JWT" },
  JSON.stringify({ sub: "user1" }),
  privateKeyPEM
);

Проверка JWS

Проверка подписи осуществляется методом verify.

Синтаксис

KJUR.jws.JWS.verify(jwsString, key)

Пример проверки HS256

const isValid = KJUR.jws.JWS.verify(jws, "secret123");

Пример проверки RS256

const isValid = KJUR.jws.JWS.verify(jws, publicKeyPEM);

Разбор JWS

Метод parse или parseJWS позволяет извлечь компоненты токена.

const parsed = KJUR.jws.JWS.parse(jwsString);

Структура результата:

{
  headerObj: {...},
  payloadObj: {...},
  sighex: "...",
  sHeader: "...",
  sPayload: "..."
}

Извлечение компонентов

getJWSComponents

Метод позволяет разделить JWS на части:

const components = KJUR.jws.JWS.parseJWS(jws);

Результат:

[
  "header(base64url)",
  "payload(base64url)",
  "signature(base64url)"
]

Проверка через verifyJWS

Расширенный метод проверки:

KJUR.jws.JWS.verifyJWS(jws, key)

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


Алгоритмы подписи

Класс поддерживает широкий набор алгоритмов:

HMAC (симметричные)

  • HS256
  • HS384
  • HS512

RSA (асимметричные)

  • RS256
  • RS384
  • RS512

ECDSA

  • ES256
  • ES384
  • ES512

Работа с заголовком (header)

Header может задаваться как объект:

{
  alg: "HS256",
  typ: "JWT"
}

Или как JSON строка:

'{"alg":"HS256","typ":"JWT"}'

При создании JWS библиотека автоматически кодирует header в Base64URL.


Payload и его особенности

Payload может быть:

  • строкой JSON
  • уже сериализованным текстом
  • произвольными данными (вне JWT-спецификации)

Пример:

JSON.stringify({
  iss: "auth-server",
  exp: 1710000000,
  sub: "user123"
});

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

При работе с KJUR.jws.JWS возможны типовые ошибки:

  • неверный формат JWS
  • несовпадение подписи
  • неподдерживаемый алгоритм
  • некорректный ключ

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

try {
  const valid = KJUR.jws.JWS.verify(jws, "secret");
} catch (e) {
  console.log("Ошибка проверки:", e);
}

Детали криптографической обработки

При создании подписи выполняются шаги:

  1. сериализация header и payload

  2. Base64URL кодирование

  3. формирование signing input:

    base64url(header) + "." + base64url(payload)
  4. применение алгоритма подписи

  5. кодирование signature в Base64URL


Пример полного цикла HS256

const secret = "my_secret_key";

const token = KJUR.jws.JWS.sign(
  "HS256",
  { alg: "HS256", typ: "JWT" },
  JSON.stringify({ user: "admin" }),
  secret
);

const isValid = KJUR.jws.JWS.verify(token, secret);

Пример полного цикла RS256

const token = KJUR.jws.JWS.sign(
  "RS256",
  { alg: "RS256", typ: "JWT" },
  JSON.stringify({ role: "user" }),
  privateKeyPEM
);

const valid = KJUR.jws.JWS.verify(token, publicKeyPEM);

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

KJUR.jws.JWS использует Base64URL вместо стандартного Base64:

  • + заменяется на -
  • / заменяется на _
  • = удаляется

Это обеспечивает совместимость с JWT-стандартом и URL-безопасность.


Частично разобранные JWS

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

const components = KJUR.jws.JWS.parseJWS(jws);

const header = KJUR.jws.JWS.readSafeJSONString(
  KJUR.b64utos(components[0])
);

Практические сценарии использования

Аутентификация

Использование JWS как JWT для передачи идентификаторов пользователя.

Авторизация

Передача ролей и прав доступа через payload.

Защита API

Проверка подписи входящих запросов.

Подпись сообщений

Гарантия целостности передаваемых данных.


Ограничения и нюансы реализации

  • не выполняет автоматическую проверку сроков действия (exp)
  • не управляет refresh-токенами
  • не хранит ключи
  • требует явного указания алгоритма

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

KJUR.jws.JWS тесно связан с:

  • KJUR.jws.JWS.JWSUtil — утилиты
  • KJUR.crypto.* — криптографические функции
  • KJUR.asn1.* — работа с ASN.1 (для RSA/ECDSA ключей)

Структура данных внутри класса

При разборе JWS внутренние структуры выглядят как:

{
  headerS: "...",
  payloadS: "...",
  signatureS: "...",
  headerObj: {...},
  payloadObj: {...}
}

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

  • использование приватного ключа вместо публичного при проверке RS256
  • несовпадение алгоритма в header и параметрах sign()
  • передача не сериализованного payload объекта
  • использование устаревших ключей без обновления подписи

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

JWS допускает произвольные payload, включая бинарные данные (в виде строки):

const payload = "raw_data_block";

Однако большинство сценариев ориентированы на JSON.