External review flagged across rounds 4-6 that the empirical evidence tying the proved model to the deployed code had not moved by a single data point in six rounds: the sole bridge was nine assertion points (3 rounds, one fixed seed, corruption always at byte 100), and the ACVP vectors vendored here contain NO SLH-DSA-SHA2-128s sigVer group at all — the one parameter set this verification campaign is about had zero NIST known-answer verification coverage. VECTORS. tests/nist_acvp_vectors/SLH-DSA-sigVer-FIPS205/sha2_128s_extracted.json carries the three SHA2-128s sigVer groups extracted verbatim from the official NIST ACVP-Server vector set (source URL, upstream file sha256 and extraction method recorded in the file's own _provenance block; per-test private keys dropped as unnecessary to verify). 42 tests: 2 valid and 12 negative per group, the negatives spread over structurally distinct corruption sites — modified R, modified SIGFORS, modified SIGHT, modified message, too-small and too-large signatures. TESTS (all in src/verify_mono.rs, so they exercise the monomorphic path the Lean certificates are about): - mono_matches_nist_acvp_128s_internal — NIST's `internal` group carries M' directly, which is exactly what slh_verify_128s consumes, so these are true known-answer tests OF THE PROVED PATH: 10 executed, 4 attributed to deserialization (wrong-length signatures, rejected above the extraction root). Accounting is exact — all 14 are accounted for, nothing silently skipped. - mono_matches_nist_acvp_128s_external_pure — builds M' the way lib.rs does and requires mono, the deployed verifier and NIST to agree: 10 executed, 9 of them with a NON-EMPTY context. This is the first empirical check of the domain-separator byte and context-length prefix that TRUSTED-BASE item 10 declares outside every proof. - deployed_matches_nist_acvp_128s_prehash — validates the deployed prehash path for 128s: 3 executed, 4 wrong-length, and 7 skipped because NIST exercises prehash functions (SHA3-*, truncated SHA2) this crate's `Ph` enum does not implement. Counted and reported rather than hidden. - mono_matches_deployed_randomized — replaces the fixed-seed/fixed-byte bridge: 12 rounds, varying message lengths including empty, corruption spread across the WHOLE 7856-byte signature, plus wrong-public-key and wrong-context cases that were never exercised before. 108 assertion points, each requiring mono and deployed to agree. Bridge coverage: 9 assertion points -> 131, of which 20 are NIST known-answer tests on the proved path where there were previously none. No change to any verify-path function: this commit touches test code and test data only, so the Charon/Aeneas extraction is unaffected (verified separately by re-running extract.sh and diffing the generated model). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|---|---|---|
| benches | ||
| dudect | ||
| ffi | ||
| fuzz | ||
| src | ||
| tests | ||
| wasm | ||
| .gitignore | ||
| Cargo.lock | ||
| Cargo.toml | ||
| CHANGELOG.md | ||
| deny.toml | ||
| LICENSE-APACHE | ||
| LICENSE-MIT | ||
| README.md | ||
| rust-toolchain.toml | ||
| rustfmt.toml | ||
| SECURITY.md | ||
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, constant-time statistical measurements, and WASM execution.
This crate implements the FIPS 205 final/released standard in pure Rust with minimal and mainstream dependencies,
and without any unsafe code. All twelve (!!) security parameter sets are fully functional. The implementation's
key- and signature-generation functionality operates in constant-time, does not require the standard library, e.g.
#[no_std], has no heap allocations, e.g. no alloc needed, and exposes the RNG so it is suitable for the full
range of applications from server down to the bare-metal. The API is stabilized and the code is heavily biased
towards safety and correctness; further performance optimizations will be implemented as the standard matures.
This crate will quickly follow any changes to FIPS 204 standard/vectors as they become available.
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};
# use std::error::Error;
#
# fn main() -> Result<(), Box<dyn Error>> {
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 only fails when the OS rng fails.
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);
// Deserialize the public key. This only fails on a malformed key.
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);
# Ok(())
# }
The detailed Rust Documentation lives under each Module corresponding to the desired security parameter below.
Notes
- This crate is fully functional and corresponds to the final/released FIPS 205 (August 13, 2024), including the pre-hash variants which formalize methods for signing a hash of the message instead of the message itself (along with metadata about the hasher used).
- Constant-time assurances target the source-code level only, with confirmation via
manual review/inspection, the embedded target, and the
dudectdynamic tests. - Note that FIPS 205 places specific requirements on randomness per section 3.1, hence the exposed
RNG. - Requires Rust 1.70 or higher. The minimum supported Rust version may be changed in the future, but it will be done with a minor version bump (when the major version is larger than 0).
- All on-by-default features of this library are covered by
SemVer. - The FIPS 205 standard and this software should be considered experimental -- USE AT YOUR OWN RISK!
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.