Skip to content
hashkey.bond

Archivehashing

Keyed vs Unkeyed Hashes

SHA-256 and HMAC both output 32 bytes, and using the wrong one in the wrong place is a real vulnerability class.

Published
Reading time
1 min read

An unkeyed hash answers "did these bytes change?" A keyed hash answers "did someone without the key produce these bytes?" They are not interchangeable.

The difference

SHA-256(m) is computable by anyone. If you use it to authenticate a message — say mac = sha256(secret + message) — you have built a length-extension oracle. Given sha256(secret + m) and the length of the secret, an attacker can compute sha256(secret + m + padding + m') without knowing the secret. This is not theoretical; it broke early Flickr and countless API signatures.

HMAC avoids this by hashing twice with derived pads:

HMAC(K, m) = H((K' ^ opad) || H((K' ^ ipad) || m))

The inner hash never exposes a resumable state to the attacker.

Choosing

  • Integrity of public data (checksums, content addressing): unkeyed hash.
  • Authentication, session tokens, webhook signatures: HMAC or, better, a modern MAC like KMAC.
  • Deriving keys from a secret: not a hash at all — use HKDF.

Takeaway: if a secret is involved in the hash, use a construction designed for secrets. H(secret || data) is never one of them.