obfus.link

HMAC Generator computes and verifies HMAC signatures with SHA-256, SHA-384, and SHA-512. The Webhook Signature Verifier differentiator applies provider-specific signing schemes for Stripe, GitHub, Twilio, Shopify, and Slack — each one prepends timestamps, formats headers, and uses the correct algorithm (Twilio uses SHA-1). Verify mode uses timing-safe equality comparison.

Tier 2generators✓ TDD Verified

HMAC Generator

Generate and verify HMAC signatures with Stripe, GitHub, Twilio, Shopify, Slack templates

Never logged · never returned in output · hash metadata excludes key

How to use

  1. Pick modeGenerate HMAC to compute a signature, or Verify Signature to check an incoming webhook against a signing secret.
  2. Choose webhook templateCustom for raw HMAC, or Stripe / GitHub / Twilio / Shopify / Slack to apply that provider's signing scheme.
  3. Set algorithmSHA-256, SHA-384, or SHA-512. The Twilio template forces SHA-1.
  4. Enter the signing keyFor webhooks this is the signing secret (Stripe whsec_..., GitHub webhook secret, etc.). The key is never logged or returned in the output.
  5. Paste the messageThe raw request body. For Twilio specifically: URL + sorted POST params concatenated.
  6. Verify only — paste the signaturePaste the full provider header value (e.g. "t=...,v1=hex" for Stripe, "sha256=hex" for GitHub) — the tool extracts the raw signature automatically.
  7. RunClick Generate/Verify or press Ctrl+Enter. Output shows hex + base64 + (in verify mode) a VERIFIED or INVALID banner.
Read technical article

MCP / API

Call hmac_gen directly from any MCP-compatible agent:

// MCP TypeScript SDK
const result = await client.callTool({
  name: "hmac_gen",
  arguments: {
    "mode": "generate",
    "message": "...",
    "key": "...",
    "algorithm": "SHA-256"
  }
});

// curl
curl -X POST https://obfus.link/mcp \
  -H "Authorization: Bearer <SPT>" \
  -H "Content-Type: application/json" \
  -d '{"method":"tools/call","params":{"name":"hmac_gen","arguments":{"mode":"generate","message":"...","key":"...","algorithm":"SHA-256"}}}'

Related tools

Hash Generator
Generate MD5, SHA-256, SHA-512, BLAKE3 and more in one call
JWT Hardener
Audit and harden JWT tokens with security scoring and diff output
Header Inspector
OWASP-graded HTTP security headers scorecard with CORS issue detection

FAQ

Why does Twilio override the algorithm to SHA-1?

Twilio mandates HMAC-SHA1 in its signature spec — every Twilio request validates against an SHA-1 signature, not SHA-256. The tool overrides the algorithm field when webhookTemplate is twilio so you do not have to remember the exception. The output hex is 40 characters (SHA-1 length), not 64.

What does "timing-safe equality" mean?

Standard string comparison short-circuits on the first mismatched byte, leaking information about how many leading bytes are correct via the comparison time. Timing-safe equality (Node's crypto.timingSafeEqual) compares every byte regardless of mismatches, so an attacker cannot use response time to incrementally guess the signature.

My Stripe webhook verification is returning false. What do I check?

Three things: (1) Use the RAW request body — Express's express.json() middleware reparses and re-serializes, breaking the signature. Capture the body with a raw parser. (2) The timestamp must match the t=... value in the Stripe-Signature header, not the current time. (3) Use the correct webhook signing secret (whsec_...), not the API key. The tool's webhookDetails.signedPayload shows the exact string that was signed — compare it to what Stripe would have signed.

Can I use this for non-webhook HMAC?

Yes. Leave webhookTemplate as "custom" and the tool computes a plain HMAC over your message with your key. Useful for integrity checks, cache keys, request signing in your own RPC protocols, or generating short-lived authentication tokens.

Can I use this tool via the MCP API?

Yes. The tool is registered on the obfus.link MCP server at https://obfus.link/mcp. Call it from any MCP-compatible agent with a Shared Payment Token. The MCP tool name matches the snake_case slug shown in the integration snippet.