# RIPEMD-160 collision for the first 50 bits

The distinct byte strings below collide when RIPEMD-160 digests are truncated
to their first 50 most significant bits. The requested JSON is in
[collision.json](../collision.json), with exactly the four required fields.
The `0x` values encode raw bytes; their textual hexadecimal characters are
not the hashed messages.

| Input | Eight input bytes (hex) | Full RIPEMD-160 digest (hex) |
| --- | --- | --- |
| A | `000000000452502f` | `0c435c0d9564cbf2e44100c312b2ce4afe803d9f` |
| B | `000000000454c205` | `0c435c0d9564c99246e3ab6f6645df758ad3c7a7` |

The common 50-bit prefix is:

```text
00001100010000110101110000001101100101010110010011
```

As an integer, this prefix is `0x0310d70365593`. The leading zero pads the
hexadecimal representation to 13 digits; it does not add bits to the
50-bit prefix. Truncation is computed as
`int.from_bytes(digest, 'big') >> 110`, since the digest has 160 bits.
The original authors' [RIPEMD-160 page](https://homes.esat.kuleuven.be/~bosselae/ripemd160.html)
provides the algorithm description and published test vectors.

## Attributable local evidence

[tools/find_collision.c](../tools/find_collision.c) searched consecutive
eight-byte, big-endian counters using the host OpenSSL `RIPEMD160` function.
It found counters 72,503,343 and 72,663,557 after examining 72,663,557
candidates. The process reported 48 seconds elapsed and exited successfully.
The hash table stores the 50-bit prefix and 14 low counter bits; when a
prefix repeats, it recovers and rehashes the earlier counter before emitting
the candidate.

[tools/verify_collision.py](../tools/verify_collision.py) separately implements
RIPEMD-160 in Python from the authors'
[algorithm pseudocode](https://homes.esat.kuleuven.be/~bosselae/ripemd/rmd160.txt).
It requires no network or third-party packages. It passed eight published
test vectors, including messages requiring multiple padded blocks, then
checked the JSON fields, distinct decoded bytes, and equal 50-bit prefixes.
Its recorded output is [verification.json](verification.json).

The host OpenSSL 3.0.2 command-line digest, with its legacy provider enabled,
also reproduced both full digests. This is a separate invocation of the same
library used for discovery; the Python verifier is the separate hash
implementation. Negative checks confirmed that the verifier rejects both
an unequal-prefix pair and identical inputs.

Reproduce the offline check from the repository root:

```sh
python3 tools/verify_collision.py collision.json
```

## Interpretation and limits

The measured facts are the distinct bytes, the reproduced full digests,
and their equal first 50 bits. Equality of those extracted prefixes directly
satisfies the requested truncated collision condition for lambda 25. The
full digests differ, so this result does not establish a full RIPEMD-160
collision.

These checks were performed locally by the contributor; they carry no
independent review authority. The external SIMD verifier has not been run
here, and its acceptance remains unobserved. No unresolved question remains
about the local prefix comparison.
