Ручная проверка X-Device-Signature через CyberChef
Когда подпись webhook не совпадает, в первую очередь нужно понять, чья сторона сравнения ошибается — ваша или наша. CyberChef позволяет прогнать ровно тот же алгоритм подписи, что и UnifyPort, в браузере, с теми же входными данными, что видит ваш обработчик — секунд за тридцать.
Что именно подписывает UnifyPort
Каждая доставка с настроенным signing secret приходит с тремя header:
Подпись вычисляется так:
Что стоит держать на виду перед отладкой:
- Байт между timestamp и body — ASCII-точка (
.), а не перевод строки. raw_body— это байты, которые мы отправили, до JSON-парсинга, удаления пробелов, unicode-нормализации на вашей стороне.- hex-вывод — нижний регистр. Сравнение с digest в верхнем регистре даст false-negative.
Рецепт CyberChef
В CyberChef положите в панель recipe две операции по порядку:
- 1. HMAC — поставьте Hashing function в
SHA256. Вставьте signing secret в поле Key, Type —UTF8. - 2. To Hex — Delimiter оставьте пустым, Bytes per line —
0. Получится hex-строка без пробелов в нижнем регистре, ровно как в header.
В панели Input вставьте именно <timestamp>.<raw_body> — например:
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.
Частые вопросы
- Как вручную проверить подпись webhook UnifyPort?
- В CyberChef добавьте HMAC (Hashing function SHA256, ваш signing secret в поле Key с кодировкой UTF8), затем To Hex (delimiter пустой, bytes per line 0). Вставьте
<timestamp>.<raw_body>ровно как есть в панель Input. Output должен совпасть с headerX-Device-Signatureбайт в байт. - Почему моя подпись не совпадает с той, что отправляет UnifyPort?
- Три частые причины: (1) вы используете неверный signing secret — сверьте значение с тем, что видите в dashboard; (2) body был изменён до проверки — переотданный JSON, удаление пробелов или unicode-нормализация сломают digest; (3) timestamp прочитан из неправильного header — подписывается только
X-Device-Timestamp, а не Date-header фреймворка. - Безопасно ли вставлять signing secret в CyberChef?
- Официальный хостед-CyberChef — статический клиентский бандл: secret не покидает ваш браузер, и серверного логирования нет. Если вы всё равно хотите нулевую экспозицию, клонируйте репозиторий и откройте
index.htmlлокально или используйте DevToys — полностью офлайн-эквивалент на десктопе.
После ручной проверки
Переложите эквивалент в обработчик. Большинство языков везут примитив в стандартной библиотеке: crypto.createHmac в Node, hmac.new в Python, hmac.New в Go. Сравнивайте только constant-time-функцией (timingSafeEqual, hmac.compare_digest, hmac.Equal) — никогда не ==.