X-Hub-Signature-256 or Stripe signature) to verify authenticity:
A Keyed-Hash Message Authentication Code (HMAC) is a cryptographic construction defined in RFC 2104 and NIST FIPS 198-1. It provides a mechanism for verifying both the data integrity and the authenticity of a message using a shared secret key and an underlying cryptographic hash function (such as SHA-256 or SHA-512).
A common mistake made by junior developers is attempting to build an authentication code by hashing the key prepended to the message: $\text{MAC} = H(K \parallel M)$.
For hash functions based on the Merkle-Damgård construction (including MD5, SHA-1, SHA-256, and SHA-512), this naive approach is vulnerable to a catastrophic attack known as the Length Extension Attack:
To mathematically defeat length extension attacks, RFC 2104 defines a two-pass nested hashing algorithm:
$$\text{HMAC}(K, m) = H\Big((K' \oplus \text{opad}) \parallel H\big((K' \oplus \text{ipad}) \parallel m\big)\Big)$$
Where:
0x36 (binary 00110110).0x5C (binary 01011100).When verifying incoming webhook signatures (such as Stripe, GitHub, or Shopify signatures) in your backend application, never use standard string equality (e.g. signature === calculated or signature == expected):
Standard string comparison operators terminate as soon as the first non-matching byte is encountered. An attacker measuring execution latency with microsecond accuracy can determine which characters matched, allowing them to brute-force a valid HMAC byte-by-byte.
Always use a constant-time comparison primitive:
crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected))hmac.compare_digest(sig, expected)hmac.Equal([]byte(sig), []byte(expected))hash_equals($expected, $sig)X-Hub-Signature-256: sha256=HEX...), while Base64URL is standard in JSON Web Signatures (JWT / JWS).crypto.subtle.sign). No keys or payloads ever leave your device.