JSON Web Key Set представляет собой контейнер, в котором публикуется набор криптографических ключей в формате JSON Web Key (JWK). Такой формат используется для распространения публичных ключей, применяемых при проверке подписи JSON Web Token (JWT). В контексте Jsrsasign работа с JWKS позволяет автоматически извлекать и использовать нужный ключ для проверки подписи токена без ручного управления сертификатами или PEM-файлами.
JWKS всегда представляет собой JSON-объект с фиксированной структурой, где основным элементом является массив ключей.
Минимально корректный JWKS выглядит следующим образом:
{
"keys": [
{
"kty": "RSA",
"kid": "example-key-id",
"use": "sig",
"alg": "RS256",
"n": "modulus-base64url",
"e": "AQAB"
}
]
}
Ключевым элементом является поле keys, которое содержит
массив объектов JWK. Каждый объект описывает один криптографический ключ
и его метаданные.
keys — обязательное поле JWKS. Оно всегда является
массивом. В него могут входить ключи разных типов и назначения
одновременно.
Пример расширенного набора:
{
"keys": [
{ "kty": "RSA", "kid": "key-1", "use": "sig", "alg": "RS256", "n": "...", "e": "AQAB" },
{ "kty": "EC", "kid": "key-2", "use": "sig", "crv": "P-256", "x": "...", "y": "..." }
]
}
Такая структура используется для поддержки ротации ключей и одновременного существования нескольких алгоритмов подписи.
Каждый элемент массива keys — это JSON Web Key. Он
содержит обязательные и опциональные поля, зависящие от типа
криптографии.
Независимо от алгоритма, часто встречаются следующие атрибуты:
kty — тип ключа (Key Type)kid — идентификатор ключаuse — назначение ключа (например, sig для
подписи)alg — алгоритм, для которого предназначен ключkty определяет криптографический тип ключа:
RSA — RSA-ключиEC — эллиптические кривыеoct — симметрические ключи (секреты)От этого значения зависит набор обязательных параметров.
RSA-ключ является наиболее распространённым вариантом для JWT подписи.
{
"kty": "RSA",
"kid": "rsa-1",
"use": "sig",
"alg": "RS256",
"n": "base64url-modulus",
"e": "AQAB"
}
n — модуль RSA (base64url)e — публичная экспонента (обычно AQAB, что
соответствует 65537)Именно эти параметры используются Jsrsasign для восстановления публичного ключа.
EC (Elliptic Curve) ключи используются в алгоритмах типа ES256, ES384 и ES512.
{
"kty": "EC",
"kid": "ec-1",
"use": "sig",
"crv": "P-256",
"x": "base64url-x",
"y": "base64url-y",
"alg": "ES256"
}
crv — кривая (например, P-256,
P-384, P-521)x, y — координаты точки на эллиптической
кривойЭти значения представляют публичную точку ключа.
Тип oct используется для HMAC-подписей.
{
"kty": "oct",
"kid": "hmac-1",
"k": "base64url-secret",
"alg": "HS256"
}
k — секретный ключ, закодированный в base64urlТакой ключ применяется только на стороне сервера, так как требует секретного значения.
kid (Key ID) — критически важный элемент JWKS. Он
позволяет определить, какой ключ использовать для проверки конкретного
JWT.
В заголовке JWT обычно присутствует:
{
"alg": "RS256",
"kid": "rsa-1"
}
При проверке библиотека:
kid из токенаВ Jsrsasign работа с JWKS осуществляется через
KEYUTIL.
JWKS можно получить как строку JSON и разобрать:
const jwks = JSON.parse(jwksString);
Далее используется преобразование ключей:
const key = KEYUTIL.getKey(jwks.keys[0]);
Однако более типичный сценарий — поиск ключа по kid.
function getKeyFromJWKS(jwks, kid) {
const jwk = jwks.keys.find(k => k.kid === kid);
if (!jwk) throw new Error("Key not found");
return KEYUTIL.getKey(jwk);
}
const isValid = KJUR.jws.JWS.verifyJWT(token, key, {
alg: ["RS256"]
});
В этом процессе ключ предварительно извлекается из JWKS.
В реальных системах JWKS часто размещается по URL:
https://example.com/.well-known/jwks.json
Пример загрузки:
async function loadJWKS(url) {
const res = await fetch(url);
return await res.json();
}
После загрузки ключи кешируются, чтобы избежать повторных запросов.
JWKS поддерживает одновременное существование нескольких ключей. Это позволяет безопасно менять ключи без прерывания работы системы.
Типичный сценарий:
Корректный JWKS должен соответствовать ряду требований:
keysktyn и ecrv, x,
ykidНарушение структуры приводит к невозможности восстановления ключа в Jsrsasign.
Jsrsasign позволяет преобразовать JWK в PEM:
const pem = KEYUTIL.getPEM(KEYUTIL.getKey(jwk));
Это удобно для интеграции с системами, ожидающими PEM-формат.
На практике часто встречаются следующие проблемы:
Без kid невозможно выбрать нужный ключ при наличии
нескольких.
Если JWT подписан RS256, а ключ помечен как ES256, проверка всегда будет провалена.
n, e, x, y должны
быть корректно закодированы. Даже одна ошибка ломает восстановление
ключа.
При ротации ключей клиент может использовать старый кеш, не содержащий актуального ключа.
JWKS является частью стандартной схемы OpenID Connect и OAuth 2.0. Сервер авторизации публикует JWKS, а клиент:
kidТакая модель обеспечивает централизованное управление ключами и упрощает масштабирование систем аутентификации.