JSON Web Key (JWK) представляет собой стандартизированное JSON-представление криптографических ключей. Для RSA-ключей JWK описывает математическую структуру алгоритма RSA через набор обязательных и дополнительных параметров. В библиотеке Jsrsasign работа с JWK тесно связана с генерацией, импортом, экспортом и использованием ключей для подписи и проверки JWT, а также для низкоуровневых криптографических операций.
RSA-ключ в формате JWK может содержать как открытые, так и закрытые компоненты. Открытая часть используется для проверки подписи и шифрования, закрытая — для создания подписи и расшифрования.
RSA JWK всегда содержит параметр kty, который определяет
тип ключа:
kty: "RSA" — ключ RSAДалее идут базовые параметры:
n — модуль RSA (modulus)e — открытая экспонента (public exponent)Для приватного ключа добавляются дополнительные поля:
d — приватная экспонента (private exponent)p — первый простой множительq — второй простой множительdp — d mod (p − 1)dq — d mod (q − 1)qi — q⁻¹ mod pRSA основан на разложении большого числа на простые множители.
n = p q
Параметр n является произведением двух больших простых
чисел p и q. Он используется как часть
открытого и закрытого ключа.
e
e — число, которое используется для шифрования и
проверки подписи. Чаще всего встречается значение 65537, так как оно
обеспечивает баланс между безопасностью и производительностью.
d e^{-1} }
d — обратное значение к e по модулю функции
Эйлера. Именно оно используется для создания цифровой подписи и
расшифровки данных.
n = p q
Пара p и q — секретные простые числа, на
которых строится вся безопасность RSA. Их утечка полностью
компрометирует ключ.
Эти параметры используются для ускорения вычислений с помощью китайской теоремы об остатках:
dp = d mod (p − 1)dq = d mod (q − 1)qi = q⁻¹ mod pОни позволяют значительно ускорить операции подписи и расшифровки.
Пример структуры приватного RSA JWK:
{
"kty": "RSA",
"n": "base64url-modulus",
"e": "AQAB",
"d": "base64url-private-exponent",
"p": "base64url-prime1",
"q": "base64url-prime2",
"dp": "base64url-exponent1",
"dq": "base64url-exponent2",
"qi": "base64url-coefficient",
"alg": "RS256",
"use": "sig",
"kid": "key-id"
}
Открытый ключ содержит только:
{
"kty": "RSA",
"n": "base64url-modulus",
"e": "AQAB"
}
Jsrsasign предоставляет удобные средства для конвертации JWK в внутренние представления ключей и обратно.
const keyObj = KEYUTIL.getKey({
kty: "RSA",
n: "....",
e: "AQAB",
d: "....",
p: "....",
q: "....",
dp: "....",
dq: "....",
qi: "...."
});
После этого keyObj становится объектом, который можно
использовать для подписания или проверки JWT.
Jsrsasign позволяет генерировать RSA ключи и получать их в формате JWK:
const kp = KEYUTIL.generateKeypair("RSA", 2048);
const pubJwk = KEYUTIL.getJWKFromKey(kp.pubKey);
const privJwk = KEYUTIL.getJWKFromKey(kp.prvKey);
После получения приватного ключа:
const header = { alg: "RS256", typ: "JWT" };
const payload = { sub: "1234567890", name: "Alice" };
const sHeader = JSON.stringify(header);
const sPayload = JSON.stringify(payload);
const jwt = KJUR.jws.JWS.sign(
"RS256",
sHeader,
sPayload,
privKey
);
Где privKey — ключ, полученный через
KEYUTIL.getKey() из JWK.
const isValid = KJUR.jws.JWS.verifyJWT(jwt, pubKey, {
alg: ["RS256"]
});
Публичный ключ содержит только n и e, что
делает его безопасным для распространения.
Jsrsasign поддерживает преобразование между форматами:
const key = KEYUTIL.getKey(jwk);
const pem = KEYUTIL.getPEM(key);
const key = KEYUTIL.getKey(pem);
const jwk = KEYUTIL.getJWKFromKey(key);
Параметры p и q никогда не включаются в
публичные ключи. Их утечка приводит к возможности факторизации
n и восстановлению d.
В реальных системах:
p и q хранятся только в защищённом
хранилищеПри использовании приватного ключа Jsrsasign может использовать CRT-оптимизацию:
m^d n
Заменяется на:
m_1 = m^{dp} p,m_2 = m^{dq} q
Далее результат объединяется через:
h = (q^{-1}(m_1 - m_2)) p
и
m = m_2 + hq
Эта оптимизация критична для производительности при больших ключах (2048–4096 бит).
Публичный RSA JWK минимально состоит из:
n — модульe — экспонентаЭтого достаточно для:
Внутри Jsrsasign ключи представлены не как чистый JWK, а как объект с методами:
signString()verifyString()encrypt()decrypt()JWK выступает как формат сериализации для передачи между системами.
Наиболее частые проблемы:
n или ektyКритические правила при обработке:
p и qRSA JWK чаще всего используется в контексте JWT:
n и e — проверка подписи токенаd, p, q — создание подписи
токенаАлгоритмы: