Cryptographic Hash Functions

Imagine downloading a 4-gigabyte operating system image. You need to verify, in microseconds, that no bit was corrupted or tampered with. Recomputing some elaborate check over the whole file is fine. But comparing two 4-gigabyte files directly is not workable. Trusting a network intermediary to vouch for their equality is not workable either. What we want is a short, fixed-length "fingerprint" summarizing arbitrarily large data. Any change to the data, however tiny, must change the fingerprint unpredictably. That fingerprint is a cryptographic hash function output. The guarantee we need is much stronger than the ordinary notion of a hash table hash. Cryptographic hash functions are the workhorse primitive quietly underneath almost every security mechanism in modern computing. They authenticate software updates and anchor digital signatures. They chain together the blocks of a blockchain and protect stored passwords. They detect tampering in Message Authentication Codes and power commitment schemes used in secure multiparty protocols. A single well-designed hash function, such as SHA-256, is reused across thousands of unrelated applications. This is because the same three security properties—preimage resistance, second-preimage resistance, and collision resistance—turn out to be exactly what each application needs. This holds true even though the applications look nothing alike. This article builds up cryptographic hash functions from first principles. We define what a hash function is. We precisely state the three resistance properties that separate a cryptographic hash from an ordinary checksum. We walk through the internal mechanics (compression functions and the Merkle–Damgård construction). These mechanics let a function accept inputs of any length while behaving like a fixed-size scrambler. We connect these properties to the confidentiality–integrity–authenticity goals established when discussing the Goals of Cryptography: Confidentiality, Integrity, Authenticity framework. This connection matters because hash functions are primarily an integrity and authenticity tool, not a confidentiality tool. By the end, you will be able to state each security property as a precise game between an adversary and a challenger. You will be able to explain why a good hash function must behave like a "random oracle" for security arguments to go through. You will also see exactly where naive intuitions (such as "just make the output long") break down. This sets up two topics that build directly on what is developed here: a deeper treatment of Collision Resistance as a standalone security notion, and The Birthday Attack, the generic attack that determines how long a hash output must be.

Key takeaways
  • A cryptographic hash function maps arbitrary-length input to a fixed-length output ("digest") in a way that behaves unpredictably and deterministically.
  • Three security properties matter: preimage resistance, second-preimage resistance, and collision resistance, each a different adversarial game.
  • Collision resistance is the strongest property; it implies second-preimage resistance but not the reverse in general.
  • Real hash functions (SHA-256, SHA-3) are built by iterating a fixed-size compression function over blocks of the message (Merkle–Damgård or sponge constructions).
  • Generic attacks bound security regardless of design: brute force costs about 2n2^n work for an nn-bit preimage, but only about 2n/22^{n/2} for a collision, due to the birthday phenomenon.
  • Hash functions are not encryption; they provide integrity and authenticity building blocks, used in signatures, password storage, MACs, and Merkle trees.
The core insight

A cryptographic hash function condenses any input into a short, fixed-size fingerprint that is easy to compute but computationally infeasible to invert, to re-target, or to collide.

The idea

A hash function is a deterministic function H:{0,1}∗→{0,1}nH : \{0,1\}^* \to \{0,1\}^n that maps a bit string of arbitrary length to a fixed-length output of nn bits, called the digest or hash value. Determinism means the same input always produces the same output; this is what makes hashes useful for verification — two parties who compute H(m)H(m) independently on the same mm will always agree. Efficiency means HH must be computable in time roughly linear in the length of the input, since it will be run on every message, file, or transaction that flows through a system. What separates a cryptographic hash function from an ordinary hash function (the kind used in hash tables) is that it must resist an adversary who is actively trying to break specific security properties, not merely trying to avoid accidental collisions for well-behaved inputs. Three properties are standard:

  • Preimage resistance (a "one-way" property): given a digest yy, it should be infeasible to find any mm with H(m)=yH(m) = y.
  • Second-preimage resistance: given a specific message m1m_1, it should be infeasible to find a different message m2≠m1m_2 \neq m_1 with H(m1)=H(m2)H(m_1) = H(m_2).
  • Collision resistance: it should be infeasible to find any pair m1≠m2m_1 \neq m_2 with H(m1)=H(m2)H(m_1) = H(m_2), without either message being fixed in advance.

These are phrased as games against a computationally bounded adversary, and "infeasible" means no efficient algorithm succeeds with more than negligible probability, in the spirit of the Goals of Cryptography: Confidentiality, Integrity, Authenticity framing where security is defined relative to a threat model rather than absolute impossibility. Note collisions always exist: since the input space is infinite (or at least far larger than 2n2^n) and the output space has only 2n2^n elements, HH cannot be injective, and by the pigeonhole principle many inputs must map to the same output. Collision resistance never claims collisions don't exist — only that they are hard to find.

How it works

A modern hash function is built in two layers: a fixed-size compression function ff, and an iteration mode that extends ff to handle inputs of arbitrary length. The most classical iteration mode is Merkle–Damgård, used (with variations) in MD5, SHA-1, and SHA-2. The compression function f:{0,1}n×{0,1}b→{0,1}nf : \{0,1\}^n \times \{0,1\}^b \to \{0,1\}^n takes a fixed-size chaining value of nn bits and a fixed-size message block of bb bits, and produces a new nn-bit chaining value. The full hash function processes the message one block at a time, feeding the output chaining value of one step in as the input chaining value of the next — this is why it is called an iterated construction. Before iteration begins, the message must be padded so its length is an exact multiple of the block size bb. Padding schemes append a `1` bit, then enough `0` bits, then (crucially) the original message length encoded in binary — this is called Merkle–Damgård strengthening and is essential to the security proof described below. ```text PSEUDOCODE: Generic Merkle–Damgård hash construction function PAD(M): L <- bit-length of M M' <- M || 1 // append a single 1 bit while (bit-length of M' + 64) mod b != 0: M' <- M' || 0 // pad with zero bits M' <- M' || encode_64bit(L) // append original length (strengthening) return M' // length of M' is now a multiple of b function HASH(M): M' <- PAD(M) split M' into blocks m_1, m_2, ..., m_k // each of length b bits h_0 <- IV // fixed public initialization vector for i in 1..k: h_i <- f(h_{i-1}, m_i) // apply compression function return h_k // final chaining value is the digest ``` Each call to `f` is a small, carefully engineered function (in SHA-256, roughly 64 rounds of bitwise rotations, XORs, and modular additions on 32-bit words). Its design goal is to behave, for security-analysis purposes, indistinguishably from a random function on its domain — this idealization is called the random oracle model, and while no real function is truly random, treating ff as if it were lets us reason cleanly about the three resistance properties and is borne out empirically by extensive cryptanalysis of the standardized designs. Newer designs such as SHA-3 use a different iteration mode called a sponge construction, which absorbs message blocks into a large internal state via a fixed permutation and then squeezes out output bits, avoiding some structural weaknesses of Merkle–Damgård (notably length-extension attacks) while offering the same three security properties.

Figure
Merkle–Damgård iterated hashing: message blocks chained through a compression function
message M, padded into blocks m₁ m₂ m₃ m₁ m₂ m₃ IV=h₀ f f h₁ f h₂ digest h₃

Complexity & correctness

Time complexity. Computing H(M)H(M) for a message of length ∣M∣=L|M| = L bits requires padding (an O(L)O(L) operation) and k=⌈L/b⌉k = \lceil L / b \rceil invocations of the compression function ff, each of which does O(1)O(1) work (a fixed number of rounds on fixed-size words). Total time is therefore O(L)O(L) — linear in the input size, which is essential since hash functions must scale to gigabyte-sized files and be usable inside tight loops such as per-packet integrity checks.

Space complexity. Only O(n+b)O(n + b) space is needed at any moment: the current chaining value (nn bits) and the current message block (bb bits). The construction is inherently streaming: you never need to hold the whole message in memory, which is why hashing a terabyte file uses the same working memory as hashing a byte.

Correctness of the construction (the Merkle–Damgård theorem). The engineering claim underlying this design is: if the compression function ff is collision-resistant, then the full iterated hash HH is collision-resistant. The proof is a clean reduction, worth walking through because it demonstrates the standard technique used throughout cryptographic security proofs. Suppose an adversary finds a collision M1≠M2M_1 \neq M_2 with H(M1)=H(M2)H(M_1) = H(M_2). After padding (which encodes the true bit-length at the end of each padded message), consider the two padded messages and their block sequences m1,…,mkm_1, \dots, m_k and m1′,…,mk′m_1', \dots, m_k'. Because the final blocks encode different lengths whenever ∣M1∣≠∣M2∣|M_1| \neq |M_2|, and encode identical content whenever ∣M1∣=∣M2∣|M_1| = |M_2| but M1≠M2M_1 \neq M_2, one can always walk backward from the final compression call:

  • If the final chaining inputs to ff differ (i.e., (hk−1,mk)≠(hk−1′,mk′)(h_{k-1}, m_k) \neq (h_{k-1}', m_k')) but ff outputs are equal, we have exhibited a collision in ff itself — contradicting ff's assumed collision resistance.
  • If the final chaining inputs are equal, then in particular hk−1=hk−1′h_{k-1} = h_{k-1}', so we recurse one block earlier and repeat the argument.
  • This process cannot continue all the way back to identical initial states, because the two original messages were assumed distinct (they must differ in content or length at some point), so at some step a genuine collision in ff is forced out.

Hence any collision-finder for HH can be converted, with only linear overhead, into a collision-finder for ff. This is a reduction: security of the simple, fixed-size, heavily analyzed primitive ff transfers to security of the complex, variable-input primitive HH. It is why cryptanalysts focus enormous effort on breaking compression functions and permutations directly, rather than the full iterated hash.

Honesty about limits. This proof only protects collision resistance — it does not automatically give preimage resistance against all attacks (Merkle–Damgård is famously vulnerable to length-extension attacks, where knowing H(M)H(M) lets an attacker compute H(M∥pad∥X)H(M \| \text{pad} \| X) for a chosen suffix XX without knowing MM, because the digest is the internal chaining state). This is precisely why protocols such as HMAC exist rather than naively hashing a secret key concatenated with a message, and why sponge-based designs like SHA-3 were introduced.

Generic bounds (independent of any specific design) come from brute-force adversary strategies and set the honest floor on security, foreshadowing The Birthday Attack in detail:

PropertyGeneric attack cost against nn-bit digest
PreimageΘ(2n)\Theta(2^n) trials expected (try random inputs until output matches)
Second-preimageΘ(2n)\Theta(2^n) trials expected (same as above, one input fixed)
CollisionΘ(2n/2)\Theta(2^{n/2}) trials expected (birthday phenomenon: collisions among qq random samples become likely once q≈2nq \approx \sqrt{2^n})

The collision bound follows from the birthday paradox: with qq hash evaluations landing in a space of size 2n2^n, the expected number of colliding pairs is roughly (q2)/2n\binom{q}{2}/2^n, which exceeds 11 once q≳2n/2q \gtrsim 2^{n/2}. This is why digest sizes for collision-resistant use (e.g., SHA-256's 256 bits, giving 21282^{128} collision-resistance) must be roughly double the size needed for preimage resistance alone — a subtlety many system designs get wrong.

Worked example

Real cryptographic hash outputs are dense hexadecimal strings with no exploitable internal structure — that opacity is the point — so to see the mechanics we trace a deliberately tiny toy hash function, small enough to compute by hand, while being explicit that it is for pedagogy only and offers no real security.

Toy setup. Let the digest size be n=8n = 8 bits. Define a toy compression function over 8-bit chaining values and 8-bit message blocks:

f(h,m)=ROL3(h⊕m)⊞m(mod256)f(h, m) = \text{ROL}_3(h \oplus m) \boxplus m \pmod{256}

where ROL3\text{ROL}_3 rotates the byte left by 3 bits and ⊞\boxplus is addition mod 256. Let IV=0x5AIV = \texttt{0x5A}. Suppose the message, after padding, splits into three one-byte blocks: m1=0x11m_1 = \texttt{0x11}, m2=0x22m_2 = \texttt{0x22}, m3=0x33m_3 = \texttt{0x33}.

StepInput hhBlock mmh⊕mh \oplus mafter ROL₃+ m(mod256)+\, m \pmod{256}New hh
1`0x5A` = `01011010``0x11` = `00010001``01001011``01011010` = `0x5A``0x5A + 0x11 = 0x6B``0x6B`
2`0x6B` = `01101011``0x22` = `00100010``01001001``01001010` = `0x4A``0x4A + 0x22 = 0x6C``0x6C`
3`0x6C` = `01101100``0x33` = `00110011``01011111``11111010` = `0xFA``0xFA + 0x33 = 0x2D`*`0x2D`

(*mod 256 wraparound: `0xFA + 0x33 = 0x12D`, truncate to 8 bits → `0x2D`.) So H(M)=0x2DH(M) = \texttt{0x2D} for this specific 3-block message. Now watch what happens with second-preimage resistance in this toy: an attacker who wants a different message with the same digest must search over the 28=2562^8 = 256 possible final chaining states and block choices at the last step to make f(h2,m3′)=0x2Df(h_2, m_3') = \texttt{0x2D} with h2=0x6Ch_2 = \texttt{0x6C} fixed — an 88-bit search space, i.e. about 282^8 trials in the worst case, matching the generic bound above (here trivially small because n=8n=8; real hash functions use n=256n = 256 or more precisely to make this search infeasible, at 22562^{256} trials). This toy also lets us see collision resistance breaking down at small scale: because ff's output space is only 256 values, if we evaluate ff on roughly 256=16\sqrt{256} = 16 random (h,m)(h,m) pairs, the birthday bound predicts a collision becomes likely — a concrete, hand-verifiable preview of why real digests need n≥256n \geq 256 for 128-bit collision security.

Common pitfalls & traps

PitfallWhy it's wrong
Confusing a checksum (CRC32) with a cryptographic hashCRCs are linear and trivially invertible by an adversary; they detect accidental corruption, not intentional tampering
Assuming preimage resistance implies collision resistanceThe implication runs the other way in general; collision resistance is the strictly stronger, harder-to-achieve property
Hashing `secret_keymessage` directly for a MAC with a Merkle–Damgård hashVulnerable to length-extension attacks; use HMAC or a sponge-based hash instead
Believing digest length alone determines security against all attacksAn nn-bit digest gives only 2n/22^{n/2} collision security, not 2n2^n, due to the birthday bound
Treating "no known collisions yet" as a permanent guaranteeMD5 and SHA-1 were once considered secure; both have since been practically broken (MD5 fully, SHA-1 via the SHAttered collision)
Storing raw password hashes without saltingEnables precomputed rainbow-table lookups across many accounts at once

Pioneers & history

Origins · 1 minRalph C. Merkle and how this was discovered
RC
Ralph C. Merkle
born 1952 · American computer scientist, co-inventor of public-key cryptography concepts and the iterated hash construction bearing his name

Merkle, working independently alongside Diffie and Hellman on foundational public-key ideas, proposed the tree-structured and iterated hashing techniques that underlie both Merkle trees (used in blockchains and version control) and the Merkle–Damgård construction analyzed above.

History
1979
— Ralph Merkle's dissertation work introduces hash-tree structures and ideas toward secure iterated hashing.
1989
— Ivan Damgård independently formalizes the iterated compression-function construction and proves the collision-resistance-preserving theorem.
1993
— NIST publishes SHA-0, soon withdrawn and replaced by the strengthened SHA-1 in 1995.
2004–2005
— Wang, Yin, and Yu publish practical collision attacks on MD5 and theoretical attacks on SHA-1.
2012
— NIST selects Keccak as SHA-3, based on the sponge construction, diversifying away from Merkle–Damgård.
2017
— Google and CWI Amsterdam announce the "SHAttered" attack, the first practical SHA-1 collision.

Where this matters

Cryptographic hash functions sit underneath nearly every layer of the security stack. TLS certificates are signed over a hash of their contents, not the raw bytes, because digital signature algorithms operate on fixed-size inputs — this is why collision resistance is critical for signature security: a collision would let an attacker get one message signed and silently substitute another. Git and other version-control systems identify every commit and file blob by its SHA-1 (moving to SHA-256) hash, giving a content-addressed storage system where identical content is automatically deduplicated. Blockchains such as Bitcoin chain blocks together via hash pointers, so altering any historical block would cascade and change every subsequent block's hash, making tampering detectable. Password storage systems run passwords through slow, memory-hard hash functions (bcrypt, Argon2 — deliberately not fast, general-purpose hashes like SHA-256) precisely to raise the cost of brute-force preimage search. Software distribution pipelines publish hash digests of installers so users can verify integrity after download. All of these depend, in different combinations, on the three properties developed here, and all of them are re-examined more rigorously when studying Collision Resistance as its own topic and the concrete numeric consequences captured by The Birthday Attack.

Ask the tutor: How exactly does the birthday bound argument generalize from finding collisions to breaking HMAC or digital signature schemes in practice?

Is a cryptographic hash function the same thing as encryption?

No. Encryption is reversible given the correct key, restoring the original plaintext, and it targets confidentiality. A cryptographic hash function is a one-way, keyless transformation with no decryption operation at all — its outputs are meant to be public and its purpose is integrity and authenticity, not secrecy. You cannot "decrypt" a hash digest back into the original message even in principle, because many different inputs map to the same output, so the mapping is not invertible even conceptually. Confusing the two leads to serious misuse, such as trying to "hash" data for confidentiality instead of encrypting it.

Why does collision resistance require roughly double the bit-length of preimage resistance for equivalent security?

Preimage and second-preimage resistance are broken by a brute-force search over a single fixed target, costing about 2n2^n trials for an nn-bit digest. Collision resistance is broken by the birthday attack, which searches over all pairs among a batch of trials, and pairs grow quadratically with batch size. This means a collision becomes likely after only about 2n/22^{n/2} evaluations rather than 2n2^n. To get 128 bits of collision security you therefore need a 256-bit digest, which is exactly why SHA-256 (not a 128-bit hash) became the standard workhorse.

Can a hash function be preimage-resistant but not collision-resistant?

Yes, and this asymmetry is important. Collision resistance is the strictly stronger property in the standard hierarchy: a collision-resistant function is automatically second-preimage resistant (any second-preimage-finder is trivially a collision-finder), but the converse does not hold generically. It is entirely possible to construct functions (typically pathological or artificially weakened ones) that resist preimage attacks yet leak collisions easily, which is why serious hash function designs and evaluations must test all three properties independently rather than assuming one implies the others.

Why do password hashing systems use different algorithms (bcrypt, Argon2) instead of SHA-256?

General-purpose cryptographic hashes like SHA-256 are deliberately optimized to be fast, since they must hash gigabytes of data efficiently for integrity checks. That speed becomes a liability for password storage, because an attacker with a stolen password database can brute-force billions of guesses per second on GPUs. Password hashing functions like bcrypt and Argon2 are intentionally slow and memory-hard, imposing a fixed, tunable cost per guess so that brute-force preimage search over the password space becomes economically infeasible, even though the underlying security property being leveraged is still preimage resistance.

What is a length-extension attack and why does it matter?

In a Merkle–Damgård hash, the digest of a message is literally the final internal chaining state after processing all blocks. If an attacker knows H(M)H(M) but not MM itself, they can still continue the iteration from that chaining state, computing a valid hash of M∥padding∥XM \| \text{padding} \| X for any suffix XX of their choosing, without ever learning MM. This becomes a real vulnerability when systems naively construct authentication tags as H(secret∥message)H(\text{secret} \| \text{message}), since an attacker can forge valid tags for extended messages. HMAC and sponge-based hashes such as SHA-3 are specifically designed to resist this.

Are MD5 and SHA-1 still safe to use anywhere?

Not for any security-critical purpose. MD5's collision resistance is completely broken — arbitrary collisions can be generated in seconds on ordinary hardware — and it should never be used for signatures, certificates, or integrity of adversarial data. SHA-1's collision resistance was practically broken in 2017 via the "SHAttered" attack, though it remains marginally harder to exploit than MD5. Both are still sometimes seen in legacy non-adversarial contexts, such as internal deduplication where no attacker controls the input, but any system exposed to an adversary should use SHA-256, SHA-3, or BLAKE3 instead.

How does collision resistance relate to digital signatures specifically?

Digital signature schemes almost always sign H(M)H(M) rather than the raw message MM, both for efficiency (fixed-size input to the signing algorithm) and because most signature algorithms are not designed to safely sign arbitrarily long messages directly. If HH is not collision-resistant, an attacker can find two messages M1M_1 and M2M_2 with the same digest, get the honest party to sign M1M_1, and then present the identical signature as a valid signature over M2M_2 — a devastating forgery. This is precisely why collision resistance, treated as its own deep topic, is often considered the most safety-critical of the three properties in practice.

Before this

Where this leads