Анатомия JSON Web Key

JSON Web Key представляет собой стандартизированное JSON-представление криптографического ключа. Спецификация описана в RFC 7517 и является частью семейства стандартов JOSE (JSON Object Signing and Encryption). В экосистеме JavaScript библиотека jose опирается на JWK как основной формат обмена и хранения ключей для операций подписи, шифрования и верификации.

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


Базовая структура JWK

Любой JSON Web Key содержит обязательные и опциональные поля. Минимально валидная структура зависит от типа ключа (kty), но общая форма выглядит следующим образом:

  • kty — тип ключа
  • use — предполагаемое использование
  • key_ops — разрешённые операции
  • alg — алгоритм, с которым предполагается использование ключа
  • kid — идентификатор ключа

Пример общей структуры:

{
  "kty": "RSA",
  "kid": "2024-01-signing",
  "use": "sig",
  "alg": "RS256"
}

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


Типы ключей (kty)

Поле kty определяет криптографическую природу ключа. В рамках JWK поддерживаются несколько основных типов.

RSA

RSA-ключи используются для асимметричной криптографии: подпись, проверка подписи, шифрование.

Основные параметры:

  • n — модуль (modulus)
  • e — публичная экспонента
  • d — приватная экспонента (только для приватного ключа)

Пример:

{
  "kty": "RSA",
  "n": "base64url-modulus",
  "e": "AQAB",
  "d": "base64url-private-exponent",
  "kid": "rsa-1",
  "use": "sig",
  "alg": "RS256"
}

Особенность RSA в JWK — обязательное кодирование числовых параметров в base64url.


EC (Elliptic Curve)

EC-ключи основаны на эллиптических кривых и используются в алгоритмах ECDSA и ECDH.

Основные параметры:

  • crv — кривая (например, P-256, P-384)
  • x — координата точки X
  • y — координата точки Y
  • d — приватный компонент

Пример:

{
  "kty": "EC",
  "crv": "P-256",
  "x": "base64url-x",
  "y": "base64url-y",
  "d": "base64url-d",
  "kid": "ec-key-1",
  "use": "sig",
  "alg": "ES256"
}

EC-ключи компактнее RSA и часто используются в современных системах подписи JWT.


OKP (Octet Key Pair)

OKP применяется для современных эллиптических схем, таких как Ed25519 и X25519.

Основные параметры:

  • crv — тип кривой (Ed25519, X25519)
  • x — публичный ключ
  • d — приватный ключ

Пример:

{
  "kty": "OKP",
  "crv": "Ed25519",
  "x": "base64url-public",
  "d": "base64url-private",
  "kid": "okp-key-1",
  "use": "sig",
  "alg": "EdDSA"
}

OKP считается наиболее современным и безопасным вариантом для цифровых подписей.


oct (симметричные ключи)

Для симметричных алгоритмов используется тип oct.

Основной параметр:

  • k — секретный ключ

Пример:

{
  "kty": "oct",
  "k": "base64url-secret",
  "kid": "hmac-key-1",
  "use": "sig",
  "alg": "HS256"
}

Симметричные ключи применяются в HMAC-алгоритмах и требуют строгого контроля доступа.


Поле use: назначение ключа

Поле use определяет основное назначение ключа:

  • sig — подпись и проверка подписи
  • enc — шифрование

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

Пример:

"use": "sig"

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


key_ops: операции ключа

Поле key_ops задаёт точный список допустимых операций:

  • sign
  • verify
  • encrypt
  • decrypt
  • wrapKey
  • unwrapKey
  • deriveKey
  • deriveBits

Пример:

"key_ops": ["sign", "verify"]

В отличие от use, это более строгий механизм контроля доступа.


alg: привязка к алгоритму

Поле alg фиксирует алгоритм, для которого предназначен ключ.

Примеры:

  • RS256
  • ES256
  • EdDSA
  • HS256

Пример:

"alg": "RS256"

Использование alg снижает риск неправильного применения ключа в неподходящем криптографическом контексте.


kid: идентификатор ключа

Поле kid (Key ID) используется для идентификации ключа в наборе ключей (JWKS).

Пример:

"kid": "2026-signing-key"

Основные сценарии:

  • выбор ключа для верификации JWT
  • ротация ключей
  • кэширование ключей в клиентах

x5c, x5t и x5t#S256: сертификаты

JWK может содержать X.509 сертификаты:

x5c

Список сертификатов в цепочке:

"x5c": ["base64-cert"]

x5t

SHA-1 отпечаток сертификата:

"x5t": "thumbprint"

x5t#S256

SHA-256 отпечаток:

"x5t#S256": "sha256-thumbprint"

Эти поля используются для интеграции с PKI-инфраструктурой.


Поля для расширенных сценариев

nbf / exp (в контексте ключей встречается редко)

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


ext: расширяемость ключа

"ext": true

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


JWKS: наборы JWK

JWK редко используется изолированно. Чаще он входит в структуру JWKS (JSON Web Key Set):

{
  "keys": [
    {
      "kty": "RSA",
      "kid": "key-1",
      "n": "...",
      "e": "AQAB"
    },
    {
      "kty": "EC",
      "kid": "key-2",
      "crv": "P-256",
      "x": "...",
      "y": "..."
    }
  ]
}

JWKS используется в OAuth2, OpenID Connect и системах авторизации.


Роль JWK в библиотеке jose

В библиотеке jose JWK выступает центральным форматом для:

  • импорта ключей (importJWK)
  • экспорта ключей (exportJWK)
  • верификации JWT
  • генерации ключевых пар
  • работы с JWKS-эндпоинтами

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


Base64url как основа кодирования

Все бинарные данные в JWK кодируются в base64url:

  • без + и /
  • без =
  • безопасно для URL

Это критически важно для корректной работы JSON-передачи ключей.


Безопасностные аспекты структуры JWK

Неправильное использование JWK приводит к типовым проблемам:

  • смешивание use и key_ops
  • отсутствие kid при ротации ключей
  • утечка приватных компонентов (d, k)
  • использование слабых алгоритмов при наличии сильных ключей
  • хранение симметричных ключей в открытых JWKS

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


Взаимосвязь полей внутри JWK

JWK нельзя рассматривать как набор независимых атрибутов. Поля образуют связанную модель:

  • kty определяет набор допустимых полей
  • alg уточняет криптографический контекст
  • use и key_ops ограничивают поведение
  • kid обеспечивает идентификацию
  • криптографические параметры зависят от типа ключа

Эта связность делает JWK строго типизированной структурой в рамках JSON-экосистемы безопасности.