Генерация ключей: generateKeyPair и generateSecret

В библиотеке Jose генерация асимметрических ключей реализована через функцию generateKeyPair, которая опирается на Web Crypto API и возвращает пару ключей: публичный и приватный. Эти ключи используются в сценариях подписи JWT (JWS) и шифрования (JWE), где требуется разделение ролей между сторонами.

Основная особенность подхода заключается в том, что ключи создаются средствами криптографического провайдера окружения (Node.js или браузер), а не вручную через произвольные алгоритмы.

Поддерживаемые алгоритмы

Функция поддерживает набор криптографических алгоритмов, каждый из которых выбирается в зависимости от требований безопасности и совместимости:

  • RS256 / RS384 / RS512 — RSA с SHA-2
  • ES256 / ES384 / ES512 — ECDSA на кривых P-256, P-384, P-521
  • EdDSA — Ed25519 (современный алгоритм подписи с высокой производительностью)

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

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

Функция возвращает объект с двумя ключами, которые могут быть использованы отдельно:

import { generateKeyPair } from 'jose'

const { publicKey, privateKey } = await generateKeyPair('RS256')

Результат представляет собой два объекта CryptoKey. Они совместимы с WebCrypto и могут быть напрямую переданы в функции подписи или верификации JWT.

Настройки генерации ключей

generateKeyPair позволяет управлять поведением создаваемых ключей через дополнительные параметры:

  • extractable — разрешает ли извлечение ключа (например, экспорт в JWK)
  • keyUsages — сценарии использования ключа (sign, verify, encrypt, decrypt)

Пример:

const { publicKey, privateKey } = await generateKeyPair('ES256', {
  extractable: true,
  keyUsages: ['sign', 'verify']
})

Контроль keyUsages особенно важен, так как WebCrypto строго ограничивает операции, доступные каждому ключу.

Поведение в Node.js и браузере

В Node.js используется встроенный модуль crypto.webcrypto, начиная с современных версий Node. В браузере используется нативный window.crypto.subtle.

Разница не видна на уровне API Jose, но влияет на производительность и доступность алгоритмов в старых окружениях.


Генерация симметрических ключей через generateSecret

Функция generateSecret используется для создания симметрических ключей, которые применяются в алгоритмах HMAC и некоторых сценариях JWE. В отличие от асимметрических ключей, здесь используется один общий секрет для подписи и проверки.

Основные алгоритмы

Чаще всего симметрические ключи используются с:

  • HS256 / HS384 / HS512 — HMAC с SHA-2
  • A128GCM / A192GCM / A256GCM — для шифрования (JWE)

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

Генерация секрета

Базовый вызов:

import { generateSecret } from 'jose'

const secret = await generateSecret('HS256')

Результатом является объект CryptoKey, который может использоваться для подписания и проверки JWT.

Особенности генерации

В отличие от generateKeyPair, здесь не возвращается пара ключей. Генерируется один криптографически стойкий секрет, размер которого соответствует требованиям алгоритма.

Для HS256 это обычно 256-битный ключ, однако библиотека сама обеспечивает корректную длину, соответствующую выбранному алгоритму.

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

import { generateSecret, SignJWT } from 'jose'

const secret = await generateSecret('HS256')

const jwt = await new SignJWT({ sub: '1234567890' })
  .setProtectedHeader({ alg: 'HS256' })
  .sign(secret)

Отличия между generateKeyPair и generateSecret

Разница между этими функциями определяется моделью криптографии:

Асимметричная модель (generateKeyPair):

  • Два ключа: публичный и приватный
  • Подходит для распределённых систем
  • Используется в RSA, ECDSA, EdDSA
  • Позволяет безопасно передавать публичный ключ

Симметричная модель (generateSecret):

  • Один общий секрет
  • Используется для HMAC и части JWE
  • Требует безопасного канала передачи секрета
  • Обычно проще и быстрее в вычислениях

Работа с WebCrypto и жизненный цикл ключей

Ключи, созданные через Jose, являются объектами WebCrypto CryptoKey, что накладывает ряд особенностей:

  • они могут быть временными (non-extractable)
  • могут быть ограничены по операциям
  • могут быть экспортированы только при разрешении extractable: true

Пример ограничения:

const { privateKey } = await generateKeyPair('RS256', {
  extractable: false
})

Такой ключ нельзя экспортировать, что повышает безопасность при работе в серверных приложениях.


Практическое применение в JWT и JWE

Генерация ключей в Jose тесно связана с последующим использованием в:

  • подписании JWT через SignJWT
  • проверке JWT через jwtVerify
  • шифровании через EncryptJWT
  • расшифровке через jwtDecrypt

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

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


Типичные ошибки при генерации ключей

При работе с generateKeyPair и generateSecret часто возникают проблемы, связанные не с библиотекой, а с криптографическими ограничениями окружения:

  • использование неподдерживаемого алгоритма в текущей версии Node.js
  • попытка экспорта ключа без extractable: true
  • несовместимость keyUsages с операцией подписи или шифрования
  • ожидание строки вместо CryptoKey

Эти ограничения являются частью WebCrypto и не обходятся на уровне Jose.