# Keccak-256 collision at 48 bits (λ = 24)

## Result

The distinct raw byte inputs below have equal first six bytes of their
Keccak-256 digests. The requested four-field output is in
[`collision.json`](../collision.json).

| Field | Value |
| --- | --- |
| inputA | `0x8f1aa60200000000` |
| inputB | `0xe826140500000000` |
| Keccak-256(inputA) | `a39664cf791e90057a510767e3c25ceb15ef8e443e3b17d949356538b96d619c` |
| Keccak-256(inputB) | `a39664cf791ecbebfaaad7565eb2b69d49a8943ec1c3ef7a318404494adb49d5` |
| Shared first 48 bits | `a39664cf791e` |

The `0x` strings are hex encodings of eight-byte messages. They are not hashed
as textual hex. Truncation retains the first 12 hex digits of the displayed
digest, equivalent to its first 48 bits MSB. The full digests differ.

## Attributable local evidence

The contributor's local C search, [`src/search.c`](../src/search.c), enumerated
eight-byte little-endian counters, computed Keccak-256 prefixes, and sorted the
records to find matching prefixes. It uses the 24-round Keccak-f[1600]
permutation, rate 1088 bits, capacity 512 bits, and original Keccak padding
(`0x01`, final `0x80`). The [Keccak team's specification summary](https://keccak.team/keccak_specs_summary.html)
describes the permutation and sponge construction. The [AMD Keccak-256 implementation documentation](https://docs.amd.com/r/2025.1-English/Vitis_Libraries/security/guide_L1/internals/keccak256.html_1)
explicitly distinguishes Keccak-256's `0x01` padding from SHA3's `0x06` padding.

Observed search batches:

| Counter range (inclusive) | Evaluations | Observed outcome |
| --- | ---: | --- |
| 0–33,554,431 | 33,554,432 | No matching prefix in this batch |
| 33,554,432–100,663,295 | 67,108,864 | Pair above found |

The second batch's local log recorded 9.301 seconds for hashing and 31.894
seconds for hashing, sorting, and finding the pair. Both batches together
evaluated 100,663,296 messages. Batches were sorted separately, so cross-batch
matches were not checked. The search returns the first adjacent match in sorted
prefix order, not necessarily the earliest match in counter order.

A separate coordinate-based Python implementation,
[`src/verify.py`](../src/verify.py), recomputed both complete digests from the
delivered JSON. Unlike the C implementation's fixed rotation cycle and round
constant table, the verifier uses a two-dimensional state and generates round
constants with an LFSR. It also checked the conventional empty-message and
`abc` Keccak-256 known-answer vectors before checking the pair. Local command:

```sh
python3 src/verify.py collision.json
```

The command exited 0, verified the exact four-field schema and requested
algorithm/λ values, decoded distinct byte strings, and confirmed prefix
equality. Its recorded full output is
[`verification.json`](verification.json). The verifier and search have no
third-party runtime dependencies; reproduction instructions are in
[`README.md`](../README.md).

## Facts, inference, and limits

**Observed facts:** the delivered messages differ, both locally recomputed
digests begin with `a39664cf791e`, and their complete 256-bit values differ.

**Inference:** these observations establish the requested truncated collision
under the stated raw-byte decoding and Keccak-256 implementation. This is a
48-bit truncation collision, not a collision of full Keccak-256.

**Uncertainty and unanswered questions:** the local checks are not an independent
review or a SIMD acceptance result. No SIMD verifier was provided or run, so its
acceptance remains unobserved. The supplied source and full digest evidence
allow offline recomputation. No claim is made about full-hash collision security
or optimal search cost.
