Expand description
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 tango_webhooks::{generate, verify, SIGNATURE_HEADER};
let body = br#"{"event_type":"alerts.contract.match"}"#;
let secret = "topsecret";
// Server side (or in tests): produce a signature for `body`.
let header = generate(body, secret);
assert!(header.starts_with("sha256="));
// Receiver side: verify the header you read off the request.
assert!(verify(body, &header, secret));
assert!(!verify(body, &header, "wrong-secret"));
// The canonical header name to look up on the request:
assert_eq!(SIGNATURE_HEADER, "X-Tango-Signature");§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.
Structs§
- Parsed
Signature - The decomposed form of an
X-Tango-Signatureheader value.
Constants§
- SIGNATURE_
HEADER - The HTTP header name Tango uses to sign webhook deliveries.
- SIGNATURE_
PREFIX - The algorithm prefix on the header value (
"sha256=").