Как проверить подписи JWT: HS256, RS256 и ES256
Как проверить подписи JWT
JWT передаёт свои claims в открытом виде. Единственное, что предотвращает подделку — это подпись. Без проверки злоумышленник может создавать произвольные токены и выдавать себя за любого пользователя. Это руководство охватывает три наиболее распространённых алгоритма подписи JWT и способы проверки каждого из них.
Процесс проверки
Независимо от алгоритма, проверка подписи JWT выполняется по одним и тем же шагам:
- Разделите токен по
., чтобы извлечь заголовок, полезную нагрузку и подпись. - Декодируйте заголовок из base64url, чтобы прочитать поле
alg. - Пересчитайте подпись из заголовка и полезной нагрузки, используя алгоритм и ключ.
- Сравните пересчитанную подпись с подписью токена.
- Если они совпадают, токен подлинный.
HS256 (HMAC-SHA256)
HS256 — это симметричный алгоритм: один и тот же секретный ключ создаёт и проверяет подпись.
signature = HMACSHA256(
base64urlEncode(header) + "." + base64urlEncode(payload),
secret
)
Для проверки пересчитайте HMAC с общим секретом и сравните:
Token: header.payload.sig
Secret: "my-shared-secret"
1. Compute: HMACSHA256("header.payload", "my-shared-secret")
2. Compare: computedSignature === sig
Рекомендации по безопасности: Секрет должен быть конфиденциальным, периодически меняться и иметь не менее 256 бит энтропии. HS256 не идеален для микросервисных архитектур, где многим сервисам нужен общий секрет.
RS256 (RSA-SHA256)
RS256 — асимметричный алгоритм. Издатель подписывает приватным ключом; проверяющие проверяют соответствующим открытым ключом.
signature = RSASHA256(
base64urlEncode(header) + "." + base64urlEncode(payload),
privateKey
)
Для проверки используйте открытый ключ:
Token: header.payload.sig
Public: "-----BEGIN PUBLIC KEY-----..."
1. Load the RSA public key
2. Verify: RSA_SHA256_verify("header.payload", sig, publicKey)
Преимущества: Ключи подписи и проверки разделены. Любой сервис может проверять, не имея секрета. Открытые ключи могут предоставляться через конечную точку JWKS для удобной ротации.
ES256 (ECDSA-SHA256)
ES256 использует ECDSA с кривой P-256. Как и RS256, он асимметричный.
signature = ECDSA_SHA256(
base64urlEncode(header) + "." + base64urlEncode(payload),
privateKey
)
Проверка использует открытый ключ ECDSA P-256. ES256 создаёт значительно меньшие подписи (64 байта против 256 байт для RSA-2048) и обеспечивает более быструю проверку.
Сравнение алгоритмов
| Свойство | HS256 | RS256 | ES256 | |----------|-------|-------|-------| | Тип ключа | Симметричный (общий секрет) | Асимметричный (пара RSA) | Асимметричный (пара EC) | | Размер подписи | 32 байта | 256 байт | 64 байта | | Распространение ключа | Передаётся секретно | Открытый ключ публичен | Открытый ключ публичен | | Ротация | Умеренная | Лёгкая (JWKS) | Лёгкая (JWKS) | | Сценарий использования | Доверенные внутренние системы | Распределённые API | Мобильные, IoT |
Распространённые ошибки при проверке
- Атака подмены алгоритма. Если ваш код читает
algиз токена без принудительной проверки, злоумышленник может изменить алгоритм. Всегда проверяйте, что алгоритм соответствует ожидаемому значению. - Принятие
alg: "none". Некоторые библиотеки принимают неподписанные токены. Явно отклоняйтеalg: "none". - Усечение подписи. Непостоянное по времени сравнение может раскрывать информацию через атаки по времени. Используйте встроенное сравнение вашей JWT-библиотеки.
Проверяйте токены JWT онлайн
Используйте инструмент JWT decoder для декодирования и проверки любого токена. Вставьте токен, просмотрите заголовок и полезную нагрузку, а также проверьте подпись, предоставив соответствующий секретный или открытый ключ. Вся обработка происходит в вашем браузере.