A Deep Dive Into Merkle Damgård Vs. Sponge Construction For Hash Functions: Sha 256 And Sha 3

2020-07-24 · Leonardo Benicio
Summary

A comprehensive technical exploration of a deep dive into merkle damgård vs. sponge construction for hash functions: sha 256 and sha 3, covering key concepts, practical implementations, and real-world applications.

Contents

The Silent Guardians: From Merkle-Damgård to Sponge – The Architectural Revolution of Cryptographic Hashing

Introduction

The digital world is built on a foundation of quiet, perfect bouncers. They don’t wear earpieces or break up fights, but they perform a security function so critical that without it, the entire edifice of modern computing – from secure internet browsing (HTTPS) and software distribution, to cryptocurrency and password storage – would collapse into a chaotic, easily-fooled mess. These bouncers are cryptographic hash functions, and their job is deceptively simple: take an input of any size, a digital “person” of infinite possible shapes and sizes, and output a fixed-length, seemingly random “ID number,” a summary called a digest or hash.

The bouncer’s rules are absolute. It must be deterministic (the same person always gets the same ID). It must be quick. But most importantly, it must be impossible to forge. You must not be able to find two different people who get the same ID (collision resistance), and given just the ID, you must be utterly unable to reconstruct the person (preimage resistance).

For decades, one particular blueprint, one set of architectural plans, was the undisputed champion of building these bouncers. This was the Merkle-Damgård (MD) construction, the hidden skeleton behind giants like MD5, SHA-1, and the ubiquitous SHA-256. For years, SHA-256 was the gold standard, the bedrock of Bitcoin, TLS 1.2, and countless other systems. It was the silent, unbreakable guardian. Then, something shifted in the cryptographic landscape. Whispers of theoretical cracks turned into groans of practical weakness. The perfect bouncer for one era turned out to have a fundamental design flaw, a crack in its architectural DNA that, while not yet making it a turncoat, left it vulnerable to a specific, insidious kind of identity theft. The security community needed to fundamentally rethink the blueprint. The result was a radically different approach, a paradigm shift in how we build these guardians. This new design is the Sponge Construction, and its most famous child is the SHA-3 standard (Keccak).

In this deep dive, we’ll explore both constructions from the ground up. We’ll dissect the Merkle-Damgård structure, understand its strengths and its Achilles’ heel, then journey into the sponge world, seeing how a radical rethinking of state management, padding, and output generation eliminated the vulnerabilities that plagued the old guard. By the end, you’ll understand not just the what but the why – the subtle architectural choices that separate a hash function that might one day be broken from one that resists even the most sophisticated cryptanalytic attacks.


Chapter 1: The Role of a Cryptographic Hash Function

Before we dive into the architectural blueprints, we need a precise understanding of what a cryptographic hash function must achieve. Think of it as a one-way, collision-free blender. You pour in any amount of data – a single byte, a novel, a multi-gigabyte file – and you get back a fixed-size “fingerprint.” The most important properties are:

  1. Deterministic: The same input always yields the same output.
  2. Fast: Must be efficient to compute for any reasonable input length.
  3. Preimage Resistance: Given a hash output h, it should be computationally infeasible to find any input m such that hash(m) = h. In other words, you can’t reverse it.
  4. Second Preimage Resistance: Given an input m1, it’s hard to find another input m2 (m1 ≠ m2) with hash(m1) = hash(m2). This prevents someone from swapping a known message with a different one that hashes the same.
  5. Collision Resistance: It’s hard to find any two distinct inputs m1 and m2 that hash to the same output. This is stronger than second preimage resistance – it doesn’t care which pair you find, just that you find a collision.
  6. Avalanche Effect: A tiny change in input (e.g., flipping one bit) should produce a completely different hash, with roughly half the output bits flipped on average.

These properties are essential for digital signatures (sign the hash, not the message), password storage (store the hash of the password, not the password itself), data integrity (compare hashes to detect file corruption), and many other applications.

For decades, the dominant way to build a hash function that satisfies these properties was the Merkle-Damgård construction. It’s elegant, simple, and proven secure under certain assumptions about the underlying compression function. But as we’ll see, simplicity can also be a vulnerability.


Chapter 2: The Merkle-Damgård Blueprint – The Old Guard

2.1 The Basic Idea

The Merkle-Damgård construction was independently described by Ralph Merkle and Ivan Damgård in 1979 and 1989, respectively. The core insight: you can build a hash function that handles arbitrary-length inputs by iterating a fixed-size, one-way compression function. Think of the compression function as a black box that takes two fixed-size inputs – a chaining variable (state) and a message block – and outputs a new, fixed-size chaining variable. Then you process the message block-by-block, updating the state each time.

The construction looks like this:

  1. Padding: The input message is padded to a multiple of the block size. The padding includes the original message length, providing clear domain separation. (For SHA-256, block size = 512 bits, output = 256 bits.)
  2. Initialization: An initial state (IV) is defined – a fixed, public constant.
  3. Iteration: For each message block M_i (starting with i=0), compute: state = Compression(state, M_i).
  4. Finalization: After processing all blocks, the final state is the hash output. Optionally, a finalization step (like truncation) may be applied.

The security of the entire construction is reduced to the security of the compression function. If the compression function is collision-resistant (or preimage-resistant), then the Merkle-Damgård hash is also collision-resistant (or preimage-resistant). That sounds great, right? But there’s a catch – the reduction assumes certain properties about the compression function, and in practice, the construction introduces additional properties (like length extension) that aren’t inherent in the compression function alone.

2.2 Anatomy of SHA-256: A Concrete Example

SHA-256 is the star of the Merkle-Damgård family. Let’s look under the hood.

  • Block size: 512 bits (64 bytes)
  • Word size: 32 bits
  • Output size: 256 bits (8 words)
  • Number of rounds: 64

The compression function takes a 256-bit state (8 words: A, B, C, D, E, F, G, H) and a 512-bit message block. It expands the 16 message words (each 32 bits) into 64 words using a message schedule. Then it runs 64 rounds of a Feistel-like structure, updating the state using bitwise operations, modular additions, and logical functions (Ch, Maj, etc.). After 64 rounds, the old state is added to the new state (feed-forward). This feed-forward step is critical for one-wayness.

Here’s a simplified Python-like pseudocode for the SHA-256 compression function (not including the schedule expansion):

def sha256_compress(state, block):
    # state is 8 32-bit words, block is 16 32-bit words
    a, b, c, d, e, f, g, h = state
    # message schedule expansion (not shown)
    w = expand(block)  # 64 words
    for i in range(64):
        S1 = rotate_right(e, 6) ^ rotate_right(e, 11) ^ rotate_right(e, 25)
        ch = (e & f) ^ ((~e) & g)
        temp1 = h + S1 + ch + k[i] + w[i]
        S0 = rotate_right(a, 2) ^ rotate_right(a, 13) ^ rotate_right(a, 22)
        maj = (a & b) ^ (a & c) ^ (b & c)
        temp2 = S0 + maj
        h = g
        g = f
        f = e
        e = d + temp1
        d = c
        c = b
        b = a
        a = temp1 + temp2
    new_state = [(a + state[0]) & 0xFFFFFFFF,
                 (b + state[1]) & 0xFFFFFFFF,
                 ...]
    return new_state

The 64 rounds provide confusion and diffusion. The feed-forward (adding the old state to the new state) ensures that even if you can invert the round function, you still need the initial state to undo.

2.3 Padding in Merkle-Damgård

Padding is not just for alignment. It’s essential for security. The standard padding for SHA-256 (and most MD hashes) is “Merkle-Damgård strengthening”:

  • Append a ‘1’ bit.
  • Append enough ‘0’ bits so that the total length in bits is congruent to 448 modulo 512 (i.e., 64 bits less than a full block).
  • Append the original message length as a 64-bit big-endian integer.

This ensures that different input lengths always produce different padded inputs, even if the original messages differ only in trailing zeros. Also, the length block is processed inside the compression function, which prevents certain trivial collisions.

2.4 The Length Extension Attack: The Achilles’ Heel

For years, Merkle-Damgård was considered perfectly secure. Then, in the mid-1990s, cryptographers noticed a weird property: given hash(m) and the length of m, you can compute hash(m || padding || extra) without knowing m. This is called the length extension attack. How does it work?

Because the hash output is just the final state after processing all blocks, you can take that state as the initial state for processing additional blocks. You essentially restart the iteration from where it left off. But you need to “continue” the padding correctly. If you know the length of m, you know how many bits of padding were already added. So you can construct a new message m’ = m || pad || extra, where pad is the padding that would have been applied to m, and then you apply the hash function to extra starting from the hash(m) state. The result is exactly hash(m’).

Example: Suppose a server stores hash(password || seed) for password verification. An attacker who doesn’t know the password can still compute hash(password || seed || extra) for any extra, by using the length extension property. They can forge a message that the server would accept if it checks only the hash of concatenation.

This attack doesn’t break collision resistance or preimage resistance in theory, but it breaks the property that a hash function should behave like a random oracle. In a random oracle, you cannot predict the output for an extended input just from the output of a prefix. Length extension is a design flaw inherent to the Merkle-Damgård structure.

2.5 Practical Impact and Mitigations

The length extension attack is not just theoretical. It has real-world consequences:

  • Hash-based message authentication codes (HMAC): HMAC was specifically designed to be resistant to length extension. That’s why HMAC-SHA-256 is still secure, even though SHA-256 itself is vulnerable. HMAC uses a secret key to wrap the hash, preventing an attacker from continuing the chain.
  • Some naive constructions: If you try to build a keyed hash by simply hashing key || message, you’re vulnerable. Similarly, using hash(seed || message) as a pseudorandom function is broken.
  • Digital signatures: While signatures typically use a different construction (hash then sign), the length extension doesn’t directly break them because the signature uses the private key. However, certain protocols that rely on hash-based commitments might be affected.

To mitigate length extension, developers often:

  • Use a secret prefix that is not just the message (e.g., HMAC).
  • Use a different hash function (like SHA-3, which is not vulnerable).
  • Apply a finalization step that doesn’t just output the state (e.g., truncation, final XOR).

But the fundamental issue is architectural. The Merkle-Damgård structure leaks the internal state, allowing continuation. This is what led the cryptographic community to look for a new blueprint.


Chapter 3: The Sponge Paradigm – A New Shape

3.1 From Chain to Sponge

The sponge construction emerged from the SHA-3 competition, organized by NIST from 2007 to 2012. The winning design, Keccak (pronounced “ket-chak”), was designed by Guido Bertoni, Joan Daemen, Michaël Peeters, and Gilles Van Assche. It introduced a radically different way of building a hash function: instead of a chain of compression functions, the sponge absorbs input into a large state and then squeezes out output.

The key differences from Merkle-Damgård:

  • No iterative compression chain: The state is a large, fixed-size buffer (for Keccak, 1600 bits). The message blocks are XORed into the state, and then a permutation (a bijective function) scrambles the entire state. No compression function that reduces size.
  • Variable-length output: You can produce any desired output length by squeezing out as many bits as you need. This makes a sponge a XOF (eXtendable Output Function) by design, whereas MD hash functions have a fixed output size.
  • No length extension vulnerability: Because the output is derived from the entire state after all input has been absorbed, and the state is not directly exposed, you cannot continue absorbing after outputting. The sponge construction is provably indifferentiable from a random oracle (under certain assumptions), which means it resists attacks like length extension.

3.2 Anatomy of the Sponge Construction

A sponge function operates as a state of b bits, divided into two parts: r (the bitrate) and c (the capacity). So b = r + c. The rate is the portion that interacts with input and output; the capacity is the inner part that remains hidden.

The two phases:

  1. Absorbing Phase: The input message is padded to a multiple of r bits. Then, for each block of r bits, the block is XORed into the first r bits of the state, and then the entire b-bit state is transformed by a fixed permutation f. This process continues until all message blocks are absorbed.

  2. Squeezing Phase: Once all input is absorbed, to produce output, you output the first r bits of the state, then apply the permutation f to the state again, and repeat until you have the desired output length. If you need more than r bits, you keep squeezing.

Important: The capacity c is what provides security. An attacker who doesn’t know the full state cannot predict the output. The security level is roughly c/2 for collision resistance (because of birthday attacks) and c for preimage resistance. For SHA-3-256, for example, c = 512 bits (providing 256-bit collision resistance, matching SHA-256’s security level). The rate r is 1088 bits (1600 - 512) for SHA-3-256, meaning it processes 136 bytes per permutation.

3.3 The Keccak Permutation

The permutation f in Keccak is a key innovation. It operates on a 5x5x64 cube of bits (5x5 words each 64 bits, total 1600 bits). The permutation consists of 24 rounds, each round applying five step mappings (θ, ρ, π, χ, ι). These steps provide diffusion and nonlinearity:

  • θ (Theta): XOR of each bit with the parity of two columns, providing linear diffusion in the state.
  • ρ (Rho): Rotation of the bits within each lane (each 64-bit word) by a fixed offset, providing intra-lane diffusion.
  • π (Pi): Permutation of the lanes, providing inter-lane diffusion.
  • χ (Chi): Nonlinear step using a 5-bit S-box applied to each row, providing the nonlinearity essential for security.
  • ι (Iota): XOR of the first lane with a round constant, breaking symmetry.

The key property: the permutation is a bijection (invertible), but the sponge construction is still one-way because the state is large and the capacity bits are unknown. An attacker cannot invert the permutation without knowing the entire state, and even if they could, the XOR of input blocks prevents trivial inversion.

3.4 Padding in the Sponge

Padding for Keccak uses a simple rule: append ‘1’ bit, then ‘0’ bits until the block length is a multiple of r. Additionally, a suffix is added for domain separation: for the SHA-3 standard, the padding appends ‘01’ followed by ‘1’ and ‘0’s. This ensures that different applications (hashing, SHAKE XOFs) produce different outputs.

3.5 Security Analysis of Sponge

The sponge construction has been rigorously analyzed. The main security bound is based on the capacity c. For any distinguisher that makes q queries to the permutation, the advantage in distinguishing the sponge from a random oracle is bounded by something like O(q² / 2^c). So as long as the permutation f behaves like a random permutation (no structural weaknesses), the sponge is secure.

Importantly, the sponge construction is indifferentiable from a random oracle for any c > 0, meaning it resists all generic attacks, including the length extension attack. Because the output is extracted from the state after all input has been absorbed, there is no way to “continue” the hash with more input after outputting. The state has already been “squeezed” and then permuted again, so any continued absorption would scramble the state before any output.

3.6 Code Example: Mini-Sponge (Python)

To illustrate, here’s a toy sponge function with a tiny state (just for demonstration – never use in practice):

import hashlib  # for a real permutation, we'd use a small block cipher; here we use a placeholder

def mini_sponge(input_bytes, output_len_bits, rate=8, capacity=8):
    # State size = rate + capacity (bits)
    state = [0] * (rate + capacity)  # list of bits (0/1)
    # Padding: add '1' then '0's to make multiple of rate
    input_bits = []
    for byte in input_bytes:
        for i in range(8):
            input_bits.append((byte >> (7-i)) & 1)
    input_bits += [1]  # padding start
    while len(input_bits) % rate != 0:
        input_bits.append(0)

    # Absorb phase
    for block_start in range(0, len(input_bits), rate):
        block = input_bits[block_start:block_start+rate]
        # XOR into first rate bits of state
        for i in range(rate):
            state[i] ^= block[i]
        # Apply permutation (use SHA-256 of state as pseudo-permutation – just for demo)
        state = list(hashlib.sha256(bytes(state)).digest()%2 for _ in range(rate+capacity))  # NOT secure
        # Real Keccak uses a full 1600-bit permutation
    # Squeeze phase
    output_bits = []
    while len(output_bits) < output_len_bits:
        # Output first rate bits
        output_bits.extend(state[:rate])
        # Apply permutation again
        state = list(hashlib.sha256(bytes(state)).digest()%2 for _ in range(rate+capacity))
    return output_bits[:output_len_bits]

Obviously, the permutation above is not secure. In practice, the Keccak permutation is a carefully designed 24-round algorithm. The sponge construction’s security rests on the permutation’s quality.


Chapter 4: The Battle of Blueprints – Merkle-Damgård vs Sponge

Now that we understand both constructions, let’s compare them head-to-head across several dimensions.

4.1 Security Properties

Length Extension:

  • MD: Vulnerable. The internal state is directly exposed as output, allowing continuation.
  • Sponge: Secure. The output is derived from the state after absorption, and further squeezing does not allow adding input without resetting.

Indifferentiability from Random Oracle:

  • MD: Not indifferentiable due to length extension. There exists an efficient distinguisher.
  • Sponge: Provably indifferentiable for appropriate parameters, assuming the permutation is ideal.

Collision Resistance:

  • MD: Essentially reduces to collision resistance of compression function. For SHA-256, 2^128 security if 256-bit output (birthday bound).
  • Sponge: Security bounded by capacity c/2. For SHA-3-256 (c=512), 2^256 security? No – actually collision resistance is min(2^(c/2), 2^(output/2)). For SHA-3-256, output=256, c=512, so collision resistance is 2^128 (since output size is the limiting factor). Wait, careful: The sponge security bound is roughly O(q² / 2^(c)). For collision resistance, an attacker can try to find collisions in the permutation? The best generic attack on a sponge is a birthday attack on the internal collisions requiring about 2^(c/2) queries. So with c=512, the security level is 2^256 for collision? No, because the output is only 256 bits, a birthday attack on the output itself requires 2^128 queries. The actual security is the minimum of those two. For SHA-3-256, the internal collision bound is 2^256, but the output bound is 2^128, so overall collision resistance is 2^128 – same as SHA-256. The capacity is large enough that the output size dominates. For SHA-3-512 (c=1024, output=512), the security is 2^256 (internal) vs 2^256 (output) – both 256-bit. So the sponge can achieve higher security than MD by using larger capacity, but at the cost of slower performance.

Preimage Resistance:

  • MD: Expected 2^n (for n-bit output) if compression function is secure.
  • Sponge: Expected 2^c for preimage? Actually preimage resistance against a generic attacker is roughly 2^min(c, n). For SHA-3-256, c=512, n=256, so preimage is 2^256. Wait, again the output size limits. So both provide similar preimage resistance for same output size, but the sponge with larger capacity can offer even stronger preimage resistance (up to 2^c) if output size is also large.

Multicollision Attacks:

  • MD: In 2004, Antoine Joux showed that iterative hash functions are vulnerable to multicollision attacks (finding many messages that hash to the same value) with only slightly more effort than a single collision. This is because you can find collisions in the compression function at each step and chain them. The sponge is not vulnerable to this because the permutation acts on the full state each time.

Side-Channel and Implementation:

  • MD: Simpler structure, often faster in software because it uses 32-bit arithmetic and can exploit SIMD.
  • Sponge: The Keccak permutation is bit-sliceable, meaning it can be implemented very efficiently in hardware and with constant-time operations, making it resistant to timing attacks. However, in software, it may be slower than SHA-256 because of the 1600-bit state and many rounds (24 rounds of 5 steps each).

4.2 Performance

For long messages, the throughput of a hash function is determined by how many bits are processed per permutation call.

  • SHA-256 (MD): Block size 512 bits (64 bytes). For a 256-bit output, it processes 512 bits using 64 rounds of compression. On modern CPUs, it achieves around 200-300 MB/s per core (using hardware instructions like SHA-NI). The internal state is small (256 bits), so it fits in registers.
  • SHA-3-256 (Sponge): Rate r = 1088 bits (136 bytes). It processes 1088 bits per permutation call (24 rounds of Keccak-f[1600]). Benchmark: On a typical CPU, SHA-3-256 achieves about 100-150 MB/s per core (without hardware acceleration). So SHA-256 is faster in software, but SHA-3 has better hardware performance because of bit-slicing.

For short messages (e.g., password hashing), the overhead of the permutation dominates. SHA-3 may be slower due to larger state initialization, but the difference is small for typical uses.

Flexibility: Sponge-based functions offer variable-length output with no extra cost, whereas MD functions are fixed-output and often require running a second hash (like a mask generation function) to produce arbitrary-length output.

4.3 Resistance to Cryptanalytic Advances

The MD construction’s security is tied to the compression function. Over the years, SHA-1 (also MD) was attacked (practical collisions found in 2017 by Google and CWI). MD5 is completely broken. SHA-2 (SHA-256/512) still stands, but there have been theoretical improvements in collision attacks (e.g., on SHA-512). However, these attacks are still far from practical. The sponge design is newer and has withstood extensive cryptanalysis. The Keccak designers were conservative with 24 rounds (they could have chosen fewer). No practical weaknesses have been found in SHA-3. Its structure is fundamentally different, making it resistant to the types of attacks that broke SHA-1 (like differential attacks that exploit the compression function’s linearity). The sponge’s permutation is a bijection, and the rate/capacity separation adds an extra layer of security.


Chapter 5: Real-World Impact – Adoption and Future

The SHA-3 standard (FIPS 202) was published in 2015. Initially, adoption was slow because SHA-256 was still considered secure. However, several factors are driving the shift:

  • Post-Quantum Preparedness: Although quantum computers do not threaten hash function security (Grover’s algorithm reduces preimage search by a square root, but that’s it), the sponge construction is seen as more “cryptographically conservative.” The Keccak team designed it to be as simple as possible, with a clear security proof.
  • XOFs and Random Oracles: Sponges natively provide XOFs (e.g., SHAKE128, SHAKE256), which are useful for key derivation, mask generation, and any case where you need a variable-length output determined by a fixed input. For example, the TLS 1.3 protocol uses SHA-256 for many operations, but SHAKE can replace it for new use cases.
  • Hardware Acceleration: Intel and ARM are starting to include SHA-3 instructions (like the KECCAK instruction in ARMv8.2). As hardware support becomes widespread, performance will improve and may surpass SHA-2 in some contexts.
  • NIST Policy: NIST continues to recommend SHA-2 for most applications, but they encourage migration to SHA-3 for new systems. Federal agencies are beginning to require SHA-3 for some new contracts.

Challenges: The main barrier to adoption is the inertia of existing infrastructure. Billions of devices run SHA-256 in their SSL/TLS stacks, blockchain nodes, and PGP keys. Changing a fundamental building block takes decades. For instance, SSL/TLS 1.2 uses SHA-256; TLS 1.3 also uses SHA-256 (and SHA-384) but not SHA-3. Bitcoin uses SHA-256 and will likely never switch because it would require a hard fork.

However, new projects (like some cryptocurrencies, post-quantum signatures, and secure enclaves) are adopting SHA-3 or Keccak directly. For example, Ethereum uses Keccak-256 (a non-standard variant) for its internal hashing. The IOTA cryptocurrency uses a sponge-based hash. Other applications like password hashing (Argon2) use a combination of functions but not SHA-3 directly.

The future may see a hybrid approach: using SHA-256 for compatibility and SHA-3 for new security-sensitive operations. The sponge paradigm has also inspired other constructions, like the “Gimli” permutation and “Ascon” (winner of the NIST Lightweight Cryptography competition). The sponge design is versatile: it can be used for hashing, authenticated encryption, and random number generation.


Chapter 6: Summary and Conclusion

We began with the simple job of a hash function – a silent bouncer that issues unforgeable IDs. For decades, the Merkle-Damgård construction was the standard blueprint, producing giants like SHA-256. Its elegance and provable security under the compression function made it ubiquitous. But its architectural DNA harbored a flaw: the length extension attack, which broke the random oracle ideal and forced developers into defensive patterns like HMAC.

The sponge construction emerged from the SHA-3 competition, a paradigm shift that ditched the chain compression for a large state, a bijective permutation, and a two-phase absorption-squeeze process. This eliminated length extension, provided variable-length output, and offered provable security that is robust against many classes of attacks. Its most famous child, SHA-3 (Keccak), is now the new gold standard, though adoption is gradual.

So, which blueprint is better? The answer depends on the use case:

  • If you need speed and your application already uses HMAC or relies on specific SHA-2 hardware acceleration, SHA-256 remains a solid choice (for now). The length extension vulnerability is mitigated by HMAC.
  • If you need a secure drop-in replacement that avoids all known pitfalls, or you need an XOF, SHA-3 is the better choice. It’s the future-proof, paranoid bouncer that doesn’t have keys to the back door.

The story of hash function construction is a testament to the constant evolution of cryptography. What was perfect yesterday may be the vulnerability of tomorrow. The sponge construction may itself one day be superseded, but for now, it stands as a brilliant example of how a simple architectural shift – from a chain to a sponge – can close a whole class of vulnerabilities. The silent guardians are still silent, but they are learning new tricks. And the digital world remains safe from identity theft, one hash at a time.


Disclaimer: The code examples in this post are simplified for educational purposes and are not suitable for production cryptographic use.