Webhook Signature Lab

Webhook Signature Lab

This local lab uses its own documented, provider-neutral profile: UTF-8 decimal Unix seconds, one ASCII dot, then the exact body bytes are authenticated with HMAC-SHA256. Its header is t=<seconds>,v1=<64 lowercase hex>. Text mode encodes the textarea as UTF-8; choose hex or a local file when CRLF or arbitrary bytes must be exact. Verification checks the MAC, ± time window and a small in-tab seen set. It is a learning/debugging profile, not a Stripe/GitHub-compatible header or a production webhook endpoint.

1. Raw body and temporary key

Body ≤ 64 KiB, key 1–128 bytes, time window 1–3600 seconds. Browser only; no provider API calls.

Textarea line endings may normalize to LF. For exact received CRLF or binary bytes, use hex or a file.

This is a teaching/debugging profile. A pasted real secret remains in this tab's memory until cleared or closed. Use a demo value when possible.

2. Create a signature

Own profile: signed bytes = ASCII Unix seconds + ASCII '.' + untouched body bytes. Header = t=<seconds>,v1=<64 lowercase SHA-256 HMAC hex>. This is not a provider header.

3. Verify a received header

After one valid check, repeating the same valid header and bytes reports replay only in this tab. Production replay defense needs a shared expiring record.

Load the demo or enter a body and temporary secret.

Comments & questions

Webhook Signature Lab

This local lab uses its own documented, provider-neutral profile: UTF-8 decimal Unix seconds, one ASCII dot, then the exact body bytes are authenticated with HMAC-SHA256. Its header is t=<seconds>,v1=<64 lowercase hex>. Text mode encodes the textarea as UTF-8; choose hex or a local file when CRLF or arbitrary bytes must be exact. Verification checks the MAC, ± time window and a small in-tab seen set. It is a learning/debugging profile, not a Stripe/GitHub-compatible header or a production webhook endpoint.

Key features

  • Sign exact text, hex or local file bytes with Web Crypto HMAC-SHA256
  • Strict timestamped header and signing-input byte count/preview
  • Verify a 32-byte digest using a fixed-length byte loop without content-dependent early exit
  • Distinguish tampering, expired timestamp, excessive future clock and repeated valid header in this tab
  • Keep the secret in page memory only, with no local storage, form submission or API call

How to use

  1. Load the demo or choose text, hex or a local body file, then enter a temporary UTF-8 or hex key.
  2. Leave the signing timestamp blank for current Unix seconds or enter a fixed test value; click Sign.
  3. Copy or inspect the resulting t=...,v1=... header and exact timestamp-dot-body input rule.
  4. Verify with the same raw bytes and key; optionally set test clock and tolerance.
  5. Edit one body byte, advance the test clock or verify twice to inspect mismatch, expiry and in-tab replay.

Use cases

  • Reproduce a webhook signature mismatch caused by CRLF versus LF
  • Test the 300-second tolerance boundary against a fixed clock
  • Demonstrate why a valid MAC alone does not stop in-window replay
  • Inspect the exact byte prefix a receiver should authenticate

Frequently asked questions

Does this match a particular webhook provider?

No. This tool defines its own strict t=<Unix seconds>,v1=<lowercase hex> profile and authenticates ASCII timestamp + '.' + raw body bytes. Real providers may use different headers, encodings and replay rules. Follow that provider's official specification in production.

Why can pasted JSON verify differently from the received request?

Signatures cover bytes, not parsed JSON meaning. Spaces, key order, encoding and CRLF/LF matter. Browser textareas normalize line endings; upload the original binary or use hex mode to reproduce received bytes exactly.

Is a timestamp enough to stop replay?

No. The ± window rejects old/far-future deliveries, but a valid message can be resent inside it. This page remembers accepted headers in one tab, up to 256 entries; closing or clearing the tab loses them. A real receiver needs a shared durable event-ID or signature cache with expiry.

Is the comparison truly constant time?

The digest loop always checks 32 byte positions without stopping at the first differing byte. JavaScript engines and browsers do not guarantee physical constant-time execution; do not treat this demo as a side-channel certification.

Can I sign an empty body?

Yes. The signed input is still the timestamp and dot, followed by zero body bytes. File mode requires a selected file; text and hex modes may be empty.

Is my secret uploaded or saved?

No. The tool has no endpoint for body or key data and does not use localStorage. The secret remains in this tab's React state until cleared or closed; browsers and extensions remain outside the tool's control.

Privacy

Body bytes, header and secret are processed in browser memory. No signing input or secret is sent to the app server or stored automatically. Clear the lab after using a real credential.

References

Related Tools

Hash GeneratorJWT DecoderHex File EditorWasm Module InspectorHreflang Matrix CheckerAST Query PlaygroundContainer Build GraphDependency Graph ExplorerSemver Range LabCron Schedule AuditorPatch Review WorkbenchSource Map ExplorerLocalization Catalog AuditorStructured Data ReviewerHTTP Archive AnalyzerProtobuf Schema WorkbenchGraphQL Schema LabAvro Schema EvolutionLocal SQL WorkbenchSchema Form BuilderMesh Repair WorkbenchPipe Network LabRobot Arm Kinematics LabThermal Network LabBeam Response LabGear Train DesignerTolerance Stackup LabSensor Calibration FitPCB Stackup PlannerDigital Filter DesignerNetwork Reachability MapSun Shadow MapGPS Error SimulatorDigital Logic SimulatorAnalog Circuit LabMechanism Linkage LabAnalysis Mesh GeneratorOpenAPI Contract InspectorDatabase Migration PlannerDimensional Equation CheckerTruss Force LabBoolean Minimization LabControl Response LabQueueing Simulation LabGeofence Event SimulatorCoordinate Reference LabSurvey Traverse LabRaster Classification LabChoropleth Design LabMap Print ComposerRaster Reprojection LabElevation Contour MakerTerrain Viewshed LabWatershed DelineatorMap Tile PackagerText File Encoding WorkbenchFilesystem Portability AuditorSBOM License ExplorerFile Signature Auditornpm Lockfile Conflict ResolverSource Secret AuditorOffline Web Package BuilderCertificate Chain InspectorTorrent Metainfo InspectorChunked File PackagerEncrypted File VaultDuplicate File FinderArchive WorkbenchDesign Token ManagerSpacing Token DesignerResponsive Type SystemPackaging Dieline DesignerSVG Icon Sprite PackerFlex Layout PlaygroundCSS Grid PlaygroundRegex Equivalence LabMarkdown Repository AuditorLog Template MinerResponsive Layout AuditorEmail Template PreviewInternal Link GraphState Machine TesterPetri Net SimulatorGit History VisualizerCurl Request WorkbenchBinary Protocol DesignerBinary Patch WorkbenchFile Signature WorkbenchAPI Mock SandboxSchema Column MapperEvent Log SessionizerER Diagram DesignerTime Series Gap AuditorStratified Data SplitterData Lineage DesignerDecision Tree LabData Anonymization WorkbenchData Expectation RunnerJSON Schema ValidatorBasket Pattern AnalyzerRobots Policy TesterSEO HTML AuditorAccessibility Structure AuditorSyndication Feed WorkbenchIndexNow Payload BuilderCrawl Log AnalyzerCSP Policy WorkbenchSearch Performance AnalyzerCSV Formula Risk AuditorCORS Response SimulatorCache Header LabCookie Policy InspectorWeb Vitals Trace LabSitemap Health AuditorBatch File RenamerFile Manifest VerifierFolder Space MapFolder Difference ReviewerRoute Order OptimizerGeoJSON Map EditorPolygon Overlay LabCartographic Label PlacerSpatial Table JoinGeoJSON Topology AuditorGPX Track AnalyzerTrack Privacy RedactorCSV Table JoinCSV Pivot WorkbenchScientific Data ProfilerTabular Cleaning WorkbenchRecord ReconciliationData Dictionary BuilderCanonical Graph AuditorRedirect Plan TesterHTTP response and ping reference testBrowser and System InformationJSON ↔ YAML ConverterXML ↔ JSON ConverterHTML FormatterJavaScript MinifierMock Data Generator.gitignore GeneratorLicense GeneratorUser-Agent ParserPassword Strength CheckerCode to ImageXML FormatterHTTP Status Code LookupMIME Type LookupJS & SQL String EscapeCSS Box Shadow GeneratorCSS Gradient GeneratorIndent ConverterNumber Base ConverterUnicode Escape ConverterUnicode InspectorJSON Structure DiffMarkdown Table GeneratorBase64 EncoderJSON FormatterURL EncoderSQL FormatterCron Expression GeneratorRegex TesterUUID GeneratorTimestamp ConverterHTML Entity ConverterMarkdown PreviewCSS MinifierMeta Tag GeneratorJSON ↔ CSVCase ConverterImage to Base64
Explore all Dev Tools tools →Image/Media →Text/Convert →Life/Fun →