Reference
Message Integrity (Digest) v.2 HMAC
Message Integrity (Digest) v.2 - HMAC
v2 is the hardened signing scheme that the v1 page itself calls for in its Hardening (recommended) note: HMAC-SHA256 over the raw body, with an explicit timestamp and nonce. It coexists with v1;
Wire format
Headers
X-Sig-Version: 2— opaque version tag. Future signing changes bump this; verifiers can switch behaviour by version.X-Timestamp: <unix seconds>— when the request was signed. Server rejects requests outside±60 sfrom its own clock.X-Nonce: <32 hex chars>—bin2hex(random_bytes(16)), a unique per-request token. Server stores it for≥ 180 s(= 2 × skew) and rejects any repeat within that window.X-Signature: <hex>—hex( HMAC-SHA256(secret, canonical) ). Lowercase hex.
The body itself is unchanged from v1 with one exception: no "hash" field. In v2-dual transition mode the body keeps the legacy "hash" field so the partner can verify either signature; the v2 HMAC signs over those exact bytes (including the legacy field).
Canonical string
Concretely for the example above:
Five lines, \n-separated. BODY is the raw bytes the partner received (php://input), not a re-encoding. SHA256_hex(BODY) is the lowercase hex SHA-256 of those bytes.
Reference (PHP, signer)
Reference (PHP, verifier — partner side)
Critical: verify against file_get_contents('php://input') — the exact bytes the wire delivered. Never decode + re-encode the body before hashing; PHP's json_encode defaults differ between major versions (float precision, unicode escape flags, key order under sorting helpers) and any drift breaks signatures silently.
Replay-protection parameters
Parameter | Value | Notes |
|---|---|---|
Timestamp skew tolerance |
| Server rejects |
Nonce store TTL |
| Must be |
Nonce bit-width |
|
|
Nonce store | Redis (recommended) or equivalent | Per-partner; isolated per-shard if the partner is sharded. |