hooksig / Cloudflare
HMAC-SHA256 · hex · timestamped
Cloudflare
Stream and Images webhooks, signed almost exactly like Stripe but with a time=,sig1= header.
Try it — live, in your browser
Request — edit anything
Verify this in code
import { verify } from "hooksig";
const result = await verify("cloudflare", {
payload: rawBody, // the RAW body, not parsed JSON
headers: request.headers,
secret: env.WEBHOOK_SECRET,
});
if (!result.verified) {
return new Response(result.reason, { status: 400 });
}no match — signature invalid
Signed string
HMAC-SHA256( secret, signed string ) = expected
Expected vs provided
expected
provided
How it's built
The scheme
- Header
Webhook-Signature - AlgorithmHMAC-SHA256
- Encodinghex
- Timestampyes, so it has replay protection
- SignsHMAC-SHA256 over `{time}.{body}`, hex, in a `time=,sig1=` header. Keyed by the webhook secret.
Gotchas
- The header is `time=...,sig1=...`. Build the signed string as `{time}.{body}` before hashing.
- Sign the raw body, not a re-serialized copy.
- Reject if the time is outside your tolerance to stop replays.
- The header name Webhook-Signature collides with Standard Webhooks; pick the right provider for your source.