bitlvl
RU

Проверка подписи вебхуков

Выберите провайдера, вставьте сырое тело запроса в точности как получено, заголовок подписи и секрет. Инструмент пересчитывает подпись и показывает ожидаемое значение, чтобы вы увидели, какая часть неверна.

 

Результаты и сообщения этого инструмента выводятся на английском языке.

Как работают подписи вебхуков

Вебхук — это просто HTTP POST с чужого сервера, и любой может отправить POST на ваш URL. Чтобы доказать, что запрос пришёл от провайдера, он вычисляет HMAC по телу с секретом, известным только вам двоим, и отправляет его в заголовке. Вы пересчитываете и сравниваете. Секрет никогда не передаётся; передаётся только хеш.

Почему возникает «неверная подпись»

  1. Вы хешировали разобранное тело, а не сырые байты. Фреймворки, разбирающие JSON до запуска вашего обработчика (Express с express.json(), Rails, Django), передают вам объект; повторная сериализация меняет пробелы и порядок ключей, и хеш больше не совпадает. Захватывайте сырое тело.
  2. Неверный секрет. У Stripe свой whsec_ для каждого эндпоинта и окружения; секрет GitHub задаётся на каждый вебхук; signing secret Slack — это не токен бота.
  3. Провайдер подписывает не только тело. Stripe подписывает timestamp.body; Slack — v0:timestamp:body; Svix — id.timestamp.body; Twilio — URL плюс отсортированные поля формы. Рецепт каждого показывается выше при выборе.
  4. Кодировка. Одни провайдеры отправляют hex, другие Base64; некоторые добавляют префикс sha256=. Сравните формы.
  5. Прокси. Прокси или CDN, перекодирующие тело (gzip, charset), либо ограничение размера тела, обрезающее его, сломают хеш.

Безопасное сравнение

В продакшене сравнивайте функцией с постоянным временем выполнения (crypto.timingSafeEqual, hmac.compare_digest, hash_equals) и проверяйте, что временная метка свежая (Stripe и Slack допускают пять минут), чтобы остановить повторы. Эта страница — отладчик, а не эталонная реализация; она использует обычное сравнение, поскольку атаки по времени против вашего собственного браузера не представляют угрозы.

Вопросы

Мой секрет здесь в безопасности?

HMAC вычисляется в вашем браузере через WebCrypto, и страница не делает сетевых запросов. Тем не менее используйте секрет тестового эндпоинта и ротируйте всё, что вставляли в веб-страницу, если хотите быть строгими.

Почему GitHub отправляет и X-Hub-Signature, и X-Hub-Signature-256?

Первый — HMAC-SHA1, сохранён для старых интеграций; второй — HMAC-SHA256, именно его нужно проверять. Оба вычисляются по сырому телу с одним и тем же секретом.

Ожидаемое значение совпадает, кроме регистра. Это ошибка?

Hex нечувствителен к регистру в коде проверки любого провайдера, так что нет; этот инструмент тоже сравнивает hex без учёта регистра. Base64 чувствителен к регистру.

Stripe говорит, что временная метка слишком старая.

Библиотеки Stripe отклоняют подписи, у которых t= отличается от текущего времени более чем на 300 секунд, чтобы предотвратить повторы. Повторная отправка захваченного запроса позже провалится именно по этой причине, даже если HMAC верен; инструмент отмечает возраст.