Cryptography / Concepts

Hash Functions & MACs

Cryptographic hash functions map arbitrary-length data streams into fixed-size digest values, providing integrity verification and avalanche diffusion. An unkeyed hash detects accidental corruption when the verifier compares it against a digest obtained through a trusted channel — the hash alone doesn't "prove" anything if an attacker can also tamper with that reference value. Hash-based Message Authentication Codes (HMAC) incorporate a shared secret key to provide integrity and shared-key authentication against active tampering; a valid tag identifies some holder of the shared key, not one uniquely attributable sender.

The Three Formal Security Properties

FIPS 180-4 (SHA-2) and FIPS 202 (SHA-3) specify the algorithms themselves, not a formal taxonomy of security properties — the three properties below are the established cryptographic security properties the broader literature expects of any secure hash function, and SHA-2/SHA-3 are designed and analyzed against them. A secure cryptographic hash function H(x) is expected to satisfy all three:

Comparison of preimage, second-preimage, and collision resistance in cryptographic hash functions.

The three hash properties describe different attacker search problems

Security Property Mathematical & Search Definition Failure Consequence Target Engineering Mitigation
Collision Resistance Infeasible to find any pair x ≠ x’ such that H(x) = H(x’). Attacker generates two distinct documents (one benign, one malicious) sharing an identical hash. Migrate from MD5 / SHA-1 to SHA-256 or SHA3-256.
Preimage Resistance (One-Way) Given y = H(x), infeasible to find any input x* — not necessarily the original x — such that H(x*) = y. Attacker finds some input that reproduces a stored password digest or token hash, sufficient to authenticate even if it isn’t the victim’s literal original secret. Deploy salted password hashes (Argon2id) or CSPRNG secret tokens.
Second-Preimage Resistance Given x, infeasible to find x’ ≠ x such that H(x) = H(x’). Attacker substitutes a malicious software binary for a target release while matching its published hash. Verify cryptographic signatures over releases rather than plain unkeyed hashes.

The Avalanche Effect

A secure cryptographic hash exhibits strong avalanche diffusion: modifying a single bit in the input alters approximately 50% of the output bits in an unpredictable pattern.

SHA-256 avalanche effect showing how changing a single character flips half the digest bits.

SHA-256 avalanche effect: altering one character produces an unrelated digest

Hash Algorithm Status Matrix

Algorithm Digest Size Current Security Status Target Applications
BLAKE3 Variable (256-bit default) NOT NIST-STANDARDIZED: Fast, modern Merkle tree hash design with extreme multi-core parallelism; independently specified (not FIPS 180-4 / FIPS 202) — NIST’s approved hash families remain SHA-2 and SHA-3. High-throughput file deduplication, supply chain hashing, tree proofs (where FIPS validation is not required).
KMAC128 / KMAC256 Variable (NIST SP 800-185) NIST-SPECIFIED KEYED HASH/PRF: Built on cSHAKE (a SHA-3 derived function), distinct from HMAC rather than a variant of it. Natively immune to length extension. High-assurance message authentication using a native sponge-based construction rather than HMAC’s nested construction — SP 800-185 doesn’t establish a universal performance advantage over HMAC, so benchmark on your target platform if throughput is the deciding factor.
MD5 128 bits CRITICALLY BROKEN: Practical collisions demonstrated (Flame malware, 2012). Legacy non-security checksums (Do not use for security).
SHA-1 160 bits DISALLOWED FOR SIGNATURE GENERATION: Practical collisions demonstrated (“SHAttered” attack, 2017). Per NIST SP 800-131A and the NIST Policy on Hash Functions, SHA-1 is disallowed for digital signature generation and collision-dependent applications; limited legacy uses remain permitted (such as verifying pre-existing signatures, HMAC, KDFs, and RNGs). Disallowed for new digital signature generation; legacy verification and non-collision uses only.
SHA-256 / SHA-512 (SHA-2) 256 / 512 bits APPROVED & STANDARD: Primary federal and commercial hash standard. Digital signatures, TLS 1.3, WebAuthn, block headers.
SHA3-256 / SHA3-512 (SHA-3) 256 / 512 bits APPROVED ALTERNATIVE: Based on Keccak sponge construction (FIPS 202). High-assurance alternative hedging against SHA-2 cryptanalysis.

Hash-based Message Authentication Codes (HMAC) & KMAC

Unkeyed hashes like SHA-256(message) do not prove origin authenticity; an attacker in the middle can alter both the message payload and the digest.

Standardized in FIPS 198-1, HMAC binds a secret key K to the message. Before use, K is normalized to the underlying hash function’s block size B: keys longer than B bytes are first hashed down to L bytes, and keys shorter than B bytes are zero-padded up to B bytes — call this normalized value K₀ (RFC 2104 §2). K₀, not the raw K, is what’s actually XORed with the inner and outer pads:

HMAC(K, M) = H((K₀ ⊕ opad) || H((K₀ ⊕ ipad) || M))

HMAC nested hash flow showing inner and outer key padding and a final tag that provides integrity and authentication by some holder of the shared key.

HMAC-SHA256 nested construction: inner and outer key padding produce a tag attributable to some holder of the shared key, not one unique party

HMAC’s guarantees are specific: it prevents length-extension attacks against the underlying Merkle–Damgård hash, and it authenticates that the tag was produced by a holder of key K. Because both communicating parties share the same key K, that guarantee is symmetric: any holder of K — sender or receiver — can produce a tag that verifies correctly, so HMAC cannot tell the two apart, cannot attribute a tag to one specific party over the other, and provides no evidence to a third party who doesn’t already trust both key holders (i.e., no non-repudiation). It does not protect the key itself — HMAC provides no defense if K is compromised through memory disclosure, a side-channel leak, weak key generation, or insecure storage; key protection is a separate concern handled by key management practices, not by the HMAC construction.

Why Naive H(Key || Message) Fails: Length-Extension Attacks

Naive concatenation H(key || message) using Merkle–Damgård hashes (MD5, SHA-1, SHA-256) is vulnerable to length-extension attacks. An adversary observing H(key || message) can compute a valid digest for key || message || padding || attacker_data without learning key.

HMAC’s nested construction prevents length-extension attacks by wrapping the inner hash output inside an outer hash layer protected by opad. Sponge-based constructions (SHA-3 / FIPS 202, KMAC / SP 800-185) are inherently immune to length extension by design; BLAKE3’s Merkle tree structure gives it the same property, though BLAKE3 is a separately-specified design rather than a NIST standard.

Client-Side Executable Hash Digest & HMAC-SHA256 Authentication Playground

Interactive Browser Playground

SHA-256 Digest & HMAC-SHA256 Authentication Playground

Compute unkeyed SHA-256 digests and keyed HMAC-SHA256 authentication tags directly in your browser. Test secret key verification and observe how invalid keys trigger authentication rejections (Zero server calls / Executed locally via Web Crypto API).

The prefilled key is an illustrative placeholder for this demo, not a production-strength secret — a real HMAC key should be a CSPRNG-generated random value of at least the hash's output length. Try changing the Receiver Verification Key to "wrong-secret-key" to verify invalid authentication rejection!
What I need to remember

A hash function's security rests on preimage, second-preimage, and collision resistance, but an unkeyed digest authenticates nothing on its own. HMAC's nested construction defends against Merkle–Damgård length-extension attacks; KMAC and BLAKE3 resist length extension by design instead.

Primary references