falcon-multisig 0.1.0

Production-grade post-quantum threshold multisignature library using Falcon-512 (NIST FIPS 206 / FN-DSA)
Documentation
//! # falcon-multisig
//!
//! Production-grade post-quantum threshold multisignature library based on Falcon-512
//! (NIST FIPS 206 / FN-DSA).
//!
//! ## Overview
//!
//! This library provides M-of-N threshold signature schemes built entirely on Falcon-512,
//! the lattice-based signature algorithm standardised by NIST. It is designed to be:
//!
//! - **Chain-agnostic** — no dependency on any specific blockchain runtime or VM.
//! - **Production-ready** — extracted from and validated against a live PQC blockchain
//!   (QuantaChain) running Falcon-512 at the consensus layer.
//! - **WASM-compatible** — uses `falcon-rust` (pure Rust, no C FFI) throughout.
//! - **Misuse-resistant** — domain separation on all signed data; secret keys are
//!   zeroized on drop.
//!
//! ## Threat Model
//!
//! The cryptographic security reduces to the hardness of the NTRU problem and the
//! Short Integer Solution (SIS) problem over NTRU lattices — both believed to be
//! quantum-resistant under current knowledge. No classical or known quantum algorithm
//! breaks Falcon-512 with fewer than 2^128 operations.
//!
//! ## Quick Start
//!
//! ```rust
//! use falcon_multisig::{KeyPair, ThresholdConfig, SigningSession};
//!
//! // Generate a 2-of-3 committee
//! let keypairs: Vec<KeyPair> = (0..3).map(|_| KeyPair::generate()).collect();
//! let public_keys: Vec<_> = keypairs.iter().map(|kp| kp.public_key().clone()).collect();
//!
//! let config = ThresholdConfig::new(2, public_keys).unwrap();
//!
//! // Each signer produces a partial signature
//! let message = b"transfer:alice:bob:1000";
//! let mut session = SigningSession::new(&config, message);
//!
//! session.add_signature(0, keypairs[0].sign(message)).unwrap();
//! session.add_signature(1, keypairs[1].sign(message)).unwrap();
//!
//! // Verify the complete threshold signature
//! assert!(session.verify().unwrap());
//! ```
//!
//! ## Feature Flags
//!
//! | Feature | Default | Description |
//! |---------|---------|-------------|
//! | `std`   | yes     | Enables `std`-dependent APIs and error formatting |
//! | `serde` | yes     | Enables JSON serialization of all public types |
//!
//! ## Security Notes
//!
//! - **Never reuse a `KeyPair` across incompatible domain contexts** — always pass the
//!   full message payload to `KeyPair::sign`, not a pre-hashed digest.
//! - Domain separation (`FALCON_MULTISIG_V1:`) is prepended internally before signing.
//! - All secret key bytes are zeroized when a `KeyPair` is dropped.

#![cfg_attr(not(feature = "std"), no_std)]
#![forbid(unsafe_code)]
#![deny(
    missing_docs,
    clippy::all,
    clippy::pedantic,
    clippy::cargo,
    unused_import_braces,
    unused_qualifications
)]
#![allow(
    clippy::module_name_repetitions,
    clippy::must_use_candidate,
    clippy::missing_errors_doc
)]

#[cfg(not(feature = "std"))]
extern crate alloc;

pub mod address;
pub mod error;
pub mod keypair;
pub mod session;
pub mod threshold;
pub mod verify;

pub use address::MultisigAddress;
pub use error::Error;
pub use keypair::KeyPair;
pub use session::SigningSession;
pub use threshold::ThresholdConfig;
pub use verify::verify_partial;

/// The domain separation tag prepended to every message before signing.
///
/// Changing this value constitutes a breaking protocol change. All peers must
/// agree on the same tag for cross-party verification to succeed.
pub const DOMAIN_TAG: &[u8] = b"FALCON_MULTISIG_V1:";

/// Byte length of a Falcon-512 public key.
pub const PUBLIC_KEY_BYTES: usize = 897;

/// Maximum byte length of a raw Falcon-512 signature.
pub const SIGNATURE_MAX_BYTES: usize = 666;

/// Minimum byte length of a valid raw Falcon-512 signature.
pub const SIGNATURE_MIN_BYTES: usize = 10;