Chosen Prefix Collision Attack Explained

Chosen Prefix Collision Attack Explained

Written by

in

A chosen prefix collision attack turns a weak hash function into a forgery tool. The attacker starts with two different inputs they want to pass off as one, a real certificate and a rogue one, or a clean contract and a swapped version, and then computes trailing bytes that drive both inputs to the exact same hash value. A signature made over one input is then a valid signature over the other. This post explains how a collision differs from a preimage, why the chosen prefix variety is the dangerous one, how broken hashes like MD5 and SHA-1 make it practical, and why the only real fix is to stop using those hashes at all.

What a chosen prefix collision attack is

A hash function takes any input and returns a fixed size digest. A collision is two different inputs that produce the same digest. Collisions always exist in theory, because there are more possible inputs than outputs. The whole job of a secure hash is to make finding one cost more compute than anyone has.

There are two flavors of collision, and the gap between them is the whole story.

  • An identical prefix collision forces the attacker to start both inputs with the same fixed bytes. The two files differ only in some carefully crafted gibberish that the attacker controls from the first byte. Useful, but awkward, because both documents share a common opening the attacker did not get to choose freely.
  • A chosen prefix collision lets the attacker pick two completely different, meaningful prefixes first, say the real data for Alice and the real data for Mallory, and then compute suffixes that make the two whole messages collide. The meaningful part is chosen. Only the trailing filler is crafted.

That freedom is what makes the chosen prefix case usable against real formats. A certificate, a document, or a signed blob has structure the attacker does not control. A chosen prefix collision works around that structure instead of fighting it.

Why the Merkle Damgard design makes suffixes stick

Most classic hashes, including MD5 and SHA-1, are built the same way. They process the message in fixed size blocks, carrying a running internal state from one block to the next. Each block mixes into the state, and the final state is the digest.

state = IV
for block in message:
    state = compress(state, block)
digest = state

One property of this design hands the attacker a gift. If two different messages reach the same internal state at some point, then appending the same bytes to both keeps them equal forever after. Collide once, and anything you glue on after the collision keeps the collision intact.

So the attack has a clear shape. Take prefix P1 and prefix P2. They push the hash into two different internal states. The attacker then computes a pair of collision blocks, call them C1 and C2, that nudge those two different states back into one shared state. This is the expensive part, built from what researchers call near collision blocks and differential paths through the compression function. Once the states match, the attacker appends one identical suffix S to both, and the two full messages hash to the same value.

hash( P1 || C1 || S ) == hash( P2 || C2 || S )

Neither message looks like noise from the outside. The prefixes are real. The suffix is real and shared. Only the short collision blocks in the middle are crafted, and formats are full of places to hide a few opaque bytes, a comment field, an image thumbnail, an unused extension.

The signer signs what they read. The attacker makes a second document the signer never saw carry the same signature. The cryptography that was supposed to bind a name to bytes now binds it to two sets of bytes at once.

From a collision to a forged certificate

Picture a certificate authority for an invented service, Acme Trust. It signs certificates by hashing the certificate body and signing the hash. If the attacker can produce two certificate bodies that hash to the same value, one harmless and one granting power the attacker should never have, then a signature over the harmless one is also valid over the dangerous one.

The attacker submits the benign certificate for signing. The authority checks it, hashes it, signs the hash, and returns the signature. The attacker lifts that signature and staples it onto the rogue certificate, which hashes to the same digest. Now they hold a signed certificate the authority never agreed to. The same move works on any signed object. Sign the version you showed me, and I attach your signature to the version I hid.

This is not hypothetical history. A chosen prefix collision against MD5 was used to build a rogue certificate authority in 2008, and the Flame malware in 2012 forged a code signing certificate by the same family of technique. SHA-1 fell to a chosen prefix collision in 2020, years after it was already being retired. The pattern repeats: a hash is declared risky, stays in production because migration is annoying, and then a working chosen prefix collision arrives and forces the issue.

How this sits next to other hash attacks

A collision is not the only way to abuse a hash, and it helps to keep the classes apart. A collision finds two inputs with one digest. A length extension attack, covered in our post on the hash length extension attack, instead takes a known digest and extends the message without knowing the secret, also a consequence of the Merkle Damgard design. Both are about the same family of hashes leaking more structure than their users assumed. For the wider set of tricks that turn a cryptographic assumption into an opening, see our hub on cryptographic oracle attacks.

The fix: retire the broken hashes

There is no clever configuration that makes MD5 or SHA-1 safe for signatures. The collision resistance they were chosen for is gone. The fix is to move to a hash with no known collision weakness and to refuse the old ones outright.

  • Use SHA-256 or stronger for any signature, certificate, or integrity check that an attacker could benefit from forging. SHA-256, SHA-384, SHA-512, and the SHA-3 family have no practical collision attack.
  • Reject deprecated hashes at the boundary. Do not merely prefer SHA-256, actively refuse MD5 and SHA-1 signatures so a downgrade cannot quietly select them. A verifier that still accepts a SHA-1 signature is still exposed.
  • Check the whole chain. A certificate chain is only as strong as its weakest hash. One SHA-1 link anywhere in the path reopens the door.
  • Do not confuse uses. MD5 as a non security checksum for detecting accidental corruption is a different question from MD5 under an adversary. If an attacker gains by a match, you need a hash that resists chosen prefix collisions.

If you are new to how cryptographic weaknesses become real world bugs, our vulnerability basics category walks through more of these from the ground up.

The assumption that breaks

The quiet assumption behind every signature is that a digest names exactly one document. A chosen prefix collision breaks that assumption while leaving the signature math untouched. Nothing is forged in the cryptographic sense. The signer really did sign that digest. The problem is that the digest was never unique, and a system that trusted it to be unique now trusts two documents equally.

That gap, between what a system assumes a hash guarantees and what a broken hash actually guarantees, is the kind of thing an autonomous researcher that tests assumptions is built to notice, by asking whether a signature step really binds what everyone believes it binds. Learn more about that approach on our about page.

Frequently asked questions

What is the difference between a collision and a chosen prefix collision?

A plain collision is any two different inputs that hash to the same value, but the attacker may not control what those inputs look like. A chosen prefix collision lets the attacker pick two meaningful, different prefixes first, such as a real certificate and a rogue one, then compute trailing bytes that make both whole messages hash to the same digest. That control over the meaningful part is what makes it usable against real file and certificate formats.

Why are MD5 and SHA1 vulnerable when SHA-256 is not?

MD5 and SHA-1 have known weaknesses in their compression functions that let researchers build collision blocks far faster than brute force. A practical chosen prefix collision against MD5 was shown years ago, and SHA-1 fell to one in 2020. SHA-256 and stronger hashes have no such practical collision attack today, which is why signatures should move to them.

How does a hash collision let someone forge a certificate?

A certificate is signed by hashing its body and signing that hash. If an attacker makes two certificate bodies that hash to the same value, one harmless and one granting power they should not have, a signature over the harmless body is also valid over the dangerous one. The attacker gets the benign version signed, then attaches that signature to the rogue version.

Is MD5 safe to use for anything?

MD5 is only acceptable where no attacker benefits from a match, such as a checksum that detects accidental file corruption. Any use where an adversary gains from two inputs sharing a digest, such as signatures, integrity checks, or certificates, needs a hash that resists chosen prefix collisions like SHA-256 or stronger.


Put an autonomous researcher on your own systems

UnboundCompute is an autonomous security researcher that reasons about how an application fits together and proves the access control and injection bugs it finds. We are opening a small number of founding design partner seats: private early access pointed at a staging target you choose, and a say in what it looks for. If your team ships software worth pressure testing, apply to the design partner program.