Design

hayahash mixes input bytes using ordinary 64-bit arithmetic. Short inputs take a dedicated path; larger inputs spread the work across parallel lanes. Both output widths share one pass over the input. Full specification · Proofs.

Watch it run

Enter text or choose a preset, then press Play or Step to follow the algorithm. Black bytes are being read, dark gray marks the previous stripe, light gray marks absorbed bytes, and underlines show overlapping reads. The final step shows both digests.


The simulator needs JavaScript. The rest of this page works without it.

The algorithm at a glance

  1. Start from the seed. A 64-bit seed initializes the state.
  2. Mix the input. Up to 16 bytes use a short path. Larger inputs use four lanes, or eight from 320 bytes onward.
  3. Handle the remaining bytes. Reads from the end cover the tail, sometimes overlapping earlier reads.
  4. Finish. Mix in the total length and combine the state into a 64- or 128-bit result.

The operations are addition, XOR, shifts, rotations, and ordinary 64-bit multiplication. No SIMD, AES, or wide multiply is required. Constants and formulas; reference C header.

Two output widths, one pass

hayahash128 returns two words, lo and hi. The low word equals hayahash64 for the same bytes and seed. The high word comes from the same state through a separate finalizer, so it does not require another pass over the input.

Hashing in chunks

The total length is mixed in at the end, so it need not be known up front. The streaming API keeps a bounded buffer and produces the same digest for any split of the input. Taking a digest leaves the state available for more updates. Streaming example.

Why the constants matter

The rotations and multipliers are chosen to prevent specific cancellation patterns found during development. The design notes explain those choices; the quality guide describes the regression tests. These properties do not make hayahash a cryptographic hash.

What can be optimized

Changing constants, block sizes, or the 320-byte threshold changes hashes. Compiler choices such as loop unrolling and auto-vectorization can improve speed while preserving the result. Implementation notes.