Hashing, Message Digests, and Message Authentication Codes
Hashes compress arbitrary input into a fixed-length digest. This domain tests the three security properties, why collision resistance is the hardest, how HMAC fixes the naive keyed hash, and how passwords should be stored.
Properties and algorithms
- Preimage resistance: given h, finding any m with H(m) = h is infeasible.
- Second-preimage resistance: given m, finding a different m' with H(m') = H(m) is infeasible.
- Collision resistance: finding any pair with equal digests is infeasible. The birthday bound puts that cost near 2^(n/2) for an n-bit digest.
- MD5 and SHA-1 are broken for collision resistance, with practical chosen-prefix attacks, and must not be used where collisions matter, including certificates.
- SHA-2 (SHA-256/384/512) and SHA-3 (Keccak sponge) remain sound.
- A hash gives integrity only if the digest itself is protected; otherwise the attacker simply recomputes it.
MACs
- HMAC hashes the key in a nested construction, H(K XOR opad concatenated with H(K XOR ipad concatenated with m)), and avoids the length-extension weakness of H(secret concatenated with message).
- MACs give integrity and authenticity between parties sharing a key, but not non-repudiation, since either party could have produced the tag.
- Password storage needs a deliberately slow, salted KDF: Argon2, scrypt, bcrypt or PBKDF2. A salt defeats precomputed rainbow tables and hides identical passwords; it is not secret.
Worked example
A system truncates a 64-bit hash for message integrity. Collision resistance is about 2^32, roughly 4.3 billion operations, which is achievable on ordinary hardware, so an attacker can substitute a forged message with the same digest. Moving to SHA-256 gives 2^128 birthday work. Even then, if the digest travels beside the message without a key, the attacker recomputes it, so a MAC is required.
Traps
A checksum detects transmission errors, not attacks. CRC32 is not cryptographic. Encryption is not a substitute for hashing when the stored value must stay unrecoverable. 'Salted hash' is not the same as a slow KDF.