saorsa_pqc/lib.rs
1//! # Saorsa Post-Quantum Cryptography Library
2//!
3//! A comprehensive, production-ready Post-Quantum Cryptography (PQC) library implementing
4//! NIST-standardized algorithms FIPS 203 (ML-KEM), FIPS 204 (ML-DSA), and FIPS 205 (SLH-DSA)
5//! with both pure PQC and hybrid (classical + PQC) modes.
6//!
7//! ## Features
8//!
9//! ### Key Encapsulation Mechanisms (KEM) - FIPS 203
10//! - **ML-KEM-512**: NIST Level 1 security (128-bit)
11//! - **ML-KEM-768**: NIST Level 3 security (192-bit)
12//! - **ML-KEM-1024**: NIST Level 5 security (256-bit)
13//! - **Hybrid KEM**: Classical ECDH + ML-KEM for defense-in-depth
14//!
15//! ### Digital Signatures - FIPS 204
16//! - **ML-DSA-44**: NIST Level 2 security (~128-bit)
17//! - **ML-DSA-65**: NIST Level 3 security (~192-bit)
18//! - **ML-DSA-87**: NIST Level 5 security (~256-bit)
19//! - **Hybrid Signatures**: Classical Ed25519 + ML-DSA for defense-in-depth
20//!
21//! ### Hash-Based Signatures - FIPS 205
22//! - **SLH-DSA**: 12 parameter sets (SHA2/SHAKE, 128/192/256-bit, fast/small)
23//!
24//! ### Symmetric Encryption (Quantum-Resistant)
25//! - **ChaCha20-Poly1305**: AEAD cipher providing quantum-resistant symmetric encryption
26//! - **Password-based Key Derivation**: PBKDF2 for secure key derivation from passwords
27//! - **Authenticated Encryption**: Built-in authentication prevents tampering
28//!
29//! ### Network Protocol Support
30//! - **Raw Public Keys**: Ed25519 key support for P2P authentication
31//! - **Key Derivation**: Utilities for network identity derivation
32//! - **Protocol Agnostic**: Designed for use with any network protocol
33//!
34//! ### Security Features
35//! - **Memory Protection**: Secure memory handling and cleanup
36//! - **Constant-Time Operations**: Resistance to side-channel attacks
37//! - **Algorithm Negotiation**: Automatic algorithm selection and fallback
38//! - **Security Validation**: Comprehensive parameter and key validation
39//!
40//! ## Quick Start
41//!
42//! ```rust,no_run
43//! use saorsa_pqc::pqc::{MlKem768, MlKemOperations, HybridPublicKeyEncryption};
44//! use saorsa_pqc::symmetric::{SymmetricKey, ChaCha20Poly1305Cipher};
45//!
46//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
47//! // Key encapsulation with ML-KEM
48//! let ml_kem = MlKem768::new();
49//! let (pub_key, sec_key) = ml_kem.generate_keypair()?;
50//! let (ciphertext, shared_secret) = ml_kem.encapsulate(&pub_key)?;
51//! let recovered_secret = ml_kem.decapsulate(&sec_key, &ciphertext)?;
52//! assert_eq!(shared_secret.as_bytes(), recovered_secret.as_bytes());
53//!
54//! // Public key encryption
55//! let pke = HybridPublicKeyEncryption::new();
56//! let plaintext = b"Secret message";
57//! let associated_data = b"context";
58//! let encrypted = pke.encrypt(&pub_key, plaintext, associated_data)?;
59//! let decrypted = pke.decrypt(&sec_key, &encrypted, associated_data)?;
60//! assert_eq!(plaintext, &decrypted[..]);
61//!
62//! // Quantum-resistant symmetric encryption
63//! let key = SymmetricKey::generate();
64//! let cipher = ChaCha20Poly1305Cipher::new(&key);
65//! let (ciphertext, nonce) = cipher.encrypt(b"Quantum-safe data", None)?;
66//! let decrypted = cipher.decrypt(&ciphertext, &nonce, None)?;
67//! assert_eq!(b"Quantum-safe data", &decrypted[..]);
68//! # Ok(())
69//! # }
70//! ```
71//!
72//! ## Security Considerations
73//!
74//! This library is designed with security as the primary concern:
75//!
76//! - **No Panics**: All operations return `Result` types with proper error handling
77//! - **Memory Safety**: Sensitive data is zeroed on drop and uses secure allocators
78//! - **Timing Attacks**: Constant-time implementations where cryptographically relevant
79//! - **Algorithm Agility**: Support for multiple algorithms and hybrid modes
80//! - **Validation**: Comprehensive input validation and parameter checking
81//!
82//! ## Performance
83//!
84//! The library is optimized for both security and performance:
85//!
86//! - **FIPS-Compliant Implementations**: Uses FIPS 203/204/205 certified crates
87//! - **Memory Pooling**: Reduces allocation overhead for frequent operations
88//! - **Parallel Processing**: Optional multi-threading for batch operations
89//! - **Zero-Copy**: Minimal data copying in critical paths
90//!
91//! ## Feature Flags
92//!
93//! The library is designed to work out-of-the-box with sensible defaults.
94//! Optional features are available for specific use cases:
95//!
96//! - `simd`: Enable SIMD acceleration for performance (requires `wide` crate)
97//! - `cert_compression`: Enable certificate compression optimization
98//! - `dangerous_configuration`: Enable dangerous configuration options (not recommended)
99//! - `test-utils`: Enable testing utilities
100//! - `benchmarks`: Enable benchmarking support
101//!
102//! ## Safety and Compliance
103//!
104//! - **NIST Standards**: Implements FIPS 203 (ML-KEM) and FIPS 204 (ML-DSA)
105//! - **No Unsafe Code**: Forbidden by lint configuration
106//! - **Comprehensive Testing**: Property-based testing and fuzzing
107//! - **Security Auditing**: Regular security audits and vulnerability scanning
108
109#![deny(
110 missing_docs,
111 unsafe_code,
112 unused_must_use,
113 clippy::panic,
114 clippy::unimplemented,
115 clippy::todo
116)]
117#![warn(clippy::correctness, clippy::suspicious, clippy::perf)]
118#![cfg_attr(docsrs, feature(doc_cfg))]
119
120// Core PQC modules - the main attraction
121pub mod pqc;
122
123// Symmetric encryption (quantum-resistant)
124pub mod symmetric;
125
126// Comprehensive API module
127pub mod api;
128
129// Re-export the comprehensive API for easy access
130pub use api::{
131 // Utils
132 init as api_init,
133 kdf::helpers as kdf_helpers,
134 // Convenience functions
135 kem::ml_kem_768,
136 sig::ml_dsa_65,
137 slh::slh_dsa_sha2_128s,
138
139 supported_algorithms,
140 version as api_version,
141 // KDF exports
142 HkdfSha3_256,
143 HkdfSha3_512,
144 KdfAlgorithm,
145 MlDsa,
146 MlDsaPublicKey as ApiMlDsaPublicKey,
147 MlDsaSecretKey as ApiMlDsaSecretKey,
148 MlDsaSignature as ApiMlDsaSignature,
149 MlDsaVariant,
150 // Main APIs
151 MlKem,
152 MlKemCiphertext as ApiMlKemCiphertext,
153 MlKemPublicKey as ApiMlKemPublicKey,
154 MlKemSecretKey as ApiMlKemSecretKey,
155 MlKemSharedSecret,
156 MlKemVariant,
157 // Error types
158 PqcError as ApiError,
159 PqcResult as ApiResult,
160
161 SlhDsa,
162 SlhDsaPublicKey,
163 SlhDsaSecretKey,
164 SlhDsaSignature,
165
166 SlhDsaVariant,
167};
168
169// Re-export the most commonly used types and traits for convenience (legacy)
170pub use pqc::{
171 // Types
172 types::{
173 HybridKemCiphertext, HybridKemPublicKey, HybridKemSecretKey, HybridSignaturePublicKey,
174 HybridSignatureSecretKey, HybridSignatureValue, MlDsaPublicKey, MlDsaSecretKey,
175 MlDsaSignature, MlKemCiphertext, MlKemPublicKey, MlKemSecretKey, PqcError, PqcResult,
176 SharedSecret,
177 },
178 EncryptedMessage,
179
180 // Hybrid modes
181 HybridKem,
182 // Public key encryption
183 HybridPublicKeyEncryption,
184 HybridSignature,
185
186 MlDsa65,
187 MlDsaOperations,
188
189 // Implementations
190 MlKem768,
191 // Core traits
192 MlKemOperations,
193};
194
195// Re-export symmetric encryption for convenience
196pub use symmetric::{
197 ChaCha20Poly1305Cipher, EncryptedMessage as SymmetricEncryptedMessage, SymmetricError,
198 SymmetricKey,
199};
200
201// Note: This is a pure PQC library - protocol integration is left to consuming crates
202
203/// Library version information
204pub const VERSION: &str = env!("CARGO_PKG_VERSION");
205
206// Re-export FIPS implementations directly
207pub use fips203::{ml_kem_1024, ml_kem_512, ml_kem_768, traits as kem_traits};
208
209pub use fips204::{ml_dsa_44, ml_dsa_65, ml_dsa_87, traits as dsa_traits};
210
211pub use fips205::{
212 slh_dsa_sha2_128f, slh_dsa_sha2_128s, slh_dsa_sha2_192f, slh_dsa_sha2_192s, slh_dsa_sha2_256f,
213 slh_dsa_sha2_256s, slh_dsa_shake_128f, slh_dsa_shake_128s, slh_dsa_shake_192f,
214 slh_dsa_shake_192s, slh_dsa_shake_256f, slh_dsa_shake_256s, traits as slh_traits,
215};
216
217/// Supported ML-KEM parameter sets
218pub const SUPPORTED_ML_KEM: &[&str] = &["ML-KEM-768"];
219
220/// Supported ML-DSA parameter sets
221pub const SUPPORTED_ML_DSA: &[&str] = &["ML-DSA-65"];
222
223/// Default security level provided by this library
224pub const DEFAULT_SECURITY_LEVEL: &str = "NIST Level 3 (192-bit quantum security)";
225
226/// Initialize the library with optimal settings
227///
228/// This function should be called once at application startup to configure
229/// the library for optimal performance and security.
230///
231/// # Examples
232///
233/// ```no_run
234/// // Initialize once at application startup
235/// saorsa_pqc::init().expect("failed to initialize saorsa_pqc");
236/// ```
237/// Initialize the library with optimal settings
238///
239/// # Errors
240/// Returns an error if initialization of internal components fails.
241pub fn init() -> Result<(), Box<dyn std::error::Error>> {
242 // Initialize logging if available
243 // Note: Logging setup is application-specific, not library-specific
244
245 // Initialize memory pools (always enabled)
246 pqc::memory_pool::initialize_global_pool()?;
247
248 // Validate algorithm availability - always available now
249 // Test that we can create algorithm instances
250 let _ml_kem = pqc::MlKem768::new();
251 let _ml_dsa = pqc::MlDsa65::new();
252
253 Ok(())
254}
255
256/// Get library information and capabilities
257///
258/// Returns information about the library version, supported algorithms,
259/// available features, and compatibility information.
260#[must_use]
261pub fn get_info() -> LibraryInfo {
262 // Parse version string to extract major.minor.patch
263 let version_parts: Vec<&str> = VERSION.split('.').collect();
264 let (major, minor, patch) = if version_parts.len() >= 3 {
265 (
266 version_parts.first().unwrap_or(&"0").parse().unwrap_or(0),
267 version_parts.get(1).unwrap_or(&"3").parse().unwrap_or(3),
268 version_parts.get(2).unwrap_or(&"6").parse().unwrap_or(6),
269 )
270 } else {
271 (0, 3, 6) // Default fallback
272 };
273
274 LibraryInfo {
275 version: VERSION.to_string(),
276 supported_ml_kem: SUPPORTED_ML_KEM.iter().map(|s| (*s).to_string()).collect(),
277 supported_ml_dsa: SUPPORTED_ML_DSA.iter().map(|s| (*s).to_string()).collect(),
278 features: get_enabled_features(),
279 security_level: DEFAULT_SECURITY_LEVEL.to_string(),
280 api_version: ApiCompatibilityInfo {
281 major,
282 minor,
283 patch,
284 min_supported_version: "0.3.0".to_string(), // Maintain compatibility back to 0.3.0
285 stability: "stable".to_string(),
286 },
287 dependencies: DependencyVersionInfo {
288 fips203_version: "0.4".to_string(), // Track major.minor for compatibility
289 fips204_version: "0.4".to_string(), // Track major.minor for compatibility
290 fips205_version: "0.4".to_string(), // Track major.minor for compatibility
291 bincode_version: "2.0".to_string(), // Major version for compatibility tracking
292 serde_version: "1.0".to_string(), // Major version for compatibility tracking
293 },
294 }
295}
296
297/// Information about the library capabilities
298#[derive(Debug, Clone, PartialEq, Eq)]
299pub struct LibraryInfo {
300 /// Library version
301 pub version: String,
302 /// Supported ML-KEM parameter sets
303 pub supported_ml_kem: Vec<String>,
304 /// Supported ML-DSA parameter sets
305 pub supported_ml_dsa: Vec<String>,
306 /// Enabled features
307 pub features: Vec<String>,
308 /// Default security level
309 pub security_level: String,
310 /// API compatibility information
311 pub api_version: ApiCompatibilityInfo,
312 /// Core dependency versions for compatibility tracking
313 pub dependencies: DependencyVersionInfo,
314}
315
316/// API compatibility and version tracking information
317#[derive(Debug, Clone, PartialEq, Eq)]
318pub struct ApiCompatibilityInfo {
319 /// Current API major version
320 pub major: u32,
321 /// Current API minor version
322 pub minor: u32,
323 /// Current API patch version
324 pub patch: u32,
325 /// Minimum supported API version for backwards compatibility
326 pub min_supported_version: String,
327 /// API stability level
328 pub stability: String,
329}
330
331/// Core dependency versions for backwards compatibility tracking
332#[derive(Debug, Clone, PartialEq, Eq)]
333pub struct DependencyVersionInfo {
334 /// FIPS 203 (ML-KEM) crate version
335 pub fips203_version: String,
336 /// FIPS 204 (ML-DSA) crate version
337 pub fips204_version: String,
338 /// FIPS 205 (SLH-DSA) crate version
339 pub fips205_version: String,
340 /// Bincode version for serialization compatibility
341 pub bincode_version: String,
342 /// Serde version for serialization compatibility
343 pub serde_version: String,
344}
345
346impl ApiCompatibilityInfo {
347 /// Check if this API version is compatible with a minimum required version
348 #[must_use]
349 pub fn is_compatible_with(&self, min_version: &str) -> bool {
350 use std::cmp::Ordering;
351 // Parse the minimum version string
352 let min_parts: Vec<&str> = min_version.split('.').collect();
353 if min_parts.len() < 3 {
354 return false;
355 }
356
357 let Ok(min_major) = min_parts.first().unwrap_or(&"0").parse::<u32>() else {
358 return false;
359 };
360 let Ok(min_minor) = min_parts.get(1).unwrap_or(&"0").parse::<u32>() else {
361 return false;
362 };
363 let Ok(min_patch) = min_parts.get(2).unwrap_or(&"0").parse::<u32>() else {
364 return false;
365 };
366
367 // Check compatibility using semantic versioning rules
368 match self.major.cmp(&min_major) {
369 Ordering::Greater => true,
370 Ordering::Equal => match self.minor.cmp(&min_minor) {
371 Ordering::Greater => true,
372 Ordering::Equal => self.patch >= min_patch,
373 Ordering::Less => false,
374 },
375 Ordering::Less => false,
376 }
377 }
378
379 /// Get the full version string
380 #[must_use]
381 pub fn version_string(&self) -> String {
382 format!("{}.{}.{}", self.major, self.minor, self.patch)
383 }
384}
385
386/// Check if the current library version supports backward compatibility with a specific version
387#[must_use]
388pub fn is_compatible_with_version(required_version: &str) -> bool {
389 get_info().api_version.is_compatible_with(required_version)
390}
391
392/// Get the list of enabled features
393fn get_enabled_features() -> Vec<String> {
394 #[allow(unused_mut)]
395 let mut features: Vec<String> = vec![
396 // Core features always enabled
397 "pqc".to_string(),
398 "parallel".to_string(),
399 "memory-pool".to_string(),
400 "secure-memory".to_string(),
401 "constant-time".to_string(),
402 "hpke-support".to_string(),
403 "extended-crypto".to_string(),
404 ];
405
406 #[cfg(feature = "simd")]
407 {
408 features.push("simd".to_string());
409 }
410
411 #[cfg(feature = "cert_compression")]
412 {
413 features.push("cert_compression".to_string());
414 }
415
416 #[cfg(feature = "dangerous_configuration")]
417 {
418 features.push("dangerous_configuration".to_string());
419 }
420
421 features
422}
423
424#[cfg(test)]
425#[allow(clippy::unwrap_used, clippy::expect_used)]
426mod tests {
427 use super::*;
428
429 #[test]
430 fn test_library_init() {
431 let result = init();
432 assert!(result.is_ok(), "Library initialization should succeed");
433 }
434
435 #[test]
436 fn test_get_info() {
437 let info = get_info();
438 assert_eq!(info.version, VERSION);
439 assert!(info.supported_ml_kem.contains(&"ML-KEM-768".to_string()));
440 assert!(info.supported_ml_dsa.contains(&"ML-DSA-65".to_string()));
441 assert!(!info.features.is_empty());
442
443 // Test new version tracking fields
444 assert_eq!(info.api_version.stability, "stable");
445 assert_eq!(info.api_version.min_supported_version, "0.3.0");
446 assert!(!info.dependencies.fips203_version.is_empty());
447 assert!(!info.dependencies.fips204_version.is_empty());
448 assert!(!info.dependencies.fips205_version.is_empty());
449 }
450
451 #[test]
452 fn test_version_compatibility() {
453 let info = get_info();
454
455 // Test compatibility with older versions
456 assert!(info.api_version.is_compatible_with("0.3.0"));
457 assert!(info.api_version.is_compatible_with("0.3.1"));
458
459 // Test compatibility with current version
460 assert!(info
461 .api_version
462 .is_compatible_with(&info.api_version.version_string()));
463
464 // Test public API function
465 assert!(is_compatible_with_version("0.3.0"));
466
467 // Test invalid version string handling
468 assert!(!info.api_version.is_compatible_with("invalid"));
469 assert!(!info.api_version.is_compatible_with("1.0"));
470 }
471
472 #[test]
473 fn test_enabled_features() {
474 let features = get_enabled_features();
475 assert!(
476 !features.is_empty(),
477 "Should have at least one feature enabled"
478 );
479 }
480
481 #[test]
482 #[allow(clippy::const_is_empty)]
483 fn test_constants() {
484 assert!(!SUPPORTED_ML_KEM.is_empty());
485 assert!(!SUPPORTED_ML_DSA.is_empty());
486 assert!(!DEFAULT_SECURITY_LEVEL.is_empty());
487 assert!(!VERSION.is_empty());
488 }
489}