Webhook signature verifier & simulator
What is a Webhook Signature Verifier?
Timing-Safe Webhook HMAC-SHA256 Signature Verification & Simulator
When building payment and e-commerce integrations with Razorpay, Shopify, Stripe, or GitHub, verifying the authenticity of incoming HTTP webhooks is critical. Without signature verification, malicious attackers can forge fake order.paid or payment.captured webhook requests to fulfill orders without actual payment.
DevDeskApp provides a client-side timing-safe HMAC verification and simulation studio built with the native Web Crypto API (crypto.subtle), ensuring raw un-serialized payload integrity without leaking secrets to remote servers.
Supported Webhook Security Standards
- Razorpay Webhooks: Header
X-Razorpay-Signature- Computed as HexadecimalHMAC-SHA256(raw_body, secret). - Shopify Webhooks: Header
X-Shopify-Hmac-Sha256- Computed as Base64HMAC-SHA256(raw_body, secret). - Stripe Webhooks: Header
Stripe-Signature- Uses timestamped schemet=1729500000,v1=hex_hmacwhere the signed payload is${timestamp}.${raw_body}to prevent replay attacks. - GitHub Webhooks: Header
X-Hub-Signature-256- Computed assha256=hex_hmac.
The Golden Rule: Never Re-serialize JSON Before Verification
A common vulnerability in Node.js and Python webhook handlers is parsing the incoming body with JSON.parse() and then calling JSON.stringify() before hashing. Because JSON key ordering and whitespace vary, re-serializing alters the cryptographic hash. Our verifier operates strictly on the exact raw text string as received by the HTTP server.
Practical Verification Example (Razorpay)
Raw Payload: {"event":"payment.captured","payment_id":"pay_9821","amount":49900}
Secret Key: secret_test_9988
Expected Signature (Hex): e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
Status: VALID SIGNATURE ✓
Related Tools & Security References
- Internal Utilities: HMAC Hash Generator | Base64 String Converter | API Request Tester
- Official Security Documentation: Stripe Webhook Signatures Guide | Razorpay Webhook Verification | Shopify Webhook Security
Frequently Asked Questions: Webhook HMAC Signature Verification & Security
Why should I never verify signatures using JSON.stringify()?
Cryptographic hashing algorithms like HMAC-SHA256 are sensitive to every single byte, whitespace, and key order. When JSON is parsed and re-stringified, the key sequence and indentation change, producing a completely different hash and failing verification.
What is timing-safe comparison and why does it prevent timing attacks?
Standard string equality (===) returns false on the very first mismatched character, taking slightly less CPU execution time for early mismatches. Attackers can measure response times down to nanoseconds to guess signatures character by character. Timing-safe comparison takes identical time regardless of where mismatches occur.
How does Stripe's timestamped signature prevent replay attacks?
Stripe prepends a Unix timestamp (t=...) to the signed payload. When your server verifies the signature, it also checks if the timestamp is within a 5-minute tolerance window. This prevents attackers from intercepting and re-transmitting old webhook payloads.
Does Razorpay use Hex or Base64 encoding for HMAC-SHA256 signatures?
Razorpay strictly uses Hexadecimal encoding (lowercase hex characters), whereas Shopify uses Base64 encoding. Our tool automatically sets the correct encoding per provider.
Can I simulate and generate signature headers to test my local server?
Yes. Switch to "Simulate / Generate Signature Header" mode to generate authentic headers and ready-to-run cURL commands for testing your localhost or staging endpoints.
Are my webhook secrets sent to any external server?
No. The verification algorithm runs entirely in your local browser using the Web Crypto API (crypto.subtle). Your secret keys and request payloads never leave your computer.