falcon_multisig/lib.rs
1//! # falcon-multisig
2//!
3//! Production-grade post-quantum threshold multisignature library based on Falcon-512
4//! (NIST FIPS 206 / FN-DSA).
5//!
6//! ## Overview
7//!
8//! This library provides M-of-N threshold signature schemes built entirely on Falcon-512,
9//! the lattice-based signature algorithm standardised by NIST. It is designed to be:
10//!
11//! - **Chain-agnostic** — no dependency on any specific blockchain runtime or VM.
12//! - **Production-ready** — extracted from and validated against a live PQC blockchain
13//! (QuantaChain) running Falcon-512 at the consensus layer.
14//! - **WASM-compatible** — uses `falcon-rust` (pure Rust, no C FFI) throughout.
15//! - **Misuse-resistant** — domain separation on all signed data; secret keys are
16//! zeroized on drop.
17//!
18//! ## Threat Model
19//!
20//! The cryptographic security reduces to the hardness of the NTRU problem and the
21//! Short Integer Solution (SIS) problem over NTRU lattices — both believed to be
22//! quantum-resistant under current knowledge. No classical or known quantum algorithm
23//! breaks Falcon-512 with fewer than 2^128 operations.
24//!
25//! ## Quick Start
26//!
27//! ```rust
28//! use falcon_multisig::{KeyPair, ThresholdConfig, SigningSession};
29//!
30//! // Generate a 2-of-3 committee
31//! let keypairs: Vec<KeyPair> = (0..3).map(|_| KeyPair::generate()).collect();
32//! let public_keys: Vec<_> = keypairs.iter().map(|kp| kp.public_key().clone()).collect();
33//!
34//! let config = ThresholdConfig::new(2, public_keys).unwrap();
35//!
36//! // Each signer produces a partial signature
37//! let message = b"transfer:alice:bob:1000";
38//! let mut session = SigningSession::new(&config, message);
39//!
40//! session.add_signature(0, keypairs[0].sign(message)).unwrap();
41//! session.add_signature(1, keypairs[1].sign(message)).unwrap();
42//!
43//! // Verify the complete threshold signature
44//! assert!(session.verify().unwrap());
45//! ```
46//!
47//! ## Feature Flags
48//!
49//! | Feature | Default | Description |
50//! |---------|---------|-------------|
51//! | `std` | yes | Enables `std`-dependent APIs and error formatting |
52//! | `serde` | yes | Enables JSON serialization of all public types |
53//!
54//! ## Security Notes
55//!
56//! - **Never reuse a `KeyPair` across incompatible domain contexts** — always pass the
57//! full message payload to `KeyPair::sign`, not a pre-hashed digest.
58//! - Domain separation (`FALCON_MULTISIG_V1:`) is prepended internally before signing.
59//! - All secret key bytes are zeroized when a `KeyPair` is dropped.
60
61#![cfg_attr(not(feature = "std"), no_std)]
62#![forbid(unsafe_code)]
63#![deny(
64 missing_docs,
65 clippy::all,
66 clippy::pedantic,
67 clippy::cargo,
68 unused_import_braces,
69 unused_qualifications
70)]
71#![allow(
72 clippy::module_name_repetitions,
73 clippy::must_use_candidate,
74 clippy::missing_errors_doc
75)]
76
77#[cfg(not(feature = "std"))]
78extern crate alloc;
79
80pub mod address;
81pub mod error;
82pub mod keypair;
83pub mod session;
84pub mod threshold;
85pub mod verify;
86
87pub use address::MultisigAddress;
88pub use error::Error;
89pub use keypair::KeyPair;
90pub use session::SigningSession;
91pub use threshold::ThresholdConfig;
92pub use verify::verify_partial;
93
94/// The domain separation tag prepended to every message before signing.
95///
96/// Changing this value constitutes a breaking protocol change. All peers must
97/// agree on the same tag for cross-party verification to succeed.
98pub const DOMAIN_TAG: &[u8] = b"FALCON_MULTISIG_V1:";
99
100/// Byte length of a Falcon-512 public key.
101pub const PUBLIC_KEY_BYTES: usize = 897;
102
103/// Maximum byte length of a raw Falcon-512 signature.
104pub const SIGNATURE_MAX_BYTES: usize = 666;
105
106/// Minimum byte length of a valid raw Falcon-512 signature.
107pub const SIGNATURE_MIN_BYTES: usize = 10;