# RIPEMD-160 first-48-bit collision

## Observed facts

The submitted inputs are distinct four-byte strings. Hex strings in `collision.json` have a `0x` prefix; that prefix is notation, not part of the hashed input. Recomputing each full RIPEMD-160 digest with `openssl dgst -ripemd160 -binary` (OpenSSL 3.0.13) produced:

| Input | Full 160-bit digest | First 48 bits |
| --- | --- | --- |
| `0x4b3fd300` | `a753ebe0c45aae16f469e0777f027348ee2bd8d0` | `a753ebe0c45a` |
| `0x942def00` | `a753ebe0c45ac7e92464fbe55b9f6a6e260405f5` | `a753ebe0c45a` |

The search hashed successive four-byte, little-endian encodings of integers starting at zero and found this pair after evaluating 15,674,773 inputs. A separate check through Python `hashlib.new('ripemd160', data)` agreed with both command-line digests. OpenSSL documents [RIPEMD160 as a 160-bit digest](https://docs.openssl.org/3.0/man3/RIPEMD160_Init/) and [the `dgst` command's digest options](https://docs.openssl.org/3.0/man1/openssl-dgst/).

Reproduction using the submitted file:

```python
import hashlib, json
with open('collision.json', encoding='utf-8') as f:
    pair = json.load(f)
a, b = (bytes.fromhex(pair[k][2:]) for k in ('inputA', 'inputB'))
assert a != b
ha = hashlib.new('ripemd160', a).digest()
hb = hashlib.new('ripemd160', b).digest()
assert ha[:6] == hb[:6] == bytes.fromhex('a753ebe0c45a')
print(ha.hex(), hb.hex())
```

## Inference

The two different inputs have the same first six digest bytes, which are the most significant 48 bits of the digest byte string. They therefore satisfy the requested truncated-digest collision for λ = 24.

## Limits and unanswered questions

The full 160-bit digests differ. This is a collision only for the specified 48-bit truncation. The local checks use OpenSSL-backed paths; an independently implemented RIPEMD-160 library was not tested. SIMD's own recomputation remains the final external check.
