1#[cfg(feature = "wasm")]
7extern crate alloc;
8#[cfg(feature = "wasm")]
9use alloc::{
10 string::{
11 String,
12 ToString,
13 },
14 vec::Vec,
15};
16
17#[cfg(feature = "wasm")]
18use serde_json;
20#[cfg(feature = "wasm")]
21use wasm_bindgen::prelude::*;
22
23use crate::api::{
24 Algorithm,
25 AlgorithmCategory,
26 CryptoProvider,
27};
28use crate::providers::LibQCryptoProvider;
30use crate::security::SecurityValidator;
31
32#[cfg_attr(feature = "wasm", wasm_bindgen)]
40pub struct WasmProviderManager {
41 provider: LibQCryptoProvider,
42 security_validator: SecurityValidator,
43}
44
45impl WasmProviderManager {
46 pub fn new() -> WasmProviderManager {
48 WasmProviderManager {
49 provider: LibQCryptoProvider::new()
50 .unwrap_or_else(|_| LibQCryptoProvider::new().unwrap()),
51 security_validator: SecurityValidator::new()
52 .unwrap_or_else(|_| SecurityValidator::new().unwrap()),
53 }
54 }
55}
56
57impl Default for WasmProviderManager {
58 fn default() -> Self {
59 Self::new()
60 }
61}
62
63impl WasmProviderManager {
64 pub fn get_provider_info(&self) -> String {
66 #[cfg(feature = "wasm")]
67 {
68 serde_json::json!({
69 "name": "lib-Q Crypto Provider",
70 "version": crate::VERSION,
71 "description": "Post-Quantum Cryptography Provider",
72 "features": {
73 "kem": true,
74 "signature": true,
75 "hash": true,
76 "aead": true,
77 "security_hardened": true,
78 "post_quantum": true
79 },
80 "security_levels": [128, 192, 256],
81 "algorithms": {
82 "kem": self.get_kem_algorithms(),
83 "signature": self.get_signature_algorithms(),
84 "hash": self.get_hash_algorithms(),
85 "aead": self.get_aead_algorithms()
86 }
87 })
88 .to_string()
89 }
90 #[cfg(not(feature = "wasm"))]
91 {
92 "{}".to_string()
93 }
94 }
95
96 pub fn is_algorithm_supported(&self, algorithm: &str) -> bool {
98 let algorithm = match self.parse_algorithm(algorithm) {
100 Ok(alg) => alg,
101 Err(_) => return false,
102 };
103
104 match algorithm.category() {
106 AlgorithmCategory::Kem => self.provider.kem().is_some(),
107 AlgorithmCategory::Signature => self.provider.signature().is_some(),
108 AlgorithmCategory::Hash => self.provider.hash().is_some(),
109 AlgorithmCategory::Aead => self.provider.aead().is_some(),
110 AlgorithmCategory::PrivacyProtocol => false,
111 }
112 }
113
114 pub fn get_algorithm_info(&self, algorithm: &str) -> Result<JsValue, JsValue> {
116 let algorithm = self.parse_algorithm(algorithm)?;
117
118 #[cfg(feature = "wasm")]
119 {
120 let info = serde_json::json!({
121 "name": algorithm.to_string(),
122 "category": algorithm.category().to_string(),
123 "security_level": 256, "key_sizes": {
125 "public_key": 1024, "secret_key": 1024, "signature": 1024, "nonce": 12, "key": 32 },
131 "message_limits": {
132 "max_size": 1024 * 1024 },
134 "features": {
135 "kem": algorithm.category() == AlgorithmCategory::Kem,
136 "signature": algorithm.category() == AlgorithmCategory::Signature,
137 "hash": algorithm.category() == AlgorithmCategory::Hash,
138 "aead": algorithm.category() == AlgorithmCategory::Aead,
139 "privacy_protocol": algorithm.category() == AlgorithmCategory::PrivacyProtocol
140 }
141 });
142
143 match serde_wasm_bindgen::to_value(&info) {
144 Ok(value) => Ok(value),
145 Err(_) => Err(JsValue::from_str("Serialization error")),
146 }
147 }
148 #[cfg(not(feature = "wasm"))]
149 {
150 Err(JsValue::from_str("WASM feature not enabled"))
151 }
152 }
153
154 pub fn get_all_algorithms(&self) -> String {
156 #[cfg(feature = "wasm")]
157 {
158 let algorithms = serde_json::json!({
159 "kem": self.get_kem_algorithms(),
160 "signature": self.get_signature_algorithms(),
161 "hash": self.get_hash_algorithms(),
162 "aead": self.get_aead_algorithms()
163 });
164 algorithms.to_string()
165 }
166 #[cfg(not(feature = "wasm"))]
167 {
168 "{}".to_string()
169 }
170 }
171
172 pub fn get_kem_algorithms(&self) -> Vec<String> {
174 #[allow(unused_mut)] let mut algorithms = alloc::vec![
176 "ml-kem-512".to_string(),
177 "ml-kem-768".to_string(),
178 "ml-kem-1024".to_string(),
179 ];
180
181 algorithms
182 }
183
184 pub fn get_signature_algorithms(&self) -> Vec<String> {
186 crate::wasm::conversions::WASM_SIGNATURE_ALGORITHM_IDS
187 .iter()
188 .map(|s| (*s).to_string())
189 .collect()
190 }
191
192 pub fn get_hash_algorithms(&self) -> Vec<String> {
194 alloc::vec![
195 "sha3-224".to_string(),
196 "sha3-256".to_string(),
197 "sha3-384".to_string(),
198 "sha3-512".to_string(),
199 "shake128".to_string(),
200 "shake256".to_string(),
201 ]
202 }
203
204 pub fn get_aead_algorithms(&self) -> Vec<String> {
206 let algorithms = alloc::vec!["saturnin".to_string(), "shake256-aead".to_string(),];
207
208 algorithms
209 }
210
211 pub fn validate_algorithm_params(
213 &self,
214 algorithm: &str,
215 key_size: Option<usize>,
216 message_size: Option<usize>,
217 nonce_size: Option<usize>,
218 ) -> Result<bool, JsValue> {
219 let algorithm = self.parse_algorithm(algorithm)?;
220
221 if let Some(size) = key_size {
223 if size == 0 {
224 return Err(JsValue::from_str("Invalid algorithm key: empty key"));
225 }
226 let test_key = (0..size).map(|_| 0u8).collect::<Vec<u8>>();
228 self.security_validator
229 .validate_key_size(algorithm, &test_key, true)
230 .map_err(crate::wasm::error::error_to_js_value)?;
231 }
232
233 if let Some(size) = message_size {
234 if size == 0 {
235 return Err(JsValue::from_str("Invalid message size: empty data"));
236 }
237 let test_message = (0..size).map(|_| 0u8).collect::<Vec<u8>>();
239 if algorithm.supports_category(AlgorithmCategory::Aead) {
240 self.security_validator
241 .validate_aead_message(&test_message)
242 .map_err(crate::wasm::error::error_to_js_value)?;
243 } else {
244 self.security_validator
245 .validate_hash_input(&test_message)
246 .map_err(crate::wasm::error::error_to_js_value)?;
247 }
248 }
249
250 if let Some(size) = nonce_size {
251 if size == 0 {
252 return Err(JsValue::from_str("Invalid nonce size: empty nonce"));
253 }
254 let test_nonce = (0..size).map(|_| 0u8).collect::<Vec<u8>>();
256 self.security_validator
257 .validate_nonce(&test_nonce)
258 .map_err(crate::wasm::error::error_to_js_value)?;
259 }
260
261 Ok(true)
262 }
263
264 pub fn get_security_recommendations(&self) -> String {
266 #[cfg(feature = "wasm")]
267 {
268 serde_json::json!({
269 "general": {
270 "use_authenticated_encryption": true,
271 "validate_all_inputs": true,
272 "use_secure_random": true,
273 "protect_secret_keys": true,
274 "rotate_keys_regularly": true
275 },
276 "kem": {
277 "recommended_algorithms": ["ml-kem-768", "ml-kem-1024"],
278 "key_rotation": "Every 90 days",
279 "security_level": "Minimum 192-bit"
280 },
281 "signature": {
282 "recommended_algorithms": ["ml-dsa-65", "ml-dsa-87"],
283 "key_rotation": "Every 90 days",
284 "security_level": "Minimum 192-bit"
285 },
286 "hash": {
287 "recommended_algorithms": ["sha3-256", "sha3-384"],
288 "security_level": "Minimum 256-bit"
289 },
290 "aead": {
291 "recommended_algorithms": ["saturnin", "shake256-aead"],
292 "nonce_requirements": "Unique per key",
293 "security_level": "Minimum 256-bit"
294 }
295 })
296 .to_string()
297 }
298 #[cfg(not(feature = "wasm"))]
299 {
300 "{}".to_string()
301 }
302 }
303
304 pub fn get_performance_benchmarks(&self) -> String {
306 #[cfg(feature = "wasm")]
307 {
308 serde_json::json!({
309 "note": "Performance benchmarks are environment-dependent",
310 "recommendations": {
311 "kem": {
312 "fastest": "ml-kem-512",
313 "most_secure": "ml-kem-1024",
314 "balanced": "ml-kem-768"
315 },
316 "signature": {
317 "fastest": "ml-dsa-44",
318 "most_secure": "ml-dsa-87",
319 "balanced": "ml-dsa-65"
320 },
321 "hash": {
322 "fastest": "sha3-224",
323 "most_secure": "sha3-512",
324 "balanced": "sha3-256"
325 }
326 }
327 })
328 .to_string()
329 }
330 #[cfg(not(feature = "wasm"))]
331 {
332 "{}".to_string()
333 }
334 }
335
336 fn parse_algorithm(&self, algorithm: &str) -> Result<Algorithm, crate::error::Error> {
338 crate::wasm::error::parse_algorithm_wasm(algorithm).map_err(|_| {
339 crate::error::Error::InvalidAlgorithm {
340 algorithm: "Invalid algorithm name",
341 }
342 })
343 }
344}
345
346#[cfg_attr(feature = "wasm", wasm_bindgen)]
353pub struct WasmProviderFactory;
354
355#[cfg_attr(feature = "wasm", wasm_bindgen)]
356impl WasmProviderFactory {
357 #[cfg_attr(feature = "wasm", wasm_bindgen)]
359 pub fn create_provider_manager() -> WasmProviderManager {
360 WasmProviderManager::new()
361 }
362
363 #[cfg_attr(feature = "wasm", wasm_bindgen)]
365 pub fn create_provider_manager_with_config(
366 config: &str,
367 ) -> Result<WasmProviderManager, JsValue> {
368 #[cfg(feature = "wasm")]
369 {
370 let _config: serde_json::Value = match serde_json::from_str(config) {
372 Ok(config) => config,
373 Err(_) => {
374 return Err(JsValue::from_str("Configuration parsing error"));
375 }
376 };
377
378 Ok(WasmProviderManager::new())
381 }
382 #[cfg(not(feature = "wasm"))]
383 {
384 Err(JsValue::from_str("WASM feature not enabled"))
385 }
386 }
387
388 #[cfg_attr(feature = "wasm", wasm_bindgen)]
390 pub fn get_available_providers() -> String {
391 #[cfg(feature = "wasm")]
392 {
393 serde_json::json!({
394 "providers": [
395 {
396 "name": "lib-q-crypto",
397 "description": "Default lib-Q cryptographic provider",
398 "features": ["kem", "signature", "hash", "aead"],
399 "security_levels": [128, 192, 256]
400 }
401 ]
402 })
403 .to_string()
404 }
405 #[cfg(not(feature = "wasm"))]
406 {
407 "{}".to_string()
408 }
409 }
410
411 #[cfg_attr(feature = "wasm", wasm_bindgen)]
413 pub fn validate_provider_config(config: &str) -> Result<bool, JsValue> {
414 #[cfg(feature = "wasm")]
415 {
416 let _config: serde_json::Value = match serde_json::from_str(config) {
417 Ok(config) => config,
418 Err(_) => {
419 return Err(JsValue::from_str("Configuration parsing error"));
420 }
421 };
422
423 Ok(true)
425 }
426 #[cfg(not(feature = "wasm"))]
427 {
428 Err(JsValue::from_str("WASM feature not enabled"))
429 }
430 }
431}
432
433#[cfg(test)]
434mod tests {
435
436 #[test]
437 #[cfg(target_arch = "wasm32")]
438 fn test_wasm_provider_manager_creation() {
439 let manager = WasmProviderManager::new();
440 let info = manager.get_provider_info();
441 assert!(info.contains("lib-Q") || info == "{}");
442 }
443
444 #[test]
445 #[cfg(target_arch = "wasm32")]
446 fn test_wasm_provider_factory() {
447 let manager = WasmProviderFactory::create_provider_manager();
448 assert!(manager.is_algorithm_supported("sha3-256"));
449 }
450
451 #[test]
452 #[cfg(target_arch = "wasm32")]
453 fn test_algorithm_support() {
454 let manager = WasmProviderManager::new();
455 assert!(manager.is_algorithm_supported("sha3-256"));
456 assert!(!manager.is_algorithm_supported("invalid-algorithm"));
457 }
458
459 #[test]
460 #[cfg(target_arch = "wasm32")]
461 fn test_algorithm_info() {
462 let manager = WasmProviderManager::new();
463 let info = manager.get_algorithm_info("sha3-256");
464 assert!(info.is_ok());
465 }
466
467 #[test]
468 #[cfg(target_arch = "wasm32")]
469 fn test_security_recommendations() {
470 let manager = WasmProviderManager::new();
471 let recommendations = manager.get_security_recommendations();
472 assert!(
473 recommendations.contains("use_authenticated_encryption") || recommendations == "{}"
474 );
475 }
476}