SIP Error 438 Invalid Identity Header: ошибки сигнатуры и утверждений PASSporT
- Маршрутизация вызова прерывается ответом
SIP/2.0 438 Invalid Identity Header. - Верифицирующий софтсвитч сообщает о несовпадении криптографической подписи (Signature Verification Failed).
- Расхождение телефонного номера в SIP From/PAI и в полезной нагрузке (Claims) токена PASSporT.
- Таймстемп создания токена (
iat) признан устаревшим (Replay Attack / Time Skew).
1. Декодирование и проверка токена PASSporT (JWT)
Токен в заголовке Identity состоит из трех частей (Header.Payload.Signature), закодированных в Base64URL. Декодируйте Payload:
{
"attest": "A",
"dest": {"tn": ["+12025550100"]},
"iat": 1672531199,
"orig": {"tn": "+12025550199"},
"origid": "123e4567-e89b-12d3-a456-426614174000"
}Причины ошибки 438:
- Номер в
orig.tnне совпадает в точности с номером в SIP-заголовкеFromилиP-Asserted-Identity. - Номер в
dest.tnне совпадает с номером вRequest-URIилиTo. - Время создания
iat(Issued At) отличается от системных часов сервера проверки более чем на допустимый дрейф (обычно 60 секунд). - Электронная подпись ES256 не сходится с открытым ключом сертификата.
2. Синхронизация системного времени (NTP)
Критически важный шаг для устранения дрейфа меток времени iat:
chronyc tracking
chronyc sources -v3. Нормализация номеров перед подписанием в диалплане
Убедитесь, что номера в токен и в сигнальные заголовки передаются в идентичном формате E.164 (с префиксом '+' или без него):
# Asterisk extensions.conf:
exten => _X.,1,NoOp(Normalize to E.164)
same => n,Set(CALLERID(num)=+${CALLERID(num):-11})
same => n,Set(PJSIP_HEADER(update,From)=<sip:${CALLERID(num)}@domain.com>)
same => n,Dial(PJSIP/${EXTEN}@carrier-shaken) Частые вопросы (FAQ)
Каков допустимый интервал расхождения времени (iat) для заголовка Identity?
В соответствии со спецификациями ATIS/IETF, допустимое окно составляет не более ±60 секунд от момента создания токена до момента верификации принимающей стороной.
Может ли модификация Request-URI промежуточным прокси вызвать ошибку 438?
Да. Если транзитный узел изменит номер назначения (To/R-URI), а в токене останется старый 'dest.tn', криптографическая проверка утверждений завершится ошибкой 438.
Как проверить валидность подписи PASSporT вручную?
Можно воспользоваться утилитой jwt.io или скриптом на Python (библиотека PyJWT/cryptography), скормив открытый ключ x509 и строку токена.
Что делать, если ошибка 438 вызвана несовпадением алгоритма подписи?
Убедитесь, что в заголовке JWT указан алгоритм 'alg': 'ES256'. Использование других алгоритмов (RS256, HS256) запрещено стандартом SHAKEN.