JSON Web Key (JWK): структура и поля

JSON Web Key представляет собой стандартизированное JSON-представление криптографических ключей, используемое в Web Crypto API и экосистеме JOSE (JSON Object Signing and Encryption). Основная цель формата — обеспечить переносимость ключей между различными системами, протоколами и библиотеками без привязки к бинарным форматам.

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


Общая структура объекта JWK

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

{
  "kty": "RSA",
  "kid": "key-id",
  "use": "sig",
  "key_ops": ["sign", "verify"],
  "alg": "RS256",
  "ext": true
}

Каждое поле несёт строго определённую семантику и участвует в интерпретации ключа криптографическими системами.


Поле kty (Key Type)

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

Основные значения:

  • RSA — RSA-ключи
  • EC — эллиптические кривые (Elliptic Curve)
  • oct — симметричные ключи (octet sequence)

Пример:

"kty": "RSA"

Тип ключа определяет набор обязательных дополнительных параметров. Например, RSA требует модуль и экспоненту, EC — параметры кривой и координаты точки.


Поле use (Public Key Use)

use описывает предполагаемое назначение ключа.

Возможные значения:

  • sig — подпись (sign/verify)
  • enc — шифрование (encrypt/decrypt)

Пример:

"use": "sig"

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


Поле key_ops (Key Operations)

key_ops задаёт допустимые операции с ключом. В отличие от use, это более точная декларация разрешённых действий.

Возможные значения:

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

Пример:

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

В Web Crypto API это поле напрямую соотносится с параметром keyUsages при импорте/экспорте ключей.


Поле alg (Algorithm)

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

Примеры:

  • RS256 — RSA с SHA-256
  • ES256 — ECDSA с P-256 и SHA-256
  • A256GCM — AES-GCM с 256-битным ключом

Пример:

"alg": "RS256"

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


Поле kid (Key ID)

kid — идентификатор ключа, используемый для выбора ключа из набора (JWK Set).

Пример:

"kid": "2026-01-signing-key"

kid особенно важен в системах с ротацией ключей, где одновременно существует несколько активных ключей.


Поле ext (Extractable)

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

  • true — ключ можно экспортировать
  • false — ключ неэкспортируемый

Пример:

"ext": true

В Web Crypto API соответствует параметру extractable при генерации ключа.


Симметричные ключи (kty = “oct”)

Для симметричных ключей используется поле k, содержащее секрет в формате base64url.

Поле k

{
  "kty": "oct",
  "k": "mF7u9sQpZl8k3v..."
}

k — это бинарные данные ключа, закодированные в base64url без padding.

Используется в алгоритмах:

  • AES-CBC
  • AES-GCM
  • HMAC

RSA ключи (kty = “RSA”)

RSA JWK требует набора обязательных параметров.

Обязательные поля RSA:

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

Пример публичного RSA ключа:

{
  "kty": "RSA",
  "n": "0vx7agoebGcQSuuPiLJXZptN9n...",
  "e": "AQAB",
  "alg": "RS256",
  "use": "sig",
  "kid": "rsa-key-1"
}

Приватный RSA ключ:

{
  "kty": "RSA",
  "n": "0vx7agoebGcQSuuPiLJXZptN9n...",
  "e": "AQAB",
  "d": "X4cTteJY_gn4FYPsXB8y...",
  "p": "83i-7IvMGXoMXCskv73TKrB...",
  "q": "3dfOR9cuYq-0S-3XbP8x...",
  "dp": "G4sPXkc6Ya9y8oR...",
  "dq": "s9lAH9fggBsoFR...",
  "qi": "GyM_p6JrXyS2...",
  "alg": "RS256",
  "ext": true
}

CRT-параметры (p, q, dp, dq, qi) ускоряют операции дешифрования и подписи.


EC ключи (kty = “EC”)

Ключи на эллиптических кривых используют координаты точки на кривой.

Основные поля:

  • crv — кривая (curve)
  • x — координата X
  • y — координата Y
  • d — приватный скаляр (для приватного ключа)

Пример публичного EC ключа:

{
  "kty": "EC",
  "crv": "P-256",
  "x": "f83OJ3D2xF4Fh3Q...",
  "y": "x_FEzRu9Yd4T6K...",
  "use": "sig",
  "alg": "ES256"
}

Приватный EC ключ:

{
  "kty": "EC",
  "crv": "P-256",
  "x": "f83OJ3D2xF4Fh3Q...",
  "y": "x_FEzRu9Yd4T6K...",
  "d": "NzbLSX7aGQ...",
  "alg": "ES256",
  "ext": true
}

Поддерживаемые кривые в Web Crypto API:

  • P-256
  • P-384
  • P-521

Кодирование значений JWK

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

Особенности base64url:

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

Это обеспечивает безопасное использование ключей в URL и JSON без экранирования.


JWK Set (наборы ключей)

Несколько ключей группируются в структуру JWK Set:

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

JWK Set используется в:

  • JWT валидации
  • OAuth 2.0 / OpenID Connect
  • распределённых системах подписи

Связь JWK и Web Crypto API

В Web Crypto API JWK используется для:

  • importKey()
  • exportKey()

Пример импорта:

crypto.subtle.importKey(
  "jwk",
  jwk,
  { name: "RSA-PSS", hash: "SHA-256" },
  true,
  ["sign"]
);

Экспорт:

crypto.subtle.exportKey("jwk", key);

Ограничения и особенности Web Crypto

  • Не все поля JWK обязательны для всех алгоритмов
  • Web Crypto API игнорирует неизвестные поля
  • Некоторые поля (alg, use) не влияют на криптографическую операцию, но используются для метаданных
  • Ключи всегда привязаны к контексту CryptoKey

Типовые ошибки при работе с JWK

Несовпадение алгоритма

Если alg не соответствует параметрам importKey, импорт может завершиться ошибкой.

Неверное кодирование base64url

Обычный base64 без преобразования приводит к некорректным значениям n, e, x, y, k.

Отсутствие обязательных полей

  • RSA без n или e недопустим
  • EC без crv, x, y считается неполным
  • oct без k невозможен

Практическая структура проверки JWK

При обработке JWK обычно выполняется логическая валидация:

  • соответствие kty и набора полей
  • корректность base64url значений
  • согласованность key_ops и use
  • совместимость alg с Web Crypto API

Минимальные корректные JWK

RSA публичный ключ

{
  "kty": "RSA",
  "n": "...",
  "e": "AQAB"
}

EC публичный ключ

{
  "kty": "EC",
  "crv": "P-256",
  "x": "...",
  "y": "..."
}

Symmetric key

{
  "kty": "oct",
  "k": "base64url-value"
}