Импорт ключей: importSPKI, importPKCS8, importX509, importJWK

Библиотека JOSE предоставляет набор функций для работы с современными криптографическими форматами, используемыми в экосистеме JWT, JWS, JWE и JWK. Одной из ключевых задач при работе с асимметричной криптографией является корректный импорт ключей из различных представлений: PEM, X.509 и JWK.

В библиотеке за это отвечают функции importSPKI, importPKCS8, importX509, importJWK. Каждая из них предназначена для строго определённого формата входных данных и типа ключа.


Общая модель работы с ключами в JOSE

Внутри JOSE ключи приводятся к единому внутреннему представлению — CryptoKey (Web Crypto API). Это позволяет унифицировать операции подписи, проверки, шифрования и расшифрования независимо от исходного формата ключа.

Типовая цепочка выглядит так:

  • получение ключа (PEM / JWK / сертификат)
  • импорт в CryptoKey
  • использование в SignJWT, jwtVerify, CompactEncrypt и других API

importSPKI: импорт публичного ключа из PEM (SPKI)

Назначение

importSPKI используется для импорта публичных ключей, представленных в формате SPKI (Subject Public Key Info), обычно закодированных в PEM.

SPKI — это стандарт X.509 для хранения публичных ключей без приватной части.


Сигнатура

importSPKI(pem, alg, options?)
  • pem — строка PEM с публичным ключом
  • alg — алгоритм (например, "RS256", "ES256")
  • options — дополнительные параметры (редко используются)

Пример PEM-ключа (SPKI)

-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqh...
-----END PUBLIC KEY-----

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

import { importSPKI, jwtVerify } from 'jose'

const publicKey = await importSPKI(
  process.env.PUBLIC_KEY,
  'RS256'
)

const { payload } = await jwtVerify(token, publicKey)

Особенности

  • Используется только для публичных ключей
  • Чаще всего применяется для проверки JWT
  • Поддерживает RSA и EC алгоритмы
  • Не подходит для приватных ключей

importPKCS8: импорт приватного ключа из PEM (PKCS#8)

Назначение

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

PKCS#8 — универсальный стандарт хранения приватных ключей, поддерживающий RSA, EC и другие алгоритмы.


Сигнатура

importPKCS8(pem, alg, options?)
  • pem — PEM строка приватного ключа
  • alg — алгоритм (например, "RS256", "ES256")
  • options — дополнительные параметры

Пример PEM (PKCS#8)

-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqh...
-----END PRIVATE KEY-----

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

import { importPKCS8, SignJWT } from 'jose'

const privateKey = await importPKCS8(
  process.env.PRIVATE_KEY,
  'RS256'
)

const jwt = await new SignJWT({ sub: '123' })
  .setProtectedHeader({ alg: 'RS256' })
  .sign(privateKey)

Особенности

  • Используется только для приватных ключей
  • Применяется при создании JWT и JWS
  • Поддерживает RSA и EC ключи
  • Требует строгого соответствия алгоритма

importX509: импорт ключа из X.509 сертификата

Назначение

importX509 предназначен для извлечения публичного ключа из X.509 сертификата.

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


Сигнатура

importX509(cert, alg, options?)
  • cert — PEM сертификат X.509
  • alg — алгоритм ключа
  • options — дополнительные параметры

Пример X.509 сертификата

-----BEGIN CERTIFICATE-----
MIIDdzCCAl+gAwIBAgIEb...
-----END CERTIFICATE-----

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

import { importX509, jwtVerify } from 'jose'

const publicKey = await importX509(
  process.env.CERT,
  'RS256'
)

const { payload } = await jwtVerify(token, publicKey)

Отличие от importSPKI

Параметр importSPKI importX509
Вход публичный ключ сертификат
Метаданные нет есть
CA цепочка нет может присутствовать
Использование JWT verification enterprise PKI

Особенности

  • Извлекает только публичный ключ
  • Поддерживает корпоративные PKI-системы
  • Полезен при работе с TLS-сертификатами
  • Может использоваться для проверки цепочек доверия (вне JOSE)

importJWK: импорт ключа из JSON Web Key

Назначение

importJWK используется для загрузки ключей в формате JWK (JSON Web Key) — стандартизированного JSON-представления криптографических ключей.


Сигнатура

importJWK(jwk, alg, options?)
  • jwk — объект JSON Web Key
  • alg — алгоритм (например, "RS256")
  • options — дополнительные параметры

Пример JWK

{
  "kty": "RSA",
  "e": "AQAB",
  "n": "sXch...base64...",
  "alg": "RS256",
  "use": "sig"
}

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

import { importJWK, jwtVerify } from 'jose'

const jwk = {
  kty: 'RSA',
  e: 'AQAB',
  n: process.env.JWK_N
}

const publicKey = await importJWK(jwk, 'RS256')

const { payload } = await jwtVerify(token, publicKey)

Особенности JWK

  • Полностью JSON-ориентированный формат
  • Удобен для API и микросервисов
  • Может содержать ключи RSA, EC, OKP
  • Поддерживает метаданные (kid, use, alg)

Типичные сценарии

  • хранение ключей в конфигурации
  • загрузка ключей из JWKS endpoint
  • интеграция с OAuth2 / OpenID Connect

Сравнение методов импорта ключей

Метод Формат входа Тип ключа Основное применение
importSPKI PEM (SPKI) публичный проверка JWT
importPKCS8 PEM (PKCS#8) приватный подпись JWT
importX509 PEM сертификат публичный PKI / TLS / enterprise
importJWK JSON публичный / приватный API / JWKS

Взаимодействие с алгоритмами

Во всех функциях важно корректно указывать алгоритм:

  • RSA: "RS256", "PS256"
  • ECDSA: "ES256", "ES384"
  • EdDSA: "EdDSA"

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

  • тип криптографического ключа
  • допустимые операции (sign / verify)
  • требования к длине ключа

Ошибки при импорте ключей

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

Если ключ RSA, а указан ES256:

JOSENotSupported: unsupported key algorithm

Повреждённый PEM

JWKInvalid: failed to parse key

Несоответствие типа ключа

  • приватный ключ передан в importSPKI
  • сертификат передан в importPKCS8

Внутренние преобразования

После импорта все ключи приводятся к CryptoKey:

  • нормализуются параметры
  • привязывается алгоритм
  • устанавливаются usage flags (sign, verify)

Это позволяет использовать единый API:

  • jwtVerify
  • SignJWT
  • jwtDecrypt
  • CompactEncrypt

Практическая модель выбора функции импорта

  • публичный PEM ключ → importSPKI
  • приватный PEM ключ → importPKCS8
  • сертификат X.509 → importX509
  • JSON ключ (JWKS, API) → importJWK