Expand description
§IntegrityChain: FIPS 205 Stateless Hash-Based Digital Signature Standard
FIPS 205 Stateless Hash-Based Digital Signature Standard written in pure Rust for server, desktop, browser and embedded applications. The source repository includes examples demonstrating benchmarking, code provenance, constant-time statistical measurements, a fuzzing harness, WASM execution, a C FFI shared library and Python bindings.
This crate implements the released FIPS 205 standard in pure Rust with minimal and mainstream dependencies, and without
any unsafe code. All twelve security parameter sets are fully functional and tested. Key generation and signing are
constant-time: every branch, loop bound and memory index depends only on public data, and each signature makes the
same number of hash calls for its parameter set, whatever the key, message or randomness. The crate does not require
the standard library (it is #![no_std]), makes no heap allocations (no alloc needed), and exposes the RNG, so it
suits the full range of applications from server down to bare metal. The API is stabilized, and the code is heavily
biased towards safety and correctness.
See https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.205.pdf for a full description of the target functionality.
The functionality is extremely simple to use, as demonstrated by the following example.
use fips205::slh_dsa_shake_128s; // Could use any of the twelve security parameter sets.
use fips205::traits::{SerDes, Signer, Verifier};
let msg_bytes = [0u8, 1, 2, 3, 4, 5, 6, 7];
// Generate both public and secret keys. This only fails when the OS rng fails.
let (pk1, sk) = slh_dsa_shake_128s::try_keygen()?;
// Use the secret key to generate a signature. The second parameter is the
// context string (often just an empty &[]), and the last parameter selects
// the preferred hedged variant. This fails when the OS rng fails or the context is longer than 255 bytes.
let sig_bytes = sk.try_sign(&msg_bytes, b"context", true)?;
// Serialize the public key, and send with message and signature bytes. These
// statements model sending byte arrays over the wire.
let (pk_send, msg_send, sig_send) = (pk1.into_bytes(), msg_bytes, sig_bytes);
let (pk_recv, msg_recv, sig_recv) = (pk_send, msg_send, sig_send);
// A public key of the right length always decodes.
let pk2 = slh_dsa_shake_128s::PublicKey::try_from_bytes(pk_recv)?;
// Use the public key to verify the msg signature
let v = pk2.verify(&msg_recv, &sig_recv, b"context");
assert!(v);The Rust Documentation lives under each Module corresponding to the desired security parameter.
§Notes
- This crate is fully functional and corresponds to the final released FIPS 205 (August 13, 2024).
- Constant-time: key generation and signing never branch, loop or index memory on secret data
(
SK.seed,SK.prf,opt_rand, and the FORS and WOTS+ secret values derived from them). Control flow and memory access follow only public data: the parameter set, the message and context lengths, thehedgedflag, and the message digest, tree indices and WOTS+ digits that the signature reveals. For each parameter set, key generation and signing always make the same number of calls to each hash function; only hashing the message and context takes longer as they grow. Checked by source review, by counting hash calls in all twelve parameter sets, and by thedudectmeasurements. The claim is at the source level: the compiler and CPU are trusted not to add secret-dependent timing, and the caller’s RNG is outside it. Verify uses only public data and makes no constant-time claim. - FIPS 205 places specific requirements on randomness (section 3.1), hence the exposed
RNG. RNG integration usesrand_core0.6: custom generators implementCryptoRngCore(CryptoRng+RngCore), which this crate re-exports along withRngError. Key generation and signing calltry_fill_bytes, so handle its error, or usekeygen_from_seedand sign withhedged = false. - The default features enable
default-rngplus all twelve parameter sets. That OS RNG path is for hosted environments; it will not compile on bare-metal targets that lack agetrandombackend (for examplethumbv7em-none-eabi). Embedded builds usedefault-features = false, the parameter-set feature they need, and*_with_rng, orkeygen_from_seedandhedged = false:fips205 = { version = "0.5", default-features = false, features = ["slh-dsa-sha2-128s"] }. try_hash_signandhash_verify(HashSLH-DSA) take a precomputed digest and a DER-encoded OID (pre_hashlists the NIST CSOR encodings). The library does not hash the message. For apre_hashOID the digest must have that function’s output length (32 bytes for SHAKE128, 64 for SHAKE256), so passing the message by mistake is an error. Any other OID must be DER-encoded and takes a digest of up to 1024 bytes.- Test vectors: the NIST ACVP keyGen, sigGen and sigVer vectors (including HashSLH-DSA) and the
SLotH known-answer files, regenerated and checked by hash,
run in the test suite, and the Python bindings apply the ACVP files for the four 128-bit sets
through the C ABI. The vector files stay in the repository; the published crate has only the
keyGen file, which the bindings’ tests can use through
FIPS205_NIST_VECTORS. - A C shared library (
libfips205, published asfips205-ffi) for the four 128-bit sets, including HashSLH-DSA, with Python bindings, and a WASM browser demo, are described inffi/README.mdandwasm/README.md. - Requires Rust 1.85 or higher (Debian stable, trixie). The minimum supported Rust version may change in the future, but only with a minor version bump (once the major version is above 0).
- All on-by-default features of this library are covered by
SemVer.
§License
Contents are licensed under either the Apache License, Version 2.0 or MIT license at your option.
§Contribution
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.
Modules§
- pre_
hash - DER-encoded OIDs for pre-hash functions used with HashSLH-DSA. See RFC 6234 (for SHA2), RFC 9688 (for SHA3), and RFC 8702 (for SHAKE). These are all within the OID space prefixed by 2.16.840.1.101.3.4.2, a.k.a. joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) See also https://csrc.nist.gov/projects/computer-security-objects-register/algorithm-registration#Hash
- slh_
dsa_ sha2_ 128f - Functionality for the SLH-DSA-SHA2-128f security parameter set per FIPS 205 section 11.
- slh_
dsa_ sha2_ 128s - Functionality for the SLH-DSA-SHA2-128s security parameter set per FIPS 205 section 11.
- slh_
dsa_ sha2_ 192f - Functionality for the SLH-DSA-SHA2-192f security parameter set per FIPS 205 section 11.
- slh_
dsa_ sha2_ 192s - Functionality for the SLH-DSA-SHA2-192s security parameter set per FIPS 205 section 11.
- slh_
dsa_ sha2_ 256f - Functionality for the SLH-DSA-SHA2-256f security parameter set per FIPS 205 section 11.
- slh_
dsa_ sha2_ 256s - Functionality for the SLH-DSA-SHA2-256s security parameter set per FIPS 205 section 11.
- slh_
dsa_ shake_ 128f - Functionality for the SLH-DSA-SHAKE-128f security parameter set per FIPS 205 section 11.
- slh_
dsa_ shake_ 128s - Functionality for the SLH-DSA-SHAKE-128s security parameter set per FIPS 205 section 11.
- slh_
dsa_ shake_ 192f - Functionality for the SLH-DSA-SHAKE-192f security parameter set per FIPS 205 section 11.
- slh_
dsa_ shake_ 192s - Functionality for the SLH-DSA-SHAKE-192s security parameter set per FIPS 205 section 11.
- slh_
dsa_ shake_ 256f - Functionality for the SLH-DSA-SHAKE-256f security parameter set per FIPS 205 section 11.
- slh_
dsa_ shake_ 256s - Functionality for the SLH-DSA-SHAKE-256s security parameter set per FIPS 205 section 11.
- traits
- All functionality is covered by traits.
Structs§
- RngError
- The
rand_coretypes are re-exported so that users of fips205 do not have to worry about using the exact correct version ofrand_core. Error type of random number generators
Traits§
- Crypto
Rng - The
rand_coretypes are re-exported so that users of fips205 do not have to worry about using the exact correct version ofrand_core. A marker trait used to indicate that anRngCoreorBlockRngCoreimplementation is supposed to be cryptographically secure. - RngCore
- The
rand_coretypes are re-exported so that users of fips205 do not have to worry about using the exact correct version ofrand_core. The core of a random number generator.