Skip to content

Implementation

How this particular library is built, as distinct from what SLH-DSA is.

  • Comptime parameterisation


    Twelve parameter sets as twelve monomorphised types, every buffer sized at compile time, and structural invariants checked by the compiler rather than by tests.

  • Constant-time discipline


    What is secret and what only looks secret, plus the ctgrind harnesses that verify the claim empirically — and the declassification hooks that make an end-to-end signing audit possible at all.

  • How this is tested


    Four independent regimes: ACVP known-answer vectors, property tests, coverage-guided fuzzing, and Valgrind-based timing verification.

  • The two-lane rule


    Why part of this repository is off-limits to AI assistance, and what that means if you contribute.

Non-negotiables

Every rule below applies to src/. They are enforced by review, and several by the compiler.

Rule In practice
Constant-time No secret-dependent branches, memory accesses, early returns, or table indices
No allocation in the library Stack buffers, comptime sizing. The library takes no allocator because it needs none
Zeroize secrets Every secret buffer scrubbed before scope exit, with volatile semantics so the compiler cannot elide it
KAT-validated No scheme operation is "functional" until NIST ACVP vectors pass
Fuzzed Every parser and attacker-facing API gets a std.testing.fuzz harness
Benchmarked Within 2× of PQClean's portable clean C reference, both sides built without hardware hash acceleration — measured, 35/36 pass, worst 2.06×
Empirically CT-verified ctgrind/Valgrind, not just claimed in a comment

Deliberate non-goals

No dependencies. Zig standard library only. Partly discipline, partly because Lane B targets std.crypto, which cannot take dependencies.

No runtime parameter selection. You cannot pass a ParamSet value at runtime and get a scheme. It is a comptime argument, and a binary contains only the sets it uses. If you need runtime agility, build a dispatch layer over the specialisations you want — that is your policy decision, not the library's.

No SIMD. No hand-vectorised Keccak or SHA-NI paths of our own. This is why the performance gate is pinned to PQClean's portable clean variant rather than its AVX2 one: matching hand-written vector assembly with portable Zig is not a realistic target, and pretending otherwise would make the gate theatre. AVX2 numbers are reported for honesty and never gated.

This is a statement about code in src/, not about what runs. std.crypto may still dispatch to CPU instructions underneath — its SHA-256 takes an ARMv8 crypto-extension path on Apple silicon, and that, rather than anything in this library, is what puts the SHA-2 parameter sets at 0.25×–0.56× of PQClean in the measured comparison. Worth knowing before reading those numbers as a verdict on the code.

No production claim. Unaudited. The 🚧 EXPERIMENTAL banner stays until a third-party audit, regardless of how many gates are green.

Current state

Implemented and ACVP-validated across all twelve parameter sets: key generation, signing and verification, both interfaces, with context strings. Pre-hash (HashSLH-DSA) is deferred by recorded decision.

Hardening is in progress — see the README status table for what is green today, and MILESTONES.md for the development log. This site does not duplicate those; they move faster than prose.