Заголовок JWS (JSON Web Signature) — это JSON-объект, содержащий метаданные, описывающие способ подписи и дополнительные параметры, влияющие на обработку токена. Заголовок кодируется в Base64URL и размещается в первой части JWS.
Ключевые параметры заголовка позволяют определить:
Ниже рассмотрены основные поля: alg, kid,
jwk, x5c, crit,
b64.
alg — алгоритм подписиПоле alg (algorithm) является обязательным и указывает,
какой криптографический алгоритм используется для подписи.
Примеры значений:
HS256 — HMAC с SHA-256RS256 — RSA с SHA-256ES256 — ECDSA с SHA-256EdDSA — Ed25519 / Ed448Особенности:
none означает отсутствие подписи (используется
редко и требует особой осторожности)Пример:
{
"alg": "RS256"
}
В библиотеке jose:
import { SignJWT } from 'jose'
const jwt = await new SignJWT({ sub: '123' })
.setProtectedHeader({ alg: 'RS256' })
.sign(privateKey)
kid — идентификатор
ключаПоле kid (key ID) используется для указания конкретного
ключа, которым была создана подпись.
Назначение:
Пример:
{
"alg": "RS256",
"kid": "key-2024-01"
}
Типичный сценарий:
kidВ jose:
.setProtectedHeader({
alg: 'RS256',
kid: 'my-key-id'
})
jwk — встроенный JSON
Web KeyПоле jwk содержит публичный ключ прямо в заголовке
JWS.
Структура:
Пример:
{
"alg": "RS256",
"jwk": {
"kty": "RSA",
"n": "...",
"e": "AQAB"
}
}
Особенности:
Ограничения:
В jose:
.setProtectedHeader({
alg: 'RS256',
jwk: publicJwk
})
x5c — цепочка
сертификатов X.509Поле x5c содержит массив сертификатов X.509 в формате
Base64.
Назначение:
Пример:
{
"alg": "RS256",
"x5c": [
"MIIDdzCCAl+gAwIBAgIEb1...",
"MIID...root"
]
}
Особенности:
Когда используется:
В jose:
.setProtectedHeader({
alg: 'RS256',
x5c: certChainArray
})
crit — критические
параметрыПоле crit (critical) — массив строк, указывающих на
заголовочные параметры, которые должны быть обязательно понятны
обработчику.
Пример:
{
"alg": "RS256",
"crit": ["b64"],
"b64": false
}
Смысл:
Особенности:
Важно:
crit должно присутствовать в
заголовкеВ jose:
.setProtectedHeader({
alg: 'RS256',
crit: ['b64'],
b64: false
})
b64 —
управление кодированием payloadПоле b64 определяет, будет ли полезная нагрузка
(payload) закодирована в Base64URL.
Значения:
true (по умолчанию) — payload кодируетсяfalse — payload передается в “сыром” видеПример:
{
"alg": "RS256",
"b64": false,
"crit": ["b64"]
}
Особенности:
crit, если используетсяПлюсы:
Минусы:
В jose:
import { CompactSign } from 'jose'
const encoder = new TextEncoder()
const jws = await new CompactSign(encoder.encode('payload'))
.setProtectedHeader({
alg: 'HS256',
b64: false,
crit: ['b64']
})
.sign(secret)
Заголовки часто используются совместно:
Пример комплексного заголовка:
{
"alg": "RS256",
"kid": "key-1",
"x5c": ["..."],
"crit": ["b64"],
"b64": false
}
Типичные комбинации:
alg + kid — стандартный сценарий с
JWKSalg + jwk — самодостаточный токенalg + x5c — проверка через
сертификатыcrit + нестандартные поля — расширения протоколаalg и реального алгоритма — частая
уязвимостьcrit может привести к обходу
проверкиjwk требует проверки доверия к
источникуx5c требует полноценной валидации цепочки
сертификатовРекомендации:
algkid при наличии нескольких ключейnone, если это не строго контролируемая
средаcrit строго по спецификацииБиблиотека jose:
algkid при работе с JWKScrit и b64 при
явном указанииПример проверки JWS:
import { jwtVerify } from 'jose'
const { payload, protectedHeader } = await jwtVerify(token, publicKey)
console.log(protectedHeader.alg)
console.log(protectedHeader.kid)
Заголовок JWS — это гибкий механизм управления криптографией и метаданными:
alg определяет криптографиюkid, jwk, x5c — способы
указания ключаcrit — механизм строгой проверки расширенийb64 — управление кодированием данныхКорректное использование этих параметров позволяет строить безопасные, расширяемые и совместимые системы аутентификации и подписи данных.