Keccak-256 collision in the first 48 bits
The distinct four-byte inputs 0xa0c9eb00 and 0x8c465b01 have the same first 48 bits of their Keccak-256 digests: 654b41768127. The required answer is collision.json.
Observed result
Here, 0x denotes hexadecimal encoding of raw input bytes, not text to be hashed literally. The first 48 bits MSB are the first six digest bytes, or first twelve hexadecimal digits.
| Field | Input A | Input B |
|---|
| Raw bytes (hex) | a0c9eb00 | 8c465b01 |
| Full Keccak-256 digest | 654b4176812717d0cbff1dce8492b2daad8199b3b60fd2df84ae32f2e8a39f26 | 654b41768127009ad7e17b9170a66c8954393e43c6c7eba5c7e42b92930da12e |
| First 48 bits | 654b41768127 | 654b41768127 |
These values were computed locally by the JavaScript search and recomputed by a separate Python implementation. The resulting evidence is saved in search-result.json and verification.json. Both implementations also passed the empty-message and abc known-answer checks. The Python verification checked the exact JSON field set, algorithm, integer lambda, distinct decoded inputs, and equality of the first six digest bytes. It returned PASS.
Method and attribution
The search enumerated four-byte little-endian integers starting at zero, hashed each candidate, and stored 48-bit prefixes in a hash table. It found the pair after 22,759,053 candidate evaluations, taking 405.321 seconds in this run. The table preserves all six prefix bytes; the table-index hash is only used to locate entries. The full digests were recomputed after the match.
The permutation, rotation offsets, round constants, and sponge construction follow the primary-source Keccak Team specifications summary, consulted on 2026-10-05. The implementations use Keccak-f[1600] with 24 rounds, a 1088-bit rate, 512-bit capacity, and original Keccak padding with delimited suffix 0x01. The source describes how the suffix is computed from trailing domain bits and gives SHA3-256's different suffix, 0x06. The requested lambda of 24 describes the collision task; the comparison length is 48 bits.
The JavaScript implementation represents lanes as pairs of 32-bit words; the Python implementation uses 64-bit integer lanes. Both are included as ordinary source files and require no downloaded packages or network access. Runtime versions used here were Node.js v24.21.0 and Python 3.12.3.
To reproduce the final check from the repository root:
python3 src/verify.py
Conclusions and limits
The observed equality of the six-byte prefixes and inequality of the inputs establish the requested truncated collision under the implemented Keccak-256 byte convention. The full digests differ; this is not a full 256-bit collision.
The checks are local evidence from two implementations written during this assignment, not an independent review or SIMD certification. SIMD verification was not available or run here; its external verdict remains unanswered. No statistical assumption is needed to compare the reported prefixes.
The supplied previous-attempt failure was runtime_error with “Credit balance is too low.” No prior files or more detailed logs were supplied. This attempt completed its search and local verification without installing dependencies or using a paid external hashing service; it does not establish the cause of that earlier failure.