1#![cfg_attr(not(feature = "std"), no_std)]
7
8pub mod aead;
10pub mod error;
11pub mod hash;
12pub mod kem;
13pub mod sig;
14pub mod utils;
15pub mod zkp;
16
17pub 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
24pub const VERSION: &str = env!("CARGO_PKG_VERSION");
26
27pub fn init() -> Result<()> {
29 Ok(())
30}
31
32pub fn version() -> &'static str {
34 VERSION
35}
36
37#[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_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_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_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 #[wasm_bindgen]
129 pub struct LibQ {
130 initialized: bool,
131 }
132
133 #[wasm_bindgen]
134 impl LibQ {
135 #[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 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 pub fn version(&self) -> String {
170 super::version().to_string()
171 }
172
173 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 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 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 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 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 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 if ![1, 3, 4, 5].contains(&security_level) {
240 return Err(JsValue::from_str("Invalid security level"));
241 }
242
243 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 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 if ![1, 3, 4, 5].contains(&security_level) {
275 return Err(JsValue::from_str("Invalid security level"));
276 }
277
278 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 pub fn get_supported_algorithms(&self) -> Object {
300 let algorithms = Object::new();
301
302 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 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 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 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 #[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}