Hash & Checksum Generator3 min readOct 21, 2026

HMAC vs Raw Hashing: How to Secure Webhook Payloads (Stripe & GitHub Style)

Learn why raw hashing secret + payload is vulnerable to length extension attacks. Understand how HMAC-SHA256 secures API webhooks.

Direct Summary (TL;DR)

Raw hashing secret + payload (e.g., sha256(secret + body)) is vulnerable to Length Extension Attacks in Merkle-Damgård hashes. HMAC (Hash-based Message Authentication Code, RFC 2104) uses a nested two-pass hashing structure H((K ^ opad) || H((K ^ ipad) || m)) that prevents message forgery, serving as the standard for Stripe, GitHub, and Shopify webhooks.

Interactive Mickytool Utility

Solve this problem now with our free Hash & Checksum Generator

Try it instantly in your browser — zero tracking, 100% client-side privacy.

Open Hash & Checksum Generator

Specification & Architecture Reference

HMAC vs Raw Hashing: How to Secure Webhook Payloads (Stripe & GitHub Style) — Technical Summary
Security PropertyRaw Hash Concatenation (sha256(secret + m))HMAC-SHA256 (RFC 2104)
Length Extension Vulnerability❌ High Risk (Attacker can append data without knowing secret)✅ Immune (Double-pass hashing isolates state)
Timing Attack ProtectionRequires manual constant-time comparisonRequires constant-time comparison (crypto.timingSafeEqual)
Standard API AdoptionDeprecated across all modern APIsStandard for Stripe, GitHub, AWS SigV4, Shopify webhooks

The Naive Flaw of Simple Concatenation

When securing API webhooks, developers sometimes try to sign payloads by concatenating a shared secret with the message body: ```text signature = sha256(SECRET_KEY + payload) ``` While this looks reasonable at first glance, it is vulnerable to a classic cryptographic exploit: the **Length Extension Attack**.

How Length Extension Attacks Work Algorithms like MD5, SHA-1, and SHA-256 process input messages through the **Merkle-Damgård construction**. The output hash is the internal register state after consuming the final block.

An attacker who intercepts `payload` and the resulting `signature` can: 1. Reconstruct the hash engine's internal state directly from the signature without knowing `SECRET_KEY`. 2. Append arbitrary extra data (`&role=admin`) along with standard padding bytes. 3. Compute a valid signature for the extended message that your server will accept as authentic.

The HMAC Solution (RFC 2104) HMAC addresses this by employing a nested, two-pass hashing construction with inner and outer padding: $$\text{HMAC}(K, m) = H\big((K' \oplus opad) \;\Vert\; H((K' \oplus ipad) \;\Vert\; m)\big)$$ Because the outer hash consumes the result of the inner hash, intermediate internal states are isolated, preventing length extension attacks.

Verifying Webhooks Safely in Node.js ```javascript const crypto = require("crypto");

function verifyWebhook(payload, signatureHeader, secret) { const hmac = crypto.createHmac("sha256", secret); hmac.update(payload, "utf8"); const computedSignature = hmac.digest("hex");

// Prevent timing attacks using constant-time comparison return crypto.timingSafeEqual( Buffer.from(computedSignature, "hex"), Buffer.from(signatureHeader, "hex") ); } ```

Test and debug your hash computations safely in your browser using Mickytool's **Hash & Checksum Generator**.

Interactive Mickytool Utility

Solve this problem now with our free Hash & Checksum Generator

Execute this workflow immediately without saving data on remote servers.

Open Hash & Checksum Generator

Frequently Asked Questions

Why is crypto.timingSafeEqual mandatory when comparing signatures?

Standard string equality (===) returns false on the first mismatched character. Attackers can measure response time variations (timing attacks) to deduce the signature byte-by-byte.

Is HMAC required when using SHA-3 or BLAKE2?

BLAKE2 and SHA-3 (Keccak) are not Merkle-Damgård constructions and are naturally immune to length extension, though keyed BLAKE2 and HMAC-SHA-3 remain recommended practice.

Related Engineering Guides