← Все инструменты
Наши заметки

Ручная проверка X-Device-Signature через CyberChef

Когда подпись webhook не совпадает, в первую очередь нужно понять, чья сторона сравнения ошибается — ваша или наша. CyberChef позволяет прогнать ровно тот же алгоритм подписи, что и UnifyPort, в браузере, с теми же входными данными, что видит ваш обработчик — секунд за тридцать.

Что именно подписывает UnifyPort

Каждая доставка с настроенным signing secret приходит с тремя header:

X-Device-Delivery-Id: d_01J2K…
X-Device-Timestamp: 1716800000
X-Device-Signature: 9f8c…

Подпись вычисляется так:

X-Device-Signature = hex( HMAC-SHA256( secret, timestamp + "." + raw_body ) )

Что стоит держать на виду перед отладкой:

  • Байт между timestamp и body — ASCII-точка (.), а не перевод строки.
  • raw_body — это байты, которые мы отправили, до JSON-парсинга, удаления пробелов, unicode-нормализации на вашей стороне.
  • hex-вывод — нижний регистр. Сравнение с digest в верхнем регистре даст false-negative.

Рецепт CyberChef

В CyberChef положите в панель recipe две операции по порядку:

  1. 1. HMAC — поставьте Hashing function в SHA256. Вставьте signing secret в поле Key, TypeUTF8.
  2. 2. To HexDelimiter оставьте пустым, Bytes per line0. Получится hex-строка без пробелов в нижнем регистре, ровно как в header.

В панели Input вставьте именно <timestamp>.<raw_body> — например:

1716800000.{"id":"evt_demo","type":"message.received",...}

Output должен совпасть с X-Device-Signature доставки. Если нет — баг локализован в трёх местах: другой secret, body, изменённый по пути, или вы читаете timestamp из неправильного header.

Когда ручная проверка действительно стоит свеч

  • После ротации signing secret. Подтвердит, что новый secret реально дошёл до обработчика, прежде чем грешить на DNS или старый деплой.
  • После апгрейда JSON-библиотеки. Некоторые парсеры переотдают body перед передачей валидатору — это легко пропустить, пока подписи внезапно не разойдутся.
  • Когда коллега говорит «у меня работает». Оба запускают один и тот же рецепт с одними и теми же входами; тот, у кого digest другой, держит неверный secret.

Про вставку secret в веб-страницу

CyberChef — статический клиентский бандл: всё крутится в вашем браузере, и в официальной хостед-версии secret не покидает машину. Если вы всё равно нервничаете из-за расширений браузера или общих сессий, запустите CyberChef локально (клон репозитория, откройте index.html) или используйте DevToys — полностью офлайн-эквивалент на десктопе. Для боевой ротации signing secret сравнение нужно делать кодом с constant-time-функцией, а не глазами по выводу CyberChef.

После ручной проверки

Переложите эквивалент в обработчик. Большинство языков везут примитив в стандартной библиотеке: crypto.createHmac в Node, hmac.new в Python, hmac.New в Go. Сравнивайте только constant-time-функцией (timingSafeEqual, hmac.compare_digest, hmac.Equal) — никогда не ==.