# SIMD-COLLISION: ripemd160, λ=24

## Question

Find two distinct inputs whose RIPEMD-160 digests agree on the first 48 bits
(λ=24, meaning 2·24=48 bits — the task's λ=24 convention maps to a 48-bit
truncation as stated in the task description).

## Method (fact)

A straightforward birthday-attack script (`test/scratch/find_collision.py`,
not part of the delivered scope, used only for local verification/search) was
run:

- Candidate messages: `b"imd-" + i.to_bytes(8, "little")` for increasing
  integer counters `i`, starting at `i = 1`.
- For each candidate, computed `hashlib.new("ripemd160", msg).digest()[:6]`
  (the first 6 bytes = 48 bits, most-significant-byte first) and stored it in
  a Python dict keyed by that 48-bit value.
- On the first key collision against a previously-seen distinct message,
  stopped and reported both inputs.

This matches the expected birthday-bound cost of roughly 2^24 (≈16.7M)
evaluations for a 48-bit truncated hash; the search in fact found a
collision after 19,307,914 evaluations in about 33 seconds on this machine,
consistent with that order of magnitude.

## Result (fact, independently reproducible)

- `inputA` (hex): `0x696d642d93c2750000000000`
- `inputB` (hex): `0x696d642d8a9d260100000000`

Full RIPEMD-160 digests:

- `RIPEMD160(inputA)` = `0ec879001f9790fdc46ab04d838cf12783433533`
- `RIPEMD160(inputB)` = `0ec879001f978ec693ae944ee9beb5789cb8dfa8`

Both digests begin with the same 6 bytes (48 bits): `0ec879001f97`.

This was verified independently after the search completed by recomputing
both digests from the raw hex bytes via Python's `hashlib.new("ripemd160", ...)`
and confirming:

1. `inputA != inputB` (distinct byte strings), and
2. the first 48 bits of both digests are bit-for-bit identical.

The result is written to `collision.json` at the repository root in the
required schema:

```json
{"algo":"ripemd160","lambda":24,"inputA":"0x696d642d93c2750000000000","inputB":"0x696d642d8a9d260100000000"}
```

## Uncertainty / scope notes

- `hashlib`'s RIPEMD-160 implementation is provided by the system's OpenSSL
  (via `hashlib.new("ripemd160", ...)`); this is a standard, widely-used
  implementation of the RIPEMD-160 algorithm as specified in its original
  1996 specification, not a custom or novel implementation, so no
  correctness risk is introduced by implementation choice.
- The collision was found by brute-force random search, not by exploiting
  any structural weakness in RIPEMD-160 — this is expected and is exactly
  the generic birthday-bound behavior for any 48-bit truncated hash,
  independent of which underlying hash function is used.
- No claim is made about collisions in full (160-bit) RIPEMD-160, which
  remains computationally infeasible to attack via this method; the
  collision found here is scoped strictly to the 48-bit truncation as
  requested.
