Home/SEO, Domain & Network Inspector Tools/Webhook Signature Verifier

Webhook Signature Verifier

Validate and test HMAC-SHA256 webhook signatures, payloads, and replay defense headers for Stripe, GitHub, Shopify, and Slack.

Webhook Payload & Secret Parameters

Processed locally in browser
156 bytes

Warning: Do not format or pretty-print formatted payload. Exact byte alignment (spaces, tabs, newlines) is critical for HMAC equivalence.

Verification Status & Cryptographic Audit

Enter a received webhook header or click “Fill with computed signature” to execute continuous constant-time equality validation.

Computed HMAC-SHA256 Signature (hex):
Awaiting inputs...
Canonical Message Signed:
Empty
Production Implementation Snippet
import crypto from "crypto";

export function verifyWebhook(rawBody: Buffer, signatureHeader: string, secret: string): boolean {
  const hmac = crypto.createHmac("sha256", secret);
  const digest = Buffer.from(hmac.update(rawBody).digest("hex"), "utf8");
  const checksum = Buffer.from(signatureHeader, "utf8");
  
  if (checksum.length !== digest.length) return false;
  return crypto.timingSafeEqual(digest, checksum);
}
WebCrypto SHA-256 activeZero server latency

Cryptographic Mechanics of Webhook HMAC Signatures

A Webhook is an asynchronous HTTP POST event notification triggered by a service provider (such as Stripe, GitHub, Shopify, or Slack) to inform downstream subscriber services of state transitions. Because webhook receiver URLs are publicly reachable Internet endpoints, relying solely on public access exposes backend systems to forged event payloads, privilege escalation, and Denial of Service (DoS) exploits.

To establish mutual authenticity and payload integrity without the overhead of bilateral public-key infrastructure (PKI), modern web services employ Hash-based Message Authentication Codes (HMAC) standardized under RFC 2104. HMAC utilizes a shared symmetric secret alongside cryptographic hash algorithms, most commonly SHA-256, to produce an authoritative digest across the message body.

Proof of Origin

Only entities possessing the private shared secret key can compute a valid digest. A successful match verifies that the request originates directly from the trusted SaaS vendor.

Tamper Resistance

SHA-256 is mathematically collision-resistant. Modifying even a single whitespace character, JSON number, or boolean in transit results in a totally distinct, non-matching checksum.

Replay Defense

Pre-pending current epoch timestamps to the signed string ensures an eavesdropper cannot capture a valid historical webhook transmission and replay it to drain inventory or issue duplicate credits.

Webhook Verification Architecture by SaaS Provider

Different platforms standardize signature generation headers, canonical formatting schemes, and hashing algorithms differently. Review the architectural specifications across tier-1 service providers:

PlatformSignature HeaderEncodingMessage ConstructionReplay Defense
StripeStripe-SignatureHext.{timestamp}.{payload}Built-in (Header t)
GitHubX-Hub-Signature-256Hex (sha256=){payload}Via X-GitHub-Delivery ID
ShopifyX-Shopify-Hmac-Sha256Base64{payload}Via Webhook ID cache
SlackX-Slack-SignatureHex (v0=)v0:{timestamp}:{payload}Built-in (X-Slack-Req-Ts)
Svix / Webhooks.comsvix-signatureBase64 (v1,...){id}.{timestamp}.{payload}Built-in (svix-timestamp)

Why Does My Signature Fail? The Top 4 Debugging Pitfalls

1. Parsing JSON Body Before HMAC Computation

Framework middlewares like express.json() or body-parser parse incoming streams into JavaScript objects. Re-stringifying with JSON.stringify(req.body) disrupts key order, drops empty fields, or normalizes spacing. You MUST preserve the exact raw stream buffer via verify: (req, res, buf) => ... or Next.js route handlers with req.text().

2. Timing Attack Vulnerabilities with ==

Standard string operators abort on the first divergent character. Remote attackers measuring execution latency over thousands of requests can reconstruct byte 0, then byte 1, etc. Always use crypto.timingSafeEqual() in Node.js or hmac.compare_digest() in Python.

3. Line Break Normalization (CRLF vs LF)

Reverse proxies (such as Nginx, Apache, or Cloudflare Workers) can sometimes convert Windows line endings (\r\n) to Unix line breaks (\n). Even a single substituted invisible character will completely break HMAC verification.

4. Production vs Test Secret Mixing

In multi-tenant SaaS environments, webhook secrets differ per webhook endpoint, per application environment, and between CLI local listeners (e.g., stripe listen --forward-to creates a ephemeral secret starting with whsec_ that differs from your Stripe Dashboard endpoint secret).

Frequently Asked Questions (FAQ)

How does HMAC-SHA256 webhook signature verification work?

HMAC (Hash-based Message Authentication Code) combines a cryptographic hash function (SHA-256) with a secret key shared between sender and receiver. The sender calculates the hash over the raw HTTP request payload and attaches it to the request header. The receiving server performs the identical HMAC computation using its shared secret. If the outputs match byte-for-byte in constant time, the payload is authentic and untampered.

Why does signature verification fail when JSON payload looks identical?

HMAC signatures are calculated against the exact raw byte stream of the HTTP body. If your web framework (such as Express, Fastify, Next.js, or Django) automatically parses incoming JSON into an object and re-stringifies it, whitespace differences, line endings (CRLF vs LF), or key ordering will alter the cryptographic hash and fail verification. Webhook endpoints must always consume unparsed raw request bodies.

What is timing-safe equality and why is standard == or === insecure?

Standard string equality operators (== or ===) terminate comparison on the first mismatched character. Attackers can measure the fractional nanosecond differences in server response time to guess valid signature characters sequentially (a side-channel timing attack). Timing-safe equality functions evaluate every byte regardless of whether an early mismatch occurs.

How do webhook timestamp headers mitigate replay attacks?

Providers like Stripe, Slack, and Svix prepend a UNIX timestamp to the signature string. The receiving server verifies that the difference between the current system epoch and the header timestamp falls within an acceptable tolerance window (usually 300 seconds). Any interceptor re-broadcasting an old payload past this window will be rejected.

Does this online HMAC verifier upload my webhook secrets?

No. This tool operates 100% client-side inside your browser sandbox using the W3C Web Cryptography API (crypto.subtle). Your webhook secrets, signatures, and payloads are never transmitted to any external server or backend database.

Found this tool helpful? Share it with others!

Share on Facebook
Share on X
Share on LinkedIn
Copy URL

Related & Complementary Utilities

Explore more privacy-first client-side web tools.