Белый список алгоритмов в jose — это механизм контроля криптографических алгоритмов, которые разрешены при проверке и создании JWT (JWS/JWE). Его задача заключается в предотвращении атак, основанных на подмене алгоритма или выборе небезопасных параметров подписи и шифрования.
Формат JOSE допускает указание алгоритма прямо в заголовке токена:
{
"alg": "HS256",
"typ": "JWT"
}
При отсутствии строгой проверки это создаёт критическую уязвимость:
сервер может доверять значению alg, пришедшему от клиента.
В результате возможны ситуации, когда:
none-алгоритма без
подписиБелый список алгоритмов исключает подобные сценарии, фиксируя допустимые значения независимо от входящего токена.
algОдна из классических атак возникает, когда сервер поддерживает несколько алгоритмов. Например:
alg на HS256При отсутствии ограничения список допустимых алгоритмов превращается в точку компрометации.
noneИсторически некоторые реализации JWT позволяли использовать:
{
"alg": "none"
}
Это означало отсутствие подписи. При неправильной настройке сервер мог принять такой токен как валидный.
В современных реализациях JOSE контроль алгоритмов реализуется через явное указание допустимых значений при проверке токена.
Любой входящий токен проверяется только в рамках заранее заданного списка:
Любые другие значения автоматически отклоняются, даже если они присутствуют в заголовке токена.
В библиотеке JOSE контроль алгоритмов осуществляется через параметры функций проверки JWT.
import { jwtVerify, createRemoteJWKSet } from 'jose'
const JWKS = createRemoteJWKSet(new URL('https://example.com/.well-known/jwks.json'))
const { payload, protectedHeader } = await jwtVerify(token, JWKS, {
algorithms: ['RS256']
})
Ключевой параметр:
algorithms: ['RS256']
Любой токен с другим alg будет отклонён до проверки
подписи.
В некоторых системах допускается несколько алгоритмов, но список остаётся фиксированным:
const { payload } = await jwtVerify(token, JWKS, {
algorithms: ['RS256', 'ES256']
})
Такой подход используется при миграции криптографических схем, когда требуется поддержка старого и нового алгоритма одновременно.
При генерации JWT алгоритм также задаётся явно, без зависимости от внешних параметров:
import { SignJWT } from 'jose'
const token = await new SignJWT({ userId: 123 })
.setProtectedHeader({ alg: 'RS256' })
.setIssuedAt()
.setExpirationTime('2h')
.sign(privateKey)
Здесь алгоритм фиксируется на уровне кода, что исключает случайную подмену.
В случае JWE (JSON Web Encryption) применяется аналогичный принцип ограничения алгоритмов:
import { compactDecrypt } from 'jose'
const { plaintext } = await compactDecrypt(jwe, privateKey, {
keyManagementAlgorithms: ['RSA-OAEP-256'],
contentEncryptionAlgorithms: ['A256GCM']
})
Контроль разделён на два уровня:
keyManagementAlgorithms — управление ключамиcontentEncryptionAlgorithms — шифрование
содержимогоJOSE реализует проверку алгоритма до криптографических операций:
algЭто важно: даже корректно подписанный токен не будет принят, если алгоритм не разрешён.
jwtVerify(token, JWKS)
Без параметра algorithms поведение зависит от версии и
конфигурации, что создаёт риск принятия нежелательных алгоритмов.
alg из
токенаИспользование значения из заголовка без проверки:
// антипаттерн
const alg = decoded.header.alg
Одновременная поддержка HS256 и RS256 в одном контексте увеличивает риск атак через подмену ключей.
Допустимые алгоритмы должны быть ограничены только необходимыми:
Следует избегать:
Разные типы токенов должны использовать разные политики:
При несовпадении алгоритма JOSE генерирует ошибку валидации до криптографической проверки. Типичные сценарии:
JOSEAlgNotAllowedJWSInvalid: Invalid Compact JWSЭто поведение предотвращает утечку информации о ключах и снижает поверхность атаки.
Белый список алгоритмов формирует фиксированную границу доверия:
Такой подход устраняет класс атак, связанных с подменой
alg, и делает обработку JWT предсказуемой и устойчивой к
внешнему влиянию.