hayahash is a family of fast, non-cryptographic 64- and 128-bit hash functions for platforms with ordinary 64-bit scalar arithmetic. It passes the full SMHasher3 suite without requiring SIMD, AES instructions, or a 64x64-to-128-bit multiply.
The reference implementation is the single C header
hayahash.h. Bit-exact ports are available for Rust, Go, Zig,
Java, C#, Python, Swift, JavaScript/TypeScript, and MIPS64 assembly. Every
128-bit API returns ordered lo and hi words, with
hayahash128.lo == hayahash64 for the same input and seed.
Experimental: the algorithm, constants, and digest values may still change. Do not use hayahash yet where hashes must remain stable across versions. It is not a cryptographic hash or message authentication code. See
docs/stability.mdfor the 1.0 freeze criteria andSECURITY.mdfor the threat model.
Haya (速) is Japanese for "fast."
- Portable scalar core: ordinary 64-bit operations, endian-independent output, no undefined behavior, and no architecture-specific intrinsics.
- Two output widths: hayahash64 and hayahash128 share the same state walk; selecting 128 bits adds a second finalization path rather than a second pass over the input.
- Streaming: one-shot and incremental APIs produce identical digests for every split of the same input, in the C reference and in every port.
- Broad language support: every maintained port exposes both widths and is checked against the C reference.
- Quality-gated development: both widths pass all 188 applicable SMHasher3 test groups, with additional structured-collision and differential tests.
The design is aimed at wasm, JVM, .NET, portable C, and other environments where wide multiplication or hardware acceleration cannot be assumed. It is not a universal speed claim: hashes that target native wide multiply, SIMD, or AES instructions can be faster on hardware that provides them. See the benchmark record for competitive results and methodology.
Representative measurements of the public 64- and 128-bit APIs:
| host / compiler | 8 B chained, 64 / 128 (ns) | 1 MiB, 64 / 128 (GB/s) |
|---|---|---|
| Apple M1 Pro / Apple clang 21 | 7.88 / 9.25 | 30.73 / 30.76 |
| Ryzen AI 9 HX PRO 370 / GCC 16 | 4.29 / 4.90 | 61.47 / 61.31 |
| EPYC 9655 KVM guest / GCC 13 | 4.92 / 5.66 | 54.15 / 53.99 |
| wasm32 on M1 Pro / Zig 0.16 | 7.7 / 10.6 | 23.55 / 23.34 |
The M1 and Ryzen native runs are bare metal. The EPYC guest has no frequency control, so its within-host ratio is more meaningful than its absolute rate. The 128-bit dispatch change recorded in the optimization log brought 128-bit bulk to parity with the 64-bit rate on all three machines. The wasm build uses no SIMD or wide multiply. These are point measurements, not a claim that one hash is fastest on every workload or machine.
Detailed size sweeps, ChibiHash comparisons, SMHasher3 shootouts, caveats, and
reproduction notes are in docs/benchmarks.md.
C - copy hayahash.h into your project, or install the
header and pkg-config file with make install:
#include "hayahash.h"
uint64_t h = hayahash64(buf, len, seed);
hayahash128_t h128 = hayahash128(buf, len, seed);
// h128.lo == hmake install PREFIX=/usr/local
cc $(pkg-config --cflags hayahash) main.c -o mainCMake installs the same header and pkg-config file to the same paths,
and adds a package config for find_package:
cmake -S . -B build && cmake --install build --prefix /usr/localfind_package(hayahash 0.5 REQUIRED)
target_link_libraries(app PRIVATE hayahash::hayahash)Streaming uses one shared state for both output widths. Calling a digest function does not modify the state:
hayahash64_state st;
hayahash64_init(&st, seed);
hayahash64_update(&st, part1, n1);
hayahash64_update(&st, part2, n2);
uint64_t h = hayahash64_digest(&st);
hayahash128_t h128 = hayahash128_digest(&st);| language | package | 64-bit call | 128-bit call |
|---|---|---|---|
| Rust | hayahash (no_std) |
hayahash::hayahash64(buf, seed) |
hayahash::hayahash128(buf, seed) |
| Go | github.com/thevilledev/hayahash/go |
hayahash.Hash64(buf, seed) |
hayahash.Hash128(buf, seed) |
| Zig | hayahash module (Zig 0.16) |
hayahash.hayahash64(buf, seed) |
hayahash.hayahash128(buf, seed) |
| Java | io.github.thevilledev:hayahash (17+) |
Hayahash.hash64(buf, seed) |
Hayahash.hash128(buf, seed) |
| C# | Hayahash (.NET 8+) |
Hayahash.Hash64(buf, seed) |
Hayahash.Hash128(buf, seed) |
| Python | hayahash (3.9+) |
hayahash64(buf, seed) |
hayahash128(buf, seed) |
| Swift | Hayahash SwiftPM package (5.9+) |
Hayahash.hash64(buf, seed: 0) |
Hayahash.hash128(buf, seed: 0) |
| JS/TS | hayahash (wasm + pure JS) |
hayahash64(buf, seed) |
hayahash128(buf, seed) |
| MIPS64 | hayahash.S (n64 ABI) |
hayahash64(buf, len, seed) |
hayahash128(buf, len, seed) |
The table lists the one-shot entry points. Every port also provides the
incremental API shown above, spelled the way that language spells it -
Digest in Go (a hash.Hash64) and Rust, Hayahash.Hasher in Swift,
Hasher elsewhere. See docs/ports.md.
Installation details, complete examples, and the repository layout are in
docs/ports.md.
hayahash64 and hayahash128 each pass all 188 applicable SMHasher3 test
groups. CI also checks structured collision sets, one-shot/streaming equality,
cross-language differential conformance, big-endian output, wasm32, MSVC x64,
and the MIPS64 n64 ABI. The exact tests, verification values, and limitations
are documented in docs/quality.md.
cli/hayasum hashes files or stdin with the C reference:
make -C cli
./cli/hayasum -b 128 README.mdIts own tests and fuzz targets live under cli/:
make -C cli check runs the functional harness and replays the fuzz
corpus, make -C cli fuzz-run fuzzes argv parsing, the reader, and the
output escaper.
- Contributing - port sync rules, local gates, SMHasher3 triggers
- Changelog - release history;
DIGESTmarks digest-breaking changes - Test vectors - versioned known-answer digests for external implementers
- Stability / 1.0 criteria - when digests freeze
- Roadmap - gaps against established hash repositories and the order for closing them
- Security policy - threat model and private reporting
- Benchmarks - comparative results and methodology
- Design - the algorithm and structural decisions
- Quality - test coverage and conformance evidence
- Ports - installation, language examples, and layout
- SMHasher3 - reproducing the suite and speed shootouts
- Website deployment - Pages and Cloudflare cache setup
- Optimization log - measured changes and rejected ideas
Public domain under the Unlicense. The separately licensed
SMHasher3 test harness is described in
docs/smhasher3.md.