Skip to main content

vaea_ntt/
lib.rs

1// Copyright (C) 2024-2026 Vaea SAS
2// SPDX-License-Identifier: AGPL-3.0-or-later
3//
4// This file is part of VaeaNTT.
5//
6// VaeaNTT is free software: you can redistribute it and/or modify it under
7// the terms of the GNU Affero General Public License as published by the
8// Free Software Foundation, either version 3 of the License, or (at your
9// option) any later version.
10//
11// VaeaNTT is distributed in the hope that it will be useful, but WITHOUT
12// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13// FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
14// License for more details.
15//
16// You should have received a copy of the GNU Affero General Public License
17// along with VaeaNTT. If not, see <https://www.gnu.org/licenses/>.
18
19
20//! # VaeaNTT — High-Performance Number Theoretic Transforms
21//!
22//! NTT engine for lattice-based cryptography, optimized for ARM NEON (aarch64)
23//! with portable scalar fallback.
24//!
25//! ## Quick Start
26//!
27//! ```
28//! use vaea_ntt::ntt32::Ntt32Context;
29//!
30//! // Any NTT-friendly prime < 2^28
31//! let ctx = Ntt32Context::new(256, 8_380_417);
32//!
33//! let mut data = vec![42u32; 256];
34//! ctx.forward(&mut data);
35//! ctx.inverse(&mut data);
36//! assert!(data.iter().all(|&x| x == 42));
37//! ```
38//!
39//! ## Post-Quantum Presets
40//!
41//! ```
42//! use vaea_ntt::pq::{PqScheme, PqNtt};
43//!
44//! // ML-DSA-65 (FIPS 204) — digital signatures, NIST Level 3
45//! let ntt = PqNtt::new(PqScheme::MlDsa65);
46//! ```
47//!
48//! ## Modules
49//!
50//! | Module | Use case |
51//! |--------|----------|
52//! | [`pq`] | Post-quantum presets for ML-DSA (FIPS 204) |
53//! | [`ntt32`] | 28-bit primes (< 2²⁸), ARM NEON vectorized |
54//! | [`ntt64`] | 60–62 bit primes for FHE (SEAL/OpenFHE compatible) |
55//! | [`poly`] | Polynomials over Z_q\[X\]/(X^N+1) with 64-bit coefficients |
56//! | [`rns`] | Multi-prime CRT (Residue Number System) |
57//!
58//! ## Features
59//!
60//! | Feature | Default | Description |
61//! |---------|---------|-------------|
62//! | `std` | **on** | Enables [`std::error::Error`] impl on [`NttError`] |
63//! | `rand` | off | Random polynomial generation |
64//! | `ffi` | off | C/C++/JS bindings via Diplomat |
65//!
66//! ## `no_std`
67//!
68//! This crate is `no_std` compatible (requires `alloc`).
69//! Disable default features to use without `std`.
70
71#![no_std]
72#![warn(missing_docs)]
73
74extern crate alloc;
75
76#[cfg(feature = "std")]
77extern crate std;
78
79/// Errors returned by NTT context construction.
80#[derive(Debug, Clone, PartialEq, Eq)]
81pub enum NttError {
82    /// N must be a power of 2 >= 2.
83    InvalidSize(usize),
84    /// q must be prime.
85    NotPrime(u64),
86    /// q must satisfy q ≡ 1 (mod 2N) for NTT.
87    NotNttFriendly {
88        /// The modulus that failed the NTT-friendly check.
89        q: u64,
90        /// The polynomial size N.
91        n: usize,
92    },
93    /// q must be < 2^28 for the 32-bit pipeline.
94    PrimeTooLarge(u64),
95}
96
97impl core::fmt::Display for NttError {
98    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
99        match self {
100            NttError::InvalidSize(n) => write!(f, "N={n} must be a power of 2 >= 2"),
101            NttError::NotPrime(q) => write!(f, "q={q} is not prime"),
102            NttError::NotNttFriendly { q, n } => {
103                write!(f, "q={q} does not satisfy q ≡ 1 (mod {})", 2 * n)
104            }
105            NttError::PrimeTooLarge(q) => write!(f, "q={q} must be < 2^28"),
106        }
107    }
108}
109
110#[cfg(feature = "std")]
111impl std::error::Error for NttError {}
112
113pub mod ntt32;
114pub mod ntt64;
115pub mod pq;
116pub mod poly;
117pub mod rns;
118
119#[cfg(feature = "ffi")]
120pub mod ffi;