RSA PKCS#1 представляет собой стандарт, описывающий схему цифровой подписи и шифрования на основе асимметричной криптографии RSA. В контексте JWT и библиотеки jose рассматривается исключительно подпись, основанная на приватном и публичном ключах.
В основе лежит принцип разделения ключей:
RSA PKCS#1 v1.5 — классическая схема подписи, применяемая в JWT через алгоритмы семейства RS*.
Ключевой особенностью является использование хэш-функций перед операцией RSA:
Таким образом, RSA не подписывает данные напрямую, а работает с их криптографическим хэшем фиксированной длины.
Алгоритмы RS256, RS384 и RS512 относятся к одной криптографической схеме, различаясь только используемой хэш-функцией.
: (m)
Наиболее распространённый вариант в JWT. Обеспечивает баланс между безопасностью и производительностью. SHA-256 формирует 256-битный хэш, который затем подписывается RSA.
Используется по умолчанию во многих системах аутентификации.
: (m)
Вариант с усиленной криптографической стойкостью за счёт более длинного хэша. SHA-384 снижает вероятность коллизий по сравнению с SHA-256, однако требует немного больших вычислительных затрат.
Используется в системах с повышенными требованиями к долговременной защите данных.
: (m)
Максимальная стойкость в рамках семейства RS*. Использует SHA-512, обеспечивая более высокий уровень криптографической надёжности за счёт увеличенного размера хэша.
Применяется там, где приоритетом является устойчивость к атакам на хэш-функции, а не скорость.
Библиотека jose реализует современный подход к работе с JSON Web Tokens, включая поддержку RSA PKCS#1 через алгоритмы RS256, RS384 и RS512.
Основные задачи библиотеки в данном контексте:
В отличие от устаревших решений, jose ориентирована на Web Crypto API и современные стандарты безопасности.
RSA требует пары ключей:
Пример структуры:
-----BEGIN PRIVATE KEY-----
...
-----END PRIVATE KEY-----
-----BEGIN PUBLIC KEY-----
...
-----END PUBLIC KEY-----
Приватный ключ хранится в защищённой среде и никогда не передаётся клиенту.
Процесс подписи включает несколько этапов:
import { SignJWT, importPKCS8 } from 'jose'
const privateKeyPem = `
-----BEGIN PRIVATE KEY-----
...
-----END PRIVATE KEY-----
`
const privateKey = await importPKCS8(privateKeyPem, 'RS256')
const jwt = await new SignJWT({ sub: 'user123' })
.setProtectedHeader({ alg: 'RS256' })
.setIssuedAt()
.setExpirationTime('2h')
.sign(privateKey)
Ключевым моментом является явное указание алгоритма в заголовке
alg.
Проверка подписи осуществляется через публичный ключ:
import { jwtVerify, importSPKI } from 'jose'
const publicKeyPem = `
-----BEGIN PUBLIC KEY-----
...
-----END PUBLIC KEY-----
`
const publicKey = await importSPKI(publicKeyPem, 'RS256')
const { payload, protectedHeader } = await jwtVerify(token, publicKey, {
algorithms: ['RS256']
})
Валидация включает:
Несмотря на общую архитектуру, различия проявляются в следующих аспектах:
Криптографическая стойкость
Производительность
Размер хэша
JWT состоит из трёх частей:
header.payload.signature
Подпись формируется следующим образом:
= _{priv}((.))
Где:
Hash — SHA-256 / SHA-384 / SHA-512RSA_priv — операция с приватным ключомσ — итоговая подписьНесмотря на зрелость RSA PKCS#1, практическая реализация часто сопровождается ошибками:
1. Несоответствие алгоритма Использование RS256 в подписи и RS512 в проверке приводит к ошибке валидации.
2. Хранение приватного ключа Утечка приватного ключа полностью компрометирует систему подписи.
3. Отсутствие ограничения algorithms Если не фиксировать список допустимых алгоритмов при проверке, возможны атаки с подменой алгоритма.
jwtVerify(token, publicKey, {
algorithms: ['RS256']
})
4. Использование устаревших библиотек Некорректная реализация PKCS#1 может приводить к уязвимостям padding oracle и signature confusion.
Выбор между RS256, RS384 и RS512 определяется компромиссом между:
RS256 остаётся де-факто стандартом в JWT-системах, тогда как RS384 и RS512 используются в высокозащищённых средах или при долгосрочном хранении токенизированных данных.