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.