Обязательные и опциональные параметры при подписании

При работе с подписью JWT в библиотеке jose критически важно понимать различие между обязательными и опциональными параметрами, поскольку именно они определяют корректность криптографической операции и совместимость токена с другими системами.

Ключ подписи (key)

Без криптографического ключа операция подписи невозможна. В jose ключ передаётся в виде одного из поддерживаемых типов:

  • KeyObject (например, из crypto в Node.js)
  • Uint8Array для симметричных алгоритмов (HS256, HS512)
  • криптографический объект для асимметричных алгоритмов (RS256, ES256 и др.)

Ключ должен соответствовать выбранному алгоритму. Например:

  • HS256 → общий секрет (HMAC)
  • RS256 → приватный RSA-ключ
  • ES256 → приватный ECDSA-ключ

Несоответствие ключа алгоритму приводит к ошибкам на этапе выполнения или к созданию некорректной подписи.


Алгоритм подписи (alg)

Алгоритм задаётся в защищённом заголовке JWT и является обязательным параметром:

setProtectedHeader({ alg: 'RS256' })

Алгоритм определяет:

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

Без alg библиотека не может сформировать корректный JWS, так как структура подписи становится неопределённой.


Полезная нагрузка (payload)

Payload — это данные, которые будут подписаны. В jose он может быть:

  • объектом (JWT claims)
  • строкой (реже, для JWS общего назначения)

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

new SignJWT({ sub: '123', role: 'admin' })

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


Формирование подписи через sign(key)

Финальный обязательный этап — вызов метода:

await jwt.sign(privateKey)

На этом этапе происходит:

  • сериализация заголовка
  • кодирование payload
  • вычисление криптографической подписи

Без передачи ключа операция невозможна.


Обязательные параметры на уровне JWT-объекта

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

setProtectedHeader

.setProtectedHeader({ alg: 'ES256' })

Этот вызов обязателен, так как именно он определяет алгоритм подписи. Без него токен не может быть корректно подписан.


Опциональные параметры заголовка

Заголовок JWT может содержать дополнительные поля, которые не влияют напрямую на алгоритм, но расширяют возможности взаимодействия.

kid (Key ID)

Используется для выбора ключа на стороне верификации:

.setProtectedHeader({
  alg: 'RS256',
  kid: 'key-2024-01'
})

Полезен при ротации ключей и работе с несколькими ключами одновременно.


typ (Type)

Определяет тип токена:

{ typ: 'JWT' }

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


crit (Critical header parameters)

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


x5c (X.509 certificate chain)

Применяется в инфраструктуре с сертификатами:

  • передача цепочки сертификатов
  • упрощение проверки подписи

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


Опциональные параметры полезной нагрузки (claims)

Хотя payload обязателен как структура, его содержимое в JWT часто полностью опционально с точки зрения спецификации.

Стандартные зарегистрированные claims

iss (issuer)

Определяет издателя токена.

sub (subject)

Идентификатор субъекта.

aud (audience)

Получатель токена.

exp (expiration time)

Время истечения.

nbf (not before)

Время начала действия.

iat (issued at)

Время выпуска.

jti (JWT ID)

Уникальный идентификатор токена.


В jose эти поля часто задаются через специализированные методы:

.setIssuedAt()
.setExpirationTime('2h')
.setNotBefore('0s')
.setJti('unique-id')

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


Алгоритмическая совместимость и скрытые обязательные условия

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

1. Соответствие алгоритма и типа ключа

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

  • подписать RS256 симметричным ключом
  • использовать EC-ключ для HMAC

2. Корректная сериализация payload

Payload должен быть сериализуемым в JSON (если это объект). Нельзя использовать:

  • функции
  • BigInt без преобразования
  • циклические структуры

3. Кодировка данных

jose автоматически использует base64url, но любые нестандартные входные данные могут привести к несовместимости с другими JWT-реализациями.


Расширенные опциональные механизмы

unprotected header (JWS general JSON serialization)

В некоторых режимах JWS допускает наличие незашищённых заголовков, но это используется редко и снижает безопасность.


detaching payload

В JWS возможно создание detached payload, где данные не включаются в сам токен:

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

Взаимосвязь обязательных и опциональных параметров

В jose важно понимать, что система разделяет:

  • криптографически обязательные параметры (alg, key, payload)
  • структурные обязательные методы API (setProtectedHeader)
  • опциональные метаданные безопасности (kid, typ, x5c)
  • опциональные бизнес-claims (iss, exp, aud и др.)

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