The Anatomy of HMAC-SHA256 Signature Headers
Platforms deliver signatures in HTTP headers (e.g., Stripe-Signature: t=1614552000,v1=5257a863e7... or X-Hub-Signature-256: sha256=...). The payload consists of a timestamp combined with the raw HTTP request body bytes.
The sending server uses a shared secret key and the HMAC (Hash-based Message Authentication Code) algorithm with SHA-256 to generate a unique hexadecimal hash.
Preventing Timing Attacks with Constant-Time Equality
A critical vulnerability in naive webhook verification is using standard JavaScript equality (`signature === computedSignature`). Standard string comparison exits on the first mismatched character, allowing attackers to measure microsecond timing discrepancies and guess the signature character-by-character.
Always use constant-time comparisons (like `crypto.timingSafeEqual` in Node.js or bitwise XOR loops in browser JavaScript) to guarantee identical execution time regardless of mismatch position.
Step-by-Step Tutorial
Capture Raw Payload Bytes
Read the raw body as an unparsed UTF-8 buffer before JSON.parse() strips whitespace or reorders keys.
Import Webhook Signing Secret
Use crypto.subtle.importKey() with algorithm HMAC and hash SHA-256 to import your secret key.
Compute and Verify Digest
Compute crypto.subtle.sign() and compare the resulting hex string using constant-time comparison.
Ready to Try It Yourself?
DocSwift processes everything directly on your device. Fast, safe, and completely free forever.
How helpful was this guide?
Rated 4.9 / 5 by 3,420+ users worldwide
Share with Colleagues & Friends
Help others protect their document privacy
Frequently Asked Questions
Why must I verify the raw body instead of parsed JSON?
Cryptographic hashes are bit-exact. Calling JSON.parse() and then JSON.stringify() changes key ordering and whitespace, yielding a completely different hash that fails verification.
Can I verify webhook payloads safely in the browser?
Yes! DocSwift Webhook Verifier uses the native Web Crypto API in local browser memory. Your private endpoint secrets never leave your device.