GS
genstack.tools
Back to Developer Tools

HMAC Webhook Signature Generator & Verifier

RFC 2104

Compute HMAC-SHA256, SHA-384, and SHA-512 message authentication codes in Hex and Base64 locally in your browser.

Webhook Provider Presets

1. Secret Key, Hash Algorithm & Raw Payload

Computed HMAC-SHA-256 (Hexadecimal)
Computed HMAC-SHA-256 (Base64 — Shopify / Okta Format)

2. Constant-Time Signature Verifier

javascript
Webhook Verifier (Node.js)
import crypto from "node:crypto";

const SECRET_KEY = "whsec_8f92a7d1e4b6c30918273645fedcba98";
const RAW_BODY = "{\"id\":\"evt_3Qa8K2LkdIwHu7ix\",\"object\":\"event\",\"type\":\"payment_intent.succeeded\",\"created\":1730900400}";

// 1. Compute RFC 2104 HMAC-SHA-256
const computedHex = crypto
  .createHmac("sha256", SECRET_KEY)
  .update(RAW_BODY, "utf8")
  .digest("hex");

// 2. Constant-Time Webhook Signature Verification
export function verifyWebhookSignature(receivedHeader) {
  const cleanHeader = receivedHeader.replace(/^sha256=/, "");
  const a = Buffer.from(computedHex, "hex");
  const b = Buffer.from(cleanHeader, "hex");
  if (a.length !== b.length) return false;
  return crypto.timingSafeEqual(a, b);
}

// Expected Hex: 
// Expected Base64: 
FILE: verify-hmac.mjs·LINES: 22·SIZE: 762 B
UTF-8 READY

Keyed-Hashing for Message Authentication (RFC 2104) & Webhook Security

Hash-based Message Authentication Code (HMAC), standardized in IETF RFC 2104 and FIPS PUB 198-1, combines a cryptographic hash function (SHA-256 or SHA-512) with a secret symmetric key using two nested passes XORed with inner (0x36) and outer (0x5c) padding constants. Unlike a naive SHA256(secret + message) construction, HMAC is immune to Merkle-Damgård length-extension attacks.

Defending Against Timing Side-Channel Attacks

Never compare an incoming webhook signature header against your computed HMAC using standard string equality (=== or ==). Standard equality operators short-circuit on the first mismatched byte, leaking nanosecond timing variations that allow attackers to forge valid signatures byte-by-byte. Always use constant-time comparison functions such as crypto.timingSafeEqual() in Node.js or hmac.compare_digest() in Python.

Preventing Replay Attacks with Timestamp Binding

Providers like Stripe and Slack prepend the Unix epoch timestamp to the raw HTTP request body before signing ("{timestamp}.{raw_body}"). Your webhook consumer must verify both the cryptographic MAC and assert that the timestamp falls within a strict tolerance window (typically 300 seconds) to prevent replay of captured requests.

Contextual Tool Cluster · Security, DNS & Cryptography

Continue Your Engineering Workflow

Explore All 37 Specifications