Skip to content

Length Extension Attacks

Length Extension Attacks

eecs-388

Merkle-Damgård Construction

  • method for building hash functions from fixed-input-length compression functions
  • used by many hash functions (e.g. MD5, SHA-1, SHA-256),which allows them to convert messages of arbitrary length into fixed-length hashes
  • procedure:
    1. pad input message so length is a multiple of compression function’s block size
    2. split padded message into equal-sized blocks BiB_i
    3. feed Bi1B_{i-1} (or initialization vector if i=0i = 0) and BiB_i into the compression function ff to get the new hash HiH_i 4. hash of the last block = hash digest h(M)h(M)
---
config:
    look: handDrawn
---
graph LR

B1["$$B_1$$"]
B2["$$B_2$$"]
B3["$$B_{n-1}$$"]
B4["$$B_n$$"]
IV["IV"]
F1{"$$f$$"}
F2{"$$f$$"}
F3{"$$f$$"}
F4{"$$f$$"}
H["$$h(M)$$"]

B1 ~~~ B2 ~~~ B3 ~~~ B4
B1 --> F1
B2 --> F2
B3 --> F3
B4 --> F4
IV --> F1 --> F2 --> F3 --> F4 --> H

Exploit

Input

  • length of message m
  • sha256(m)

Output

  • m + padding(m) + x
  • sha256(m + padding(len(m)) + x)

Setup

say we intercept message m, but cannot read it without knowing m, we can compute the hash of longer messages of the form m + padding(len(m)) + suffix by initializing our SHA-256 function to sha256(m) and setting the function’s message length counter to the size of m plus the padding: padded_message_len = len(m) + len(padding(len(m)))

# m is an arbitrary message; we don't need to know it's contents
padded_message_len = len(m) + len(padding(len(m)))

h2 = sha256(
	state=bytes.fromhex(sha256(m))
	count=padded_message_len
)

then we can use length extension to get the hash of a longer string that we append more text to:

x = 'suffix'.encode()  # .encode() converts str to bytes
h2.update(x)
print(h2.hexdigest())

note that h2.hexdigest() is equal to sha256(m + padding(len(m)) + x), but not sha256(m + x

Sep 8, 2026