HMAC-SHA256 signing and verification for Tango webhook deliveries.
Tango signs each webhook delivery with an HTTP header of the form:
X-Tango-Signature: sha256=<lowercase hex HMAC-SHA256 of raw body>
The signature is computed over the raw request body bytes, keyed by the endpoint's secret. Verify against the bytes you received off the wire — re-serializing a parsed JSON document will produce a different signature because of whitespace, key ordering, and float formatting differences.
This crate has no transport dependency. It pulls in only hmac, sha2,
subtle, and hex, so a webhook receiver can verify deliveries without
linking the full SDK.
Quick start
use ;
let body = br#"{"event_type":"alerts.contract.match"}"#;
let secret = "topsecret";
// Server side (or in tests): produce a signature for `body`.
let header = generate;
assert!;
// Receiver side: verify the header you read off the request.
assert!;
assert!;
// The canonical header name to look up on the request:
assert_eq!;
Constant-time comparison
[verify] decodes both signatures to bytes and compares them with
[subtle::ConstantTimeEq]. The comparison does not short-circuit on the
first differing byte, which protects against timing-based signature
recovery attacks.
Why no axum/actix middleware?
Transport adapters live behind cargo features added in a later release.
This crate intentionally stays tiny — a verifier service depends on
tango-webhooks alone, not the full SDK.