KEYUTIL.getKey из JWK-объекта

В библиотеке Jsrsasign работа с криптографическими ключами строится вокруг утилиты KEYUTIL, которая обеспечивает унифицированное преобразование различных представлений ключей в внутренние структуры, используемые при подписи, проверке и шифровании. Одним из наиболее важных сценариев является получение криптографического ключа из JWK (JSON Web Key) — формата, стандартизированного в RFC 7517 и широко применяемого в современных системах аутентификации и обмена ключами.

JWK представляет ключ в виде JSON-структуры, содержащей параметры алгоритма, тип ключа, кривую (для EC), модуль и экспоненту (для RSA), а также дополнительные метаданные. Основная задача KEYUTIL.getKey заключается в преобразовании этого JSON-представления в объект ключа, который может быть использован внутри Jsrsasign для криптографических операций.

JWK для RSA-ключа обычно содержит следующие поля:

  • kty — тип ключа (RSA, EC, oct)
  • n — модуль (base64url)
  • e — экспонента
  • alg — рекомендуемый алгоритм
  • kid — идентификатор ключа
  • use — назначение (sig, enc)

Пример JWK:

const jwk = {
  kty: "RSA",
  n: "0vx7agoebGcQSuuPiLJXZptN3h...",
  e: "AQAB",
  alg: "RS256",
  kid: "2011-04-29"
};

В случае EC-ключей структура включает:

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

Преобразование JWK через KEYUTIL.getKey

Основная функция преобразования:

const key = KEYUTIL.getKey(jwk);

Функция анализирует поле kty и определяет тип ключа, после чего выполняет декодирование параметров из base64url и формирует внутренний объект ключа Jsrsasign.

RSA JWK → KEY Object

При обработке RSA-ключа происходит:

  1. Декодирование n (модуль) в BigInteger
  2. Декодирование e (экспонента)
  3. Формирование RSAKey объекта
  4. Назначение криптографических параметров

Внутренне это эквивалентно созданию объекта:

const rsaKey = new RSAKey();
rsaKey.setPublic(n, e);

Однако KEYUTIL.getKey выполняет этот процесс автоматически и поддерживает дополнительные проверки корректности структуры JWK.

EC JWK → KEY Object

Для эллиптических кривых:

const ecKey = KEYUTIL.getKey(jwk);

Процесс включает:

  • Определение кривой crv
  • Декодирование координат точки x, y
  • Восстановление публичного ключа на эллиптической кривой
  • При наличии d — формирование приватного ключа

Jsrsasign использует внутреннюю реализацию ECDSA-ключей, совместимую с OpenSSL-форматами.

Обработка приватных JWK

Если JWK содержит параметр d, ключ интерпретируется как приватный. Это критически важно, так как наличие приватной части открывает возможность выполнения операций подписи:

const privJwk = {
  kty: "RSA",
  n: "...",
  e: "AQAB",
  d: "KJd9..."
};

const key = KEYUTIL.getKey(privJwk);

После преобразования объект может использоваться в:

  • KJUR.crypto.Signature
  • KJUR.crypto.Decrypt

Алгоритмическое соответствие

KEYUTIL.getKey сопоставляет JWK с криптографическими алгоритмами Jsrsasign:

kty alg Внутренний тип
RSA RS256 / PS256 RSAKey
EC ES256 / ES384 KJUR.crypto.ECDSA
oct HS256 Array/WordArray

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

Пример использования с подписью JWT

const jwk = {
  kty: "RSA",
  n: "...",
  e: "AQAB",
  d: "..."
};

const key = KEYUTIL.getKey(jwk);

const sig = new KJUR.crypto.Signature({ alg: "SHA256withRSA" });
sig.init(key);
sig.updateString("data");
const signature = sig.sign();

Особенности декодирования base64url

JWK использует base64url без padding. KEYUTIL.getKey автоматически:

  • заменяет - на +
  • заменяет _ на /
  • добавляет padding при необходимости

Это позволяет корректно восстанавливать числовые значения RSA и EC параметров без ручной обработки.

Поддержка ключей Symmetric (oct)

Для симметричных ключей:

const jwk = {
  kty: "oct",
  k: "AyM1..."
};

В этом случае KEYUTIL.getKey возвращает бинарное представление ключа, пригодное для HMAC-операций:

const key = KEYUTIL.getKey(jwk);

const sig = new KJUR.crypto.Signature({ alg: "HmacSHA256" });
sig.init(key);

Ошибки и ограничения обработки JWK

При работе с KEYUTIL.getKey возникают типовые ограничения:

  • отсутствие обязательных полей (n, e, crv, k)
  • некорректный base64url
  • несоответствие kty структуре данных
  • неподдерживаемые кривые EC

В таких случаях функция генерирует исключения, прерывающие процесс конвертации.

Внутренний процесс разбора JWK

Логика преобразования включает несколько этапов:

  1. Проверка наличия kty
  2. Ветвление по типу ключа
  3. Декодирование параметров
  4. Создание объекта ключа (RSAKey / ECKey / symmetric buffer)
  5. Приведение к унифицированному интерфейсу Jsrsasign

Особое значение имеет этап нормализации: библиотека приводит разные JWK-диалекты к единому внутреннему представлению.

Совместимость с внешними JWK-провайдерами

KEYUTIL.getKey поддерживает JWK, сгенерированные:

  • OAuth2/OpenID Connect провайдерами
  • JWKS endpoint сервисами
  • библиотеками Web Crypto API (с преобразованием)

При этом важно учитывать различия:

  • Web Crypto JWK может содержать дополнительные поля (ext, key_ops)
  • Jsrsasign игнорирует неиспользуемые параметры, сохраняя только криптографически значимые

Практика работы с JWKS (набор ключей)

Часто JWK приходит в составе JWKS:

const jwks = {
  keys: [ jwk1, jwk2 ]
};

Выбор ключа осуществляется вручную по kid:

const key = KEYUTIL.getKey(jwks.keys[0]);

В реальных сценариях kid используется для выбора нужного ключа перед вызовом getKey.

Преобразование JWK в PEM через KEYUTIL

Хотя основная задача — получение объекта ключа, результат можно преобразовать:

const key = KEYUTIL.getKey(jwk);
const pem = KEYUTIL.getPEM(key);

Это полезно при интеграции с системами, ожидающими PEM-формат.

Поведение при неполных ключах

Если JWK содержит только публичные параметры:

  • RSA: n, e
  • EC: x, y

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

Внутренние типы данных

Jsrsasign использует:

  • RSAKey — для RSA операций
  • KJUR.crypto.ECDSA — для EC
  • массивы байтов — для симметричных ключей

KEYUTIL.getKey выступает адаптером между JSON-описанием и этими структурами.

Влияние параметра alg на интерпретацию

Поле alg не является обязательным для JWK, но влияет на:

  • выбор алгоритма подписи
  • валидацию соответствия ключа операции
  • поведение JWT-операций

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