# keccak256 48-bit truncated collision (λ = 24)

## Answer

```json
{"algo":"keccak256","lambda":24,"inputA":"0x00436477","inputB":"0x0067ebfa"}
```

Both inputs are hex byte strings (4 bytes each), not UTF-8 text.

| input | keccak256 digest |
|---|---|
| `0x00436477` | `803f144e84b9`2d6803ce5432afcf593a936f87b54be18a4b1ea7410a0c7a018a |
| `0x0067ebfa` | `803f144e84b9`38cd84e779a1863662773ba8a695a9ba3635aae214cc936f54ba |

The first 48 bits (12 hex chars, most significant first), `803f144e84b9`, are the same. The digests differ from the 49th bit onward.

## Evidence (facts: observed locally on 2026-10-06)

1. **Search:** `tools/find_collision.js` is a dependency-free Keccak-f[1600] implementation in Node.js v24.21.0. It runs a birthday search over the 4-byte big-endian counters 0, 1, 2, …. The first repeated 48-bit prefix appeared at evaluation 6,810,619, between counters 0x00436477 (4,416,631) and 0x0067ebfa (6,810,618). The run took 110 s.
2. **Built-in self-test:** before searching, the script checks the standard Keccak-256 vectors: `""` gives `c5d24601…5d85a470` and `"abc"` gives `4e03657a…a12d6c45`. Both passed.
3. **Independent check:** I recomputed both digests with a second implementation, the npm package `js-sha3` v0.13.0 (`keccak256`). It gave the same full digests shown above. It also confirmed that the 48-bit prefixes are equal and the inputs are distinct.
4. **Variant check:** the same inputs under FIPS-202 SHA3-256 give unrelated prefixes (`82ad4aab5a31` and `e4b269f685db`). The collision only holds for original Keccak-256, which uses padding byte 0x01, as Ethereum does. That is the algorithm the task names (`keccak256`).

## Inferences

- An evaluation count of 6.8 M ≈ 2^22.7 is lower than the expected ≈ √(π/2 · 2^48) ≈ 2^24.3 (about 21 M). It is still well within the normal spread of birthday-collision stopping times, so I read it as luck, not as a sign of a weakness in Keccak.
- I assume the verifier reads `0x`-prefixed values as raw bytes and truncates the MSB-first digest to its leading 6 bytes. That matches the task text.

## Uncertainty / open questions

- I have not seen the verifier's exact parsing rules, so I can't confirm them. If it treated `0x00436477` as UTF-8 text, it would hash different bytes and the collision would not hold.
- The `js-sha3` cross-check was fetched over the network and is not committed. Only the self-contained search tool is part of the delivered source.

## Reproduce

```
node tools/find_collision.js collision.json   # deterministic; ~2 min, ~400 MB RAM
```
