Skip to content
yutils
Example

Input (Message + Secret + Signature + Algorithm)

Message: GET /api/orders
Secret: your-256-bit-secret
Signature: f4a4d5e1c8d2b3a9...
Algorithm: SHA-256

Result

✓ Match — the message was signed with this secret

Note

Constant-time comparison — never returns early on the first differing byte, defeating timing attacks. Required pattern when verifying Stripe / GitHub / Slack webhook payloads.

Usage / FAQ

When to use

  • Verify X-Signature headers on Stripe / GitHub / Slack webhooks
  • Debug AWS Signature V4 — compare expected vs actual signature
  • Test API request signing locally
  • Verify a JWT HS256 token's signature portion directly
  • Round-trip workflow with HMAC Generator (pair)

FAQ

Q.Why is constant-time comparison important?
A.Plain `==` returns early on the first differing byte — measuring that timing lets an attacker guess the signature one character at a time. This tool XORs all bytes for a uniform comparison time.
Q.What if my signature is Base64?
A.Currently hex-only. Convert Base64 → bytes → hex first (Base64 tool → re-encode as hex). Direct Base64 support is under consideration.
Q.Is the secret sent anywhere?
A.No. `crypto.subtle.importKey` + `subtle.sign` run entirely in the browser — secret, message, and signature never leave your device.
Fun facts
  • Almost every webhook system — Stripe, GitHub, Slack, Twilio — uses HMAC signatures. The receiver compares the incoming payload + signature to verify tamper-resistance and sender authenticity. It's the de facto pattern for 'asymmetric trust via a shared secret.'

    Stripe — Webhook signatures
  • Constant-time comparison (`crypto.timingSafeEqual`) is the crux of HMAC verification. Naive `===` returns early on the first differing byte, leaking a timing side-channel measurable even across the network — Lawson's 2009 Keyczar vulnerability is the canonical case study.

    Wikipedia — Timing attack
  • Signature alone isn't enough to defeat replay attacks — you also need to sign a timestamp and reject requests older than ~5 minutes. Stripe's `t=` + `v1=` header format encodes timestamp + signature together, and is a clean reference for that pattern.

    Stripe — Verify webhook