Skip to main content

falcon/
lib.rs

1//! # falcon — FN-DSA (FIPS 206) Post-Quantum Digital Signatures
2//!
3//! Native Rust implementation of **FN-DSA** (FFT over NTRU-Lattice-Based
4//! Digital Signature Algorithm), the NIST FIPS 206 standard formerly known
5//! as Falcon. Ported from the [C reference](https://falcon-sign.info/) by
6//! Thomas Pornin.
7//!
8//! ## Quick start — Pure FN-DSA
9//!
10//! ```rust
11//! use falcon::prelude::*;
12//!
13//! // Generate an FN-DSA-512 key pair
14//! let kp = FnDsaKeyPair::generate(9).unwrap();
15//!
16//! // Sign with no context (ph_flag = 0x00)
17//! let sig = kp.sign(b"Hello, post-quantum world!", &DomainSeparation::None).unwrap();
18//!
19//! // Verify
20//! FnDsaSignature::verify(sig.to_bytes(), kp.public_key(),
21//!     b"Hello, post-quantum world!", &DomainSeparation::None).unwrap();
22//! ```
23//!
24//! ## HashFN-DSA — pre-hash large messages
25//!
26//! ```rust
27//! use falcon::prelude::*;
28//!
29//! let kp = FnDsaKeyPair::generate(9).unwrap();
30//!
31//! // ph_flag = 0x01: message is SHA-256 hashed before signing
32//! let domain = DomainSeparation::Prehashed {
33//!     alg: PreHashAlgorithm::Sha256,
34//!     context: b"my-protocol-v1",   // optional, max 255 bytes
35//! };
36//! let sig = kp.sign(b"large document ...", &domain).unwrap();
37//! FnDsaSignature::verify(sig.to_bytes(), kp.public_key(),
38//!     b"large document ...", &domain).unwrap();
39//! ```
40//!
41//! ## Key serialization
42//!
43//! ```rust
44//! # use falcon::prelude::*;
45//! let kp = FnDsaKeyPair::generate(9).unwrap();
46//!
47//! let private_key = kp.private_key().to_vec();  // 1281 bytes (FN-DSA-512)
48//! let public_key  = kp.public_key().to_vec();   // 897 bytes
49//!
50//! // Import from both keys or from private key only
51//! let restored = FnDsaKeyPair::from_keys(&private_key, &public_key).unwrap();
52//! let restored2 = FnDsaKeyPair::from_private_key(&private_key).unwrap();
53//! assert_eq!(public_key, restored2.public_key());
54//! ```
55//!
56//! ## Security levels
57//!
58//! | `logn` | Variant | NIST Level | Private Key | Public Key | Signature |
59//! |--------|---------|------------|-------------|------------|-----------|
60//! | 9 | FN-DSA-512  | I | 1281 B | 897 B  | 666 B  |
61//! | 10 | FN-DSA-1024 | V | 2305 B | 1793 B | 1280 B |
62//!
63//! ## Modules
64//!
65//! | Module | Description |
66//! |--------|-------------|
67//! | [`prelude`] | Re-exports all core public types — `use falcon::prelude::*` |
68//! | [`safe_api`] | High-level SDK: keygen, sign, verify, serialization |
69//! | [`falcon`] | Low-level C-equivalent API (streamed signing, expanded keys) |
70//! | `codec`, `shake`, `rng`, … | Internal ports of the C reference |
71//!
72//! ## Features
73//!
74//! | Feature | Default | Description |
75//! |---------|---------|-------------|
76//! | `std` | ✅ | OS-level entropy via `/dev/urandom` |
77//! | *(no std)* | — | `no_std` / WASM — use `generate_deterministic` |
78//! | `serde` | — | `Serialize`/`Deserialize` for all public types |
79
80#![no_std]
81#![allow(
82    clippy::needless_range_loop,
83    clippy::manual_range_contains,
84    clippy::identity_op,
85    clippy::excessive_precision,
86    clippy::too_many_arguments,
87    clippy::unnecessary_cast,
88    non_snake_case,
89    non_upper_case_globals,
90    dead_code
91)]
92
93#[cfg(feature = "std")]
94extern crate std;
95
96extern crate alloc;
97
98pub mod codec;
99pub mod common;
100pub mod falcon;
101pub mod fft;
102pub mod fpr;
103pub mod keygen;
104pub mod rng;
105pub mod safe_api;
106pub mod shake;
107pub mod sign;
108pub mod vrfy;
109
110/// Prelude — import the entire public API with `use falcon::prelude::*`.
111///
112/// ```rust
113/// use falcon::prelude::*;
114///
115/// let kp = FnDsaKeyPair::generate(9).unwrap();
116/// let sig = kp.sign(b"msg", &DomainSeparation::None).unwrap();
117/// FnDsaSignature::verify(sig.to_bytes(), kp.public_key(), b"msg",
118///     &DomainSeparation::None).unwrap();
119///
120/// // Expanded-key fast repeated signing
121/// let ek = kp.expand().unwrap();
122/// let sig2 = ek.sign(b"msg", &DomainSeparation::None).unwrap();
123/// FnDsaSignature::verify(sig2.to_bytes(), ek.public_key(), b"msg",
124///     &DomainSeparation::None).unwrap();
125/// ```
126pub mod prelude {
127    pub use crate::safe_api::{
128        DomainSeparation,
129        FalconError,
130        FalconKeyPair,   // backward-compat alias
131        FalconSignature, // backward-compat alias
132        FnDsaExpandedKey,
133        FnDsaKeyPair,
134        FnDsaSignature,
135        PreHashAlgorithm,
136    };
137}
138
139// Root-level convenience re-exports so `falcon::FnDsaKeyPair` works directly.
140pub use safe_api::{
141    DomainSeparation, FalconError, FalconKeyPair, FalconSignature, FnDsaExpandedKey, FnDsaKeyPair,
142    FnDsaSignature, PreHashAlgorithm,
143};