libq/
lib.rs

1//! lib-Q - Post-Quantum Cryptography Library
2//!
3//! A modern, secure cryptography library built exclusively with NIST-approved
4//! post-quantum algorithms. Written in Rust with WASM compilation support.
5
6#![cfg_attr(not(feature = "std"), no_std)]
7
8// Core modules
9pub mod aead;
10pub mod error;
11pub mod hash;
12pub mod kem;
13pub mod sig;
14pub mod utils;
15pub mod zkp;
16
17// Re-exports for convenience
18pub use aead::{Aead, AeadKey, Nonce};
19pub use error::{Error, Result};
20pub use hash::{Hash, HashAlgorithm};
21pub use kem::{Kem, KemKeypair, KemPublicKey, KemSecretKey};
22pub use sig::{SigKeypair, SigPublicKey, SigSecretKey, Signature};
23
24// Constants
25pub const VERSION: &str = env!("CARGO_PKG_VERSION");
26
27/// Initialize the library
28pub fn init() -> Result<()> {
29    Ok(())
30}
31
32/// Get library version information
33pub fn version() -> &'static str {
34    VERSION
35}
36
37// WASM API Module
38#[cfg(feature = "wasm")]
39pub mod wasm_api {
40    use super::*;
41    use js_sys::{Array, Object, Uint8Array};
42    use std::result::Result as StdResult;
43    use wasm_bindgen::prelude::*;
44    use web_sys::console;
45
46    /// WASM-compatible key pair for KEM operations
47    #[wasm_bindgen]
48    pub struct KemKeyPairWasm {
49        public_key: Uint8Array,
50        secret_key: Uint8Array,
51    }
52
53    #[wasm_bindgen]
54    impl KemKeyPairWasm {
55        #[wasm_bindgen(constructor)]
56        pub fn new(public_key: Uint8Array, secret_key: Uint8Array) -> Self {
57            Self {
58                public_key,
59                secret_key,
60            }
61        }
62
63        #[wasm_bindgen(getter)]
64        pub fn public_key(&self) -> Uint8Array {
65            self.public_key.clone()
66        }
67
68        #[wasm_bindgen(getter)]
69        pub fn secret_key(&self) -> Uint8Array {
70            self.secret_key.clone()
71        }
72    }
73
74    /// WASM-compatible key pair for signature operations
75    #[wasm_bindgen]
76    pub struct SigKeyPairWasm {
77        public_key: Uint8Array,
78        secret_key: Uint8Array,
79    }
80
81    #[wasm_bindgen]
82    impl SigKeyPairWasm {
83        #[wasm_bindgen(constructor)]
84        pub fn new(public_key: Uint8Array, secret_key: Uint8Array) -> Self {
85            Self {
86                public_key,
87                secret_key,
88            }
89        }
90
91        #[wasm_bindgen(getter)]
92        pub fn public_key(&self) -> Uint8Array {
93            self.public_key.clone()
94        }
95
96        #[wasm_bindgen(getter)]
97        pub fn secret_key(&self) -> Uint8Array {
98            self.secret_key.clone()
99        }
100    }
101
102    /// WASM-compatible hash result
103    #[wasm_bindgen]
104    pub struct HashResultWasm {
105        hash: Uint8Array,
106        algorithm: String,
107    }
108
109    #[wasm_bindgen]
110    impl HashResultWasm {
111        #[wasm_bindgen(constructor)]
112        pub fn new(hash: Uint8Array, algorithm: String) -> Self {
113            Self { hash, algorithm }
114        }
115
116        #[wasm_bindgen(getter)]
117        pub fn hash(&self) -> Uint8Array {
118            self.hash.clone()
119        }
120
121        #[wasm_bindgen(getter)]
122        pub fn algorithm(&self) -> String {
123            self.algorithm.clone()
124        }
125    }
126
127    /// Main WASM API for lib-Q
128    #[wasm_bindgen]
129    pub struct LibQ {
130        initialized: bool,
131    }
132
133    #[wasm_bindgen]
134    impl LibQ {
135        /// Create a new LibQ instance
136        #[wasm_bindgen(constructor)]
137        pub fn new() -> LibQ {
138            let mut libq = LibQ { initialized: false };
139            let _ = libq.init();
140            libq
141        }
142    }
143
144    impl Default for LibQ {
145        fn default() -> Self {
146            Self::new()
147        }
148    }
149
150    #[wasm_bindgen]
151    impl LibQ {
152        /// Initialize the library
153        pub fn init(&mut self) -> StdResult<(), JsValue> {
154            if self.initialized {
155                return Ok(());
156            }
157
158            match super::init() {
159                Ok(()) => {
160                    self.initialized = true;
161                    console::log_1(&"lib-Q initialized successfully".into());
162                    Ok(())
163                }
164                Err(_) => Err(JsValue::from_str("Failed to initialize lib-Q")),
165            }
166        }
167
168        /// Get library version
169        pub fn version(&self) -> String {
170            super::version().to_string()
171        }
172
173        /// Generate random bytes
174        pub fn random_bytes(&self, length: usize) -> StdResult<Uint8Array, JsValue> {
175            if !self.initialized {
176                return Err(JsValue::from_str("Library not initialized"));
177            }
178
179            match utils::random_bytes(length) {
180                Ok(bytes) => Ok(Uint8Array::from(&bytes[..])),
181                Err(_) => Err(JsValue::from_str("Failed to generate random bytes")),
182            }
183        }
184
185        /// Generate a random key
186        pub fn random_key(&self, size: usize) -> StdResult<Uint8Array, JsValue> {
187            if !self.initialized {
188                return Err(JsValue::from_str("Library not initialized"));
189            }
190
191            match utils::random_key(size) {
192                Ok(key) => Ok(Uint8Array::from(&key[..])),
193                Err(_) => Err(JsValue::from_str("Failed to generate random key")),
194            }
195        }
196
197        /// Convert bytes to hex string
198        pub fn bytes_to_hex(&self, bytes: &Uint8Array) -> String {
199            let bytes_vec: Vec<u8> = bytes.to_vec();
200            utils::bytes_to_hex(&bytes_vec)
201        }
202
203        /// Convert hex string to bytes
204        pub fn hex_to_bytes(&self, hex: &str) -> StdResult<Uint8Array, JsValue> {
205            match utils::hex_to_bytes(hex) {
206                Ok(bytes) => Ok(Uint8Array::from(&bytes[..])),
207                Err(_) => Err(JsValue::from_str("Failed to convert hex to bytes")),
208            }
209        }
210
211        /// Hash data using SHAKE256
212        pub fn hash_shake256(&self, data: &Uint8Array) -> StdResult<HashResultWasm, JsValue> {
213            if !self.initialized {
214                return Err(JsValue::from_str("Library not initialized"));
215            }
216
217            let data_vec: Vec<u8> = data.to_vec();
218            let hash_impl = HashAlgorithm::Shake256.create_hash();
219            match hash_impl.hash(&data_vec) {
220                Ok(hash) => Ok(HashResultWasm::new(
221                    Uint8Array::from(&hash[..]),
222                    "SHAKE256".to_string(),
223                )),
224                Err(_) => Err(JsValue::from_str("Failed to hash data")),
225            }
226        }
227
228        /// Generate KEM key pair (placeholder implementation)
229        pub fn kem_generate_keypair(
230            &self,
231            algorithm: &str,
232            security_level: u32,
233        ) -> StdResult<KemKeyPairWasm, JsValue> {
234            if !self.initialized {
235                return Err(JsValue::from_str("Library not initialized"));
236            }
237
238            // Simple validation
239            if ![1, 3, 4, 5].contains(&security_level) {
240                return Err(JsValue::from_str("Invalid security level"));
241            }
242
243            // Placeholder implementation - will be replaced with actual algorithms
244            let public_key_size = match algorithm {
245                "kyber" => 800,
246                "mceliece" => 261120,
247                "hqc" => 2241,
248                _ => return Err(JsValue::from_str("Unsupported algorithm")),
249            };
250
251            match utils::random_bytes(public_key_size) {
252                Ok(public_key) => match utils::random_bytes(public_key_size) {
253                    Ok(secret_key) => Ok(KemKeyPairWasm::new(
254                        Uint8Array::from(&public_key[..]),
255                        Uint8Array::from(&secret_key[..]),
256                    )),
257                    Err(_) => Err(JsValue::from_str("Failed to generate secret key")),
258                },
259                Err(_) => Err(JsValue::from_str("Failed to generate public key")),
260            }
261        }
262
263        /// Generate signature key pair (placeholder implementation)
264        pub fn sig_generate_keypair(
265            &self,
266            algorithm: &str,
267            security_level: u32,
268        ) -> StdResult<SigKeyPairWasm, JsValue> {
269            if !self.initialized {
270                return Err(JsValue::from_str("Library not initialized"));
271            }
272
273            // Simple validation
274            if ![1, 3, 4, 5].contains(&security_level) {
275                return Err(JsValue::from_str("Invalid security level"));
276            }
277
278            // Placeholder implementation - will be replaced with actual algorithms
279            let public_key_size = match algorithm {
280                "dilithium" => 1312,
281                "falcon" => 897,
282                "sphincs" => 32,
283                _ => return Err(JsValue::from_str("Unsupported algorithm")),
284            };
285
286            match utils::random_bytes(public_key_size) {
287                Ok(public_key) => match utils::random_bytes(public_key_size) {
288                    Ok(secret_key) => Ok(SigKeyPairWasm::new(
289                        Uint8Array::from(&public_key[..]),
290                        Uint8Array::from(&secret_key[..]),
291                    )),
292                    Err(_) => Err(JsValue::from_str("Failed to generate secret key")),
293                },
294                Err(_) => Err(JsValue::from_str("Failed to generate public key")),
295            }
296        }
297
298        /// Get supported algorithms
299        pub fn get_supported_algorithms(&self) -> Object {
300            let algorithms = Object::new();
301
302            // KEM algorithms
303            let kem_algorithms = Array::new();
304            kem_algorithms.push(&"kyber".into());
305            kem_algorithms.push(&"mceliece".into());
306            kem_algorithms.push(&"hqc".into());
307            let _ = js_sys::Reflect::set(&algorithms, &"kem".into(), &kem_algorithms);
308
309            // Signature algorithms
310            let sig_algorithms = Array::new();
311            sig_algorithms.push(&"dilithium".into());
312            sig_algorithms.push(&"falcon".into());
313            sig_algorithms.push(&"sphincs".into());
314            let _ = js_sys::Reflect::set(&algorithms, &"signature".into(), &sig_algorithms);
315
316            // Hash algorithms
317            let hash_algorithms = Array::new();
318            hash_algorithms.push(&"shake256".into());
319            hash_algorithms.push(&"shake128".into());
320            hash_algorithms.push(&"cshake256".into());
321            let _ = js_sys::Reflect::set(&algorithms, &"hash".into(), &hash_algorithms);
322
323            // Security levels
324            let security_levels = Array::new();
325            security_levels.push(&1u32.into());
326            security_levels.push(&3u32.into());
327            security_levels.push(&4u32.into());
328            security_levels.push(&5u32.into());
329            let _ = js_sys::Reflect::set(&algorithms, &"securityLevels".into(), &security_levels);
330
331            algorithms
332        }
333    }
334
335    // Standalone functions for convenience
336    #[wasm_bindgen]
337    pub fn libq_version_standalone() -> String {
338        super::version().to_string()
339    }
340
341    #[wasm_bindgen]
342    pub fn libq_init_standalone() -> StdResult<(), JsValue> {
343        match super::init() {
344            Ok(()) => Ok(()),
345            Err(_) => Err(JsValue::from_str("Failed to initialize lib-Q")),
346        }
347    }
348
349    #[wasm_bindgen]
350    pub fn libq_random_bytes_standalone(length: usize) -> StdResult<Uint8Array, JsValue> {
351        match utils::random_bytes(length) {
352            Ok(bytes) => Ok(Uint8Array::from(&bytes[..])),
353            Err(_) => Err(JsValue::from_str("Failed to generate random bytes")),
354        }
355    }
356
357    #[wasm_bindgen]
358    pub fn libq_bytes_to_hex_standalone(bytes: &Uint8Array) -> String {
359        let bytes_vec: Vec<u8> = bytes.to_vec();
360        utils::bytes_to_hex(&bytes_vec)
361    }
362
363    #[wasm_bindgen]
364    pub fn libq_hex_to_bytes_standalone(hex: &str) -> StdResult<Uint8Array, JsValue> {
365        match utils::hex_to_bytes(hex) {
366            Ok(bytes) => Ok(Uint8Array::from(&bytes[..])),
367            Err(_) => Err(JsValue::from_str("Failed to convert hex to bytes")),
368        }
369    }
370}
371
372#[cfg(test)]
373mod tests {
374    use super::*;
375
376    #[test]
377    fn test_init() {
378        assert!(init().is_ok());
379    }
380
381    #[test]
382    fn test_version() {
383        assert!(!version().is_empty());
384        assert_eq!(version(), VERSION);
385    }
386}