JWT представляет собой компактный токен, состоящий из трёх частей:
заголовка, полезной нагрузки и подписи. В библиотеке jsrsasign проверка
целостности и подлинности такого токена выполняется через низкоуровневый
механизм работы с JWS (JSON Web Signature), где основная роль
принадлежит методу KJUR.jws.JWS.verify.
JWT фактически является частным случаем JWS. Токен имеет вид:
header.payload.signature
Каждая часть закодирована в Base64URL. Подпись вычисляется на основе первых двух частей и секретного ключа (для HMAC) или приватного ключа (для RSA/ECDSA).
При проверке важно не только убедиться в корректности подписи, но и правильно интерпретировать алгоритм, указанный в заголовке.
В jsrsasign проверка JWS реализуется через:
KJUR.jws.JWS.verify(jws, key, alg)
Параметры:
jws — строка JWT/JWSkey — секретный ключ (для HS256) или публичный ключ в
PEM-формате (для RS256/ES256)alg — алгоритм подписи (например, "HS256",
"RS256")Метод возвращает:
true — подпись корректнаfalse — подпись недействительна или данные
поврежденыHS256 использует симметричный ключ, который одинаков для подписи и проверки:
const jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
const secret = "my_secret_key"
const isValid = KJUR.jws.JWS.verify(jwt, secret, ["HS256"])
Важно, что алгоритм передаётся как массив допустимых значений. Это позволяет ограничить список разрешённых алгоритмов.
В случае RSA используется асимметричная криптография. Подпись создаётся приватным ключом, а проверка выполняется публичным:
const jwt = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..."
const publicKey = `
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqh...
-----END PUBLIC KEY-----
`
const isValid = KJUR.jws.JWS.verify(jwt, publicKey, ["RS256"])
Ключ должен быть в корректном PEM-формате, иначе проверка завершится ошибкой.
Метод выполняет несколько последовательных шагов:
Если хотя бы один этап не проходит проверку, результат будет
false.
Передача массива алгоритмов — важный механизм защиты:
KJUR.jws.JWS.verify(jwt, key, ["RS256", "RS512"])
Это предотвращает атаки, связанные с подменой алгоритма (например, downgrade attack, когда злоумышленник пытается заменить RS256 на HS256).
Хотя KJUR.jws.JWS.verify проверяет только подпись, на
практике JWT требует дополнительной валидации:
exp — срок действияnbf — начало действияiss — издательaud — аудиторияЭти проверки выполняются отдельно после декодирования payload:
const payloadObj = KJUR.jws.JWS.parse(jwt).payloadObj
const now = Math.floor(Date.now() / 1000)
if (payloadObj.exp < now) {
throw new Error("Токен истёк")
}
В библиотеке также существует более высокий уровень:
KJUR.jws.JWS.verifyJWT()
Но verify используется чаще в низкоуровневых сценариях,
где требуется:
Частые причины возврата false:
Иногда система поддерживает несколько схем подписи одновременно:
const isValid = KJUR.jws.JWS.verify(
jwt,
publicKey,
["RS256", "RS384", "RS512"]
)
Это полезно при миграции криптографических алгоритмов или интеграции с внешними сервисами.
При использовании проверки подписи важно учитывать следующие моменты:
alg из заголовка без валидацииЕсли проверка успешна, это означает только одно — токен не был изменён после подписания. Это не гарантирует:
Поэтому KJUR.jws.JWS.verify используется как первый
уровень проверки, после которого всегда следует анализ payload.
const jwt = "..."
const isValidSignature = KJUR.jws.JWS.verify(jwt, publicKey, ["RS256"])
if (!isValidSignature) {
throw new Error("Некорректная подпись")
}
const parsed = KJUR.jws.JWS.parse(jwt)
const payload = parsed.payloadObj
const now = Math.floor(Date.now() / 1000)
if (payload.exp <= now) {
throw new Error("JWT просрочен")
}
Такая схема разделяет криптографическую проверку и бизнес-валидацию, что делает систему более предсказуемой и безопасной.