1#[cfg(feature = "wasm")]
7extern crate alloc;
8#[cfg(feature = "wasm")]
9use alloc::{
10 boxed::Box,
11 format,
12 string::{
13 String,
14 ToString,
15 },
16 vec::Vec,
17};
18
19#[cfg(feature = "wasm")]
20use js_sys::Uint8Array;
21#[cfg(feature = "wasm")]
22use serde_json;
23#[cfg(feature = "wasm")]
24use serde_wasm_bindgen;
25#[cfg(feature = "wasm")]
26use wasm_bindgen::prelude::*;
27
28use crate::api::{
29 Algorithm,
30 AlgorithmCategory,
31};
32use crate::contexts::{
33 AeadContext,
34 HashContext,
35 KemContext,
36 SignatureContext,
37};
38use crate::providers::LibQCryptoProvider;
40use crate::security::SecurityValidator;
41use crate::traits::{
42 AeadKey,
43 Nonce,
44};
45use crate::wasm::conversions::WASM_SIGNATURE_ALGORITHM_IDS;
47use crate::wasm::error::{
48 convert_result,
49 error_to_js_value,
50 parse_algorithm_wasm,
51 };
53
54#[cfg_attr(feature = "wasm", wasm_bindgen)]
62pub struct WasmKemContext {
63 inner: KemContext,
64 security_validator: SecurityValidator,
65}
66
67impl WasmKemContext {
68 pub fn new() -> WasmKemContext {
70 WasmKemContext {
71 inner: KemContext::with_default_provider(),
72 security_validator: SecurityValidator::new()
73 .unwrap_or_else(|_| SecurityValidator::new().unwrap()),
74 }
75 }
76
77 pub fn with_provider(provider: &WasmCryptoProvider) -> WasmKemContext {
79 WasmKemContext {
80 inner: KemContext::with_provider(Box::new(provider.inner.clone())),
81 security_validator: SecurityValidator::new()
82 .unwrap_or_else(|_| SecurityValidator::new().unwrap()),
83 }
84 }
85}
86
87impl Default for WasmKemContext {
88 fn default() -> Self {
89 Self::new()
90 }
91}
92
93impl WasmKemContext {
94 pub fn generate_keypair(
102 &mut self,
103 algorithm: &str,
104 randomness: Option<Uint8Array>,
105 ) -> Result<JsValue, JsValue> {
106 let algorithm = self
108 .parse_kem_algorithm(algorithm)
109 .map_err(error_to_js_value)?;
110
111 convert_result(
113 self.security_validator
114 .validate_algorithm_category(algorithm, algorithm.category()),
115 )?;
116
117 let randomness_vec = randomness.map(|rand| rand.to_vec());
119 let randomness_bytes = randomness_vec.as_deref();
120
121 let keypair = self
123 .inner
124 .generate_keypair(algorithm, randomness_bytes)
125 .map_err(error_to_js_value)?;
126
127 #[cfg(feature = "wasm")]
129 {
130 let result = serde_json::json!({
131 "public_key": keypair.public_key.data,
132 "secret_key": keypair.secret_key.data,
133 "algorithm": algorithm.to_string(),
134 "security_level": 256 });
136
137 serde_wasm_bindgen::to_value(&result)
138 .map_err(|e| JsValue::from_str(&format!("Serialization error: {:?}", e)))
139 }
140 #[cfg(not(feature = "wasm"))]
141 {
142 Err(JsValue::from_str("WASM feature not enabled"))
143 }
144 }
145
146 pub fn encapsulate(
154 &self,
155 algorithm: &str,
156 public_key_data: &Uint8Array,
157 randomness: Option<Uint8Array>,
158 ) -> Result<JsValue, JsValue> {
159 let algorithm = self
161 .parse_kem_algorithm(algorithm)
162 .map_err(error_to_js_value)?;
163
164 if public_key_data.length() == 0 {
166 return Err(JsValue::from_str("Invalid KEM public key: empty key"));
167 }
168
169 let randomness_vec = randomness.map(|rand| rand.to_vec());
171 let randomness_bytes = randomness_vec.as_deref();
172
173 let public_key = crate::traits::KemPublicKey::new(public_key_data.to_vec());
175
176 let (ciphertext, shared_secret) = self
178 .inner
179 .encapsulate(algorithm, &public_key, randomness_bytes)
180 .map_err(error_to_js_value)?;
181
182 #[cfg(feature = "wasm")]
184 {
185 let result = serde_json::json!({
186 "ciphertext": ciphertext,
187 "shared_secret": shared_secret,
188 "algorithm": algorithm.to_string(),
189 "security_level": 256 });
191
192 serde_wasm_bindgen::to_value(&result)
193 .map_err(|e| JsValue::from_str(&format!("Serialization error: {:?}", e)))
194 }
195 #[cfg(not(feature = "wasm"))]
196 {
197 Err(JsValue::from_str("WASM feature not enabled"))
198 }
199 }
200
201 pub fn decapsulate(
209 &self,
210 algorithm: &str,
211 secret_key_data: &Uint8Array,
212 ciphertext: &Uint8Array,
213 ) -> Result<Vec<u8>, JsValue> {
214 let algorithm = self
216 .parse_kem_algorithm(algorithm)
217 .map_err(error_to_js_value)?;
218
219 self.security_validator
221 .validate_algorithm_category(algorithm, AlgorithmCategory::Kem)
222 .map_err(error_to_js_value)?;
223
224 if secret_key_data.length() == 0 {
226 return Err(JsValue::from_str("Invalid KEM secret key: empty key"));
227 }
228
229 if ciphertext.length() == 0 {
231 return Err(JsValue::from_str("Invalid message size: empty data"));
232 }
233
234 let secret_key = crate::traits::KemSecretKey::new(secret_key_data.to_vec());
236
237 self.security_validator
239 .validate_secret_key(algorithm, secret_key.as_bytes())
240 .map_err(error_to_js_value)?;
241
242 self.security_validator
244 .validate_ciphertext(algorithm, &ciphertext.to_vec())
245 .map_err(error_to_js_value)?;
246
247 let shared_secret = self
249 .inner
250 .decapsulate(algorithm, &secret_key, &ciphertext.to_vec())
251 .map_err(error_to_js_value)?;
252
253 Ok(shared_secret)
254 }
255
256 pub fn security_level(&self) -> u32 {
258 256 }
261
262 pub fn is_algorithm_supported(&self, algorithm: &str) -> bool {
264 self.parse_kem_algorithm(algorithm).is_ok()
265 }
266
267 pub fn supported_algorithms(&self) -> String {
269 #[allow(unused_mut)] let mut algorithms = alloc::vec!["ml-kem-512", "ml-kem-768", "ml-kem-1024"];
271 #[cfg(feature = "wasm")]
272 {
273 serde_json::to_string(&algorithms).unwrap_or_else(|_| "[]".to_string())
274 }
275 #[cfg(not(feature = "wasm"))]
276 {
277 "[]".to_string()
278 }
279 }
280
281 fn parse_kem_algorithm(&self, algorithm: &str) -> Result<Algorithm, crate::error::Error> {
283 parse_algorithm_wasm(algorithm).map_err(|_| crate::error::Error::InvalidAlgorithm {
284 algorithm: "Invalid algorithm name",
285 })
286 }
287}
288
289#[cfg_attr(feature = "wasm", wasm_bindgen)]
297pub struct WasmSignatureContext {
298 inner: SignatureContext,
299 security_validator: SecurityValidator,
300}
301
302impl WasmSignatureContext {
303 pub fn new() -> WasmSignatureContext {
308 WasmSignatureContext {
309 inner: SignatureContext::with_default_provider(),
310 security_validator: SecurityValidator::new()
311 .unwrap_or_else(|_| SecurityValidator::new().unwrap()),
312 }
313 }
314
315 pub fn from_signature_context(inner: SignatureContext) -> WasmSignatureContext {
318 WasmSignatureContext {
319 inner,
320 security_validator: SecurityValidator::new()
321 .unwrap_or_else(|_| SecurityValidator::new().unwrap()),
322 }
323 }
324}
325
326impl Default for WasmSignatureContext {
327 fn default() -> Self {
328 Self::new()
329 }
330}
331
332impl WasmSignatureContext {
333 pub fn with_provider(provider: &WasmCryptoProvider) -> WasmSignatureContext {
335 WasmSignatureContext {
336 inner: SignatureContext::with_provider(Box::new(provider.inner.clone())),
337 security_validator: SecurityValidator::new()
338 .unwrap_or_else(|_| SecurityValidator::new().unwrap()),
339 }
340 }
341
342 fn parse_signature_algorithm(&self, algorithm: &str) -> Result<Algorithm, crate::error::Error> {
344 parse_algorithm_wasm(algorithm).map_err(|_| crate::error::Error::InvalidAlgorithm {
345 algorithm: "Invalid algorithm name",
346 })
347 }
348}
349
350#[cfg_attr(feature = "wasm", wasm_bindgen)]
351impl WasmSignatureContext {
352 pub fn generate_keypair(
354 &mut self,
355 algorithm: &str,
356 randomness: Option<Uint8Array>,
357 ) -> Result<JsValue, JsValue> {
358 let algorithm = self
360 .parse_signature_algorithm(algorithm)
361 .map_err(error_to_js_value)?;
362
363 convert_result(
365 self.security_validator
366 .validate_algorithm_category(algorithm, algorithm.category()),
367 )?;
368
369 let randomness_vec = randomness.map(|rand| rand.to_vec());
371 let randomness_bytes = randomness_vec.as_deref();
372
373 let keypair = self
375 .inner
376 .generate_keypair(algorithm, randomness_bytes)
377 .map_err(error_to_js_value)?;
378
379 #[cfg(feature = "wasm")]
381 {
382 let result = serde_json::json!({
383 "public_key": keypair.public_key.data,
384 "secret_key": keypair.secret_key.data,
385 "algorithm": algorithm.to_string(),
386 "security_level": 256 });
388
389 serde_wasm_bindgen::to_value(&result)
390 .map_err(|e| JsValue::from_str(&format!("Serialization error: {:?}", e)))
391 }
392 #[cfg(not(feature = "wasm"))]
393 {
394 Err(JsValue::from_str("WASM feature not enabled"))
395 }
396 }
397
398 pub fn sign(
400 &self,
401 algorithm: &str,
402 secret_key_data: &Uint8Array,
403 message: &Uint8Array,
404 randomness: Option<Uint8Array>,
405 ) -> Result<Vec<u8>, JsValue> {
406 let algorithm = self
408 .parse_signature_algorithm(algorithm)
409 .map_err(error_to_js_value)?;
410
411 if secret_key_data.length() == 0 {
413 return Err(JsValue::from_str("Invalid signature secret key: empty key"));
414 }
415
416 if message.length() == 0 {
418 return Err(JsValue::from_str("Invalid message size: empty data"));
419 }
420
421 let randomness_vec = randomness.map(|rand| rand.to_vec());
423 let randomness_bytes = randomness_vec.as_deref();
424
425 let secret_key = crate::traits::SigSecretKey::new(secret_key_data.to_vec());
427
428 let signature = self
430 .inner
431 .sign(algorithm, &secret_key, &message.to_vec(), randomness_bytes)
432 .map_err(error_to_js_value)?;
433 Ok(signature)
434 }
435
436 pub fn verify(
438 &self,
439 algorithm: &str,
440 public_key_data: &Uint8Array,
441 message: &Uint8Array,
442 signature: &Uint8Array,
443 ) -> Result<bool, JsValue> {
444 let algorithm = self
446 .parse_signature_algorithm(algorithm)
447 .map_err(error_to_js_value)?;
448
449 if public_key_data.length() == 0 {
451 return Err(JsValue::from_str("Invalid signature public key: empty key"));
452 }
453
454 if message.length() == 0 {
456 return Err(JsValue::from_str("Invalid message size: empty data"));
457 }
458
459 if signature.length() == 0 {
461 return Err(JsValue::from_str("Invalid signature: empty data"));
462 }
463
464 let public_key = crate::traits::SigPublicKey::new(public_key_data.to_vec());
466
467 let is_valid = self
469 .inner
470 .verify(
471 algorithm,
472 &public_key,
473 &message.to_vec(),
474 &signature.to_vec(),
475 )
476 .map_err(error_to_js_value)?;
477 Ok(is_valid)
478 }
479
480 pub fn security_level(&self) -> u32 {
482 256 }
484
485 pub fn is_algorithm_supported(&self, algorithm: &str) -> bool {
487 self.parse_signature_algorithm(algorithm).is_ok()
488 }
489
490 pub fn supported_algorithms(&self) -> String {
492 #[cfg(feature = "wasm")]
493 {
494 serde_json::to_string(&WASM_SIGNATURE_ALGORITHM_IDS)
495 .unwrap_or_else(|_| "[]".to_string())
496 }
497 #[cfg(not(feature = "wasm"))]
498 {
499 "[]".to_string()
500 }
501 }
502}
503
504#[cfg_attr(feature = "wasm", wasm_bindgen)]
512pub struct WasmHashContext {
513 inner: HashContext,
514 security_validator: SecurityValidator,
515}
516
517impl WasmHashContext {
518 pub fn new() -> WasmHashContext {
520 WasmHashContext {
521 inner: HashContext::with_default_provider(),
522 security_validator: SecurityValidator::new()
523 .unwrap_or_else(|_| SecurityValidator::new().unwrap()),
524 }
525 }
526
527 pub fn from_hash_context(inner: HashContext) -> WasmHashContext {
530 WasmHashContext {
531 inner,
532 security_validator: SecurityValidator::new()
533 .unwrap_or_else(|_| SecurityValidator::new().unwrap()),
534 }
535 }
536}
537
538impl Default for WasmHashContext {
539 fn default() -> Self {
540 Self::new()
541 }
542}
543
544impl WasmHashContext {
545 pub fn with_provider(provider: &WasmCryptoProvider) -> WasmHashContext {
547 WasmHashContext {
548 inner: HashContext::with_provider(Box::new(provider.inner.clone())),
549 security_validator: SecurityValidator::new()
550 .unwrap_or_else(|_| SecurityValidator::new().unwrap()),
551 }
552 }
553
554 pub fn hash(&mut self, algorithm: &str, data: &Uint8Array) -> Result<JsValue, JsValue> {
556 let algorithm = self
558 .parse_hash_algorithm(algorithm)
559 .map_err(error_to_js_value)?;
560
561 self.security_validator
563 .validate_algorithm_category(algorithm, AlgorithmCategory::Hash)
564 .map_err(error_to_js_value)?;
565
566 self.security_validator
568 .validate_hash_input(&data.to_vec())
569 .map_err(error_to_js_value)?;
570
571 let hash = self
573 .inner
574 .hash(algorithm, &data.to_vec())
575 .map_err(error_to_js_value)?;
576
577 #[cfg(feature = "wasm")]
579 {
580 let result = serde_json::json!({
581 "hash": hash,
582 "algorithm": algorithm.to_string(),
583 "security_level": 256 });
585
586 match serde_wasm_bindgen::to_value(&result) {
587 Ok(value) => Ok(value),
588 Err(e) => Err(JsValue::from_str(&format!("Serialization error: {:?}", e))),
589 }
590 }
591 #[cfg(not(feature = "wasm"))]
592 {
593 Err(JsValue::from_str("WASM feature not enabled"))
594 }
595 }
596
597 pub fn security_level(&self) -> u32 {
599 256 }
601
602 pub fn is_algorithm_supported(&self, algorithm: &str) -> bool {
604 self.parse_hash_algorithm(algorithm).is_ok()
605 }
606
607 pub fn supported_algorithms(&self) -> String {
609 let algorithms = alloc::vec![
610 "sha3-224",
611 "sha3-256",
612 "sha3-384",
613 "sha3-512",
614 "shake128",
615 "shake256",
616 "sha-224",
617 "sha-256",
618 "sha-384",
619 "sha-512",
620 "sha-512/224",
621 "sha-512/256",
622 "cshake128",
623 "cshake256",
624 "keccak-224",
625 "keccak-256",
626 "keccak-384",
627 "keccak-512",
628 "kangarootwelve",
629 "turboshake128",
630 "turboshake256",
631 "kmac128",
632 "kmac256",
633 "tuplehash128",
634 "tuplehash256",
635 "parallelhash128",
636 "parallelhash256",
637 ];
638 #[cfg(feature = "wasm")]
639 {
640 serde_json::to_string(&algorithms).unwrap_or_else(|_| "[]".to_string())
641 }
642 #[cfg(not(feature = "wasm"))]
643 {
644 "[]".to_string()
645 }
646 }
647
648 fn parse_hash_algorithm(&self, algorithm: &str) -> Result<Algorithm, crate::error::Error> {
650 parse_algorithm_wasm(algorithm).map_err(|_| crate::error::Error::InvalidAlgorithm {
651 algorithm: "Invalid algorithm name",
652 })
653 }
654}
655
656#[cfg_attr(feature = "wasm", wasm_bindgen)]
664pub struct WasmAeadContext {
665 inner: AeadContext,
666 security_validator: SecurityValidator,
667}
668
669impl WasmAeadContext {
670 pub fn new() -> WasmAeadContext {
675 WasmAeadContext {
676 inner: AeadContext::new(),
677 security_validator: SecurityValidator::new()
678 .unwrap_or_else(|_| SecurityValidator::new().unwrap()),
679 }
680 }
681
682 pub fn from_aead_context(inner: AeadContext) -> WasmAeadContext {
684 WasmAeadContext {
685 inner,
686 security_validator: SecurityValidator::new()
687 .unwrap_or_else(|_| SecurityValidator::new().unwrap()),
688 }
689 }
690}
691
692impl Default for WasmAeadContext {
693 fn default() -> Self {
694 Self::new()
695 }
696}
697
698impl WasmAeadContext {
699 pub fn with_provider(provider: &WasmCryptoProvider) -> WasmAeadContext {
701 WasmAeadContext {
702 inner: AeadContext::with_provider(Box::new(provider.inner.clone())),
703 security_validator: SecurityValidator::new()
704 .unwrap_or_else(|_| SecurityValidator::new().unwrap()),
705 }
706 }
707
708 pub fn encrypt(
710 &mut self,
711 algorithm: &str,
712 key: &Uint8Array,
713 nonce: &Uint8Array,
714 plaintext: &Uint8Array,
715 aad: Option<Uint8Array>,
716 ) -> Result<Vec<u8>, JsValue> {
717 let algorithm = self
719 .parse_aead_algorithm(algorithm)
720 .map_err(error_to_js_value)?;
721
722 self.security_validator
724 .validate_algorithm_category(algorithm, AlgorithmCategory::Aead)
725 .map_err(error_to_js_value)?;
726
727 self.security_validator
729 .validate_key_size(algorithm, &key.to_vec(), true)
730 .map_err(error_to_js_value)?;
731
732 self.security_validator
734 .validate_nonce(&nonce.to_vec())
735 .map_err(error_to_js_value)?;
736
737 self.security_validator
739 .validate_aead_message(&plaintext.to_vec())
740 .map_err(error_to_js_value)?;
741
742 let aad_bytes = aad.map(|aad_data| aad_data.to_vec());
744 if let Some(ref aad_data) = aad_bytes {
745 self.security_validator
746 .validate_aead_message(aad_data)
747 .map_err(error_to_js_value)?;
748 }
749
750 let aead_key = AeadKey::new(key.to_vec());
752 let nonce_obj = Nonce::new(nonce.to_vec());
753 let ciphertext = self
754 .inner
755 .encrypt(
756 algorithm,
757 &aead_key,
758 &nonce_obj,
759 &plaintext.to_vec(),
760 aad_bytes.as_deref(),
761 )
762 .map_err(error_to_js_value)?;
763 Ok(ciphertext)
764 }
765
766 pub fn decrypt(
773 &self,
774 algorithm: &str,
775 key: &Uint8Array,
776 nonce: &Uint8Array,
777 ciphertext: &Uint8Array,
778 aad: Option<Uint8Array>,
779 ) -> Result<Vec<u8>, JsValue> {
780 let algorithm = self
782 .parse_aead_algorithm(algorithm)
783 .map_err(error_to_js_value)?;
784
785 self.security_validator
787 .validate_algorithm_category(algorithm, AlgorithmCategory::Aead)
788 .map_err(error_to_js_value)?;
789
790 self.security_validator
792 .validate_key_size(algorithm, &key.to_vec(), true)
793 .map_err(error_to_js_value)?;
794
795 self.security_validator
797 .validate_nonce(&nonce.to_vec())
798 .map_err(error_to_js_value)?;
799
800 self.security_validator
802 .validate_ciphertext(algorithm, &ciphertext.to_vec())
803 .map_err(error_to_js_value)?;
804
805 let aad_bytes = aad.map(|aad_data| aad_data.to_vec());
807 if let Some(ref aad_data) = aad_bytes {
808 self.security_validator
809 .validate_aead_message(aad_data)
810 .map_err(error_to_js_value)?;
811 }
812
813 let aead_key = AeadKey::new(key.to_vec());
815 let nonce_obj = Nonce::new(nonce.to_vec());
816 let plaintext = self
817 .inner
818 .decrypt(
819 algorithm,
820 &aead_key,
821 &nonce_obj,
822 &ciphertext.to_vec(),
823 aad_bytes.as_deref(),
824 )
825 .map_err(error_to_js_value)?;
826 Ok(plaintext)
827 }
828
829 pub fn security_level(&self) -> u32 {
831 256 }
833
834 pub fn is_algorithm_supported(&self, algorithm: &str) -> bool {
836 self.parse_aead_algorithm(algorithm).is_ok()
837 }
838
839 pub fn supported_algorithms(&self) -> String {
841 let algorithms = alloc::vec!["saturnin", "shake256-aead"];
842 #[cfg(feature = "wasm")]
843 {
844 serde_json::to_string(&algorithms).unwrap_or_else(|_| "[]".to_string())
845 }
846 #[cfg(not(feature = "wasm"))]
847 {
848 "[]".to_string()
849 }
850 }
851
852 fn parse_aead_algorithm(&self, algorithm: &str) -> Result<Algorithm, crate::error::Error> {
854 parse_algorithm_wasm(algorithm).map_err(|_| crate::error::Error::InvalidAlgorithm {
855 algorithm: "Invalid algorithm name",
856 })
857 }
858}
859
860#[cfg_attr(feature = "wasm", wasm_bindgen)]
867pub struct WasmCryptoProvider {
868 inner: LibQCryptoProvider,
869}
870
871impl WasmCryptoProvider {
872 pub fn new() -> WasmCryptoProvider {
874 WasmCryptoProvider {
875 inner: LibQCryptoProvider::new().unwrap_or_else(|_| LibQCryptoProvider::new().unwrap()),
876 }
877 }
878}
879
880impl Default for WasmCryptoProvider {
881 fn default() -> Self {
882 Self::new()
883 }
884}
885
886impl WasmCryptoProvider {
887 pub fn info(&self) -> String {
889 #[cfg(feature = "wasm")]
890 {
891 serde_json::json!({
892 "name": "lib-Q Crypto Provider",
893 "version": crate::VERSION,
894 "features": {
895 "kem": true,
896 "signature": true,
897 "hash": true,
898 "aead": true,
899 "security_hardened": true
900 }
901 })
902 .to_string()
903 }
904 #[cfg(not(feature = "wasm"))]
905 {
906 "{}".to_string()
907 }
908 }
909
910 pub fn is_algorithm_supported(&self, _algorithm: &str) -> bool {
912 true }
915
916 pub fn supported_algorithms(&self) -> String {
918 #[cfg(feature = "wasm")]
919 {
920 #[allow(unused_mut)] let mut kem_algorithms = alloc::vec!["ml-kem-512", "ml-kem-768", "ml-kem-1024"];
922 let algorithms = serde_json::json!({
923 "kem": kem_algorithms,
924 "signature": WASM_SIGNATURE_ALGORITHM_IDS,
925 "hash": [
926 "sha3-224", "sha3-256", "sha3-384", "sha3-512", "shake128", "shake256",
927 "sha-224", "sha-256", "sha-384", "sha-512", "sha-512/224", "sha-512/256",
928 "cshake128", "cshake256", "keccak-224", "keccak-256", "keccak-384", "keccak-512",
929 "kangarootwelve", "turboshake128", "turboshake256", "kmac128", "kmac256",
930 "tuplehash128", "tuplehash256", "parallelhash128", "parallelhash256",
931 ],
932 "aead": ["saturnin", "shake256-aead"]
933 });
934 algorithms.to_string()
935 }
936 #[cfg(not(feature = "wasm"))]
937 {
938 "{}".to_string()
939 }
940 }
941}
942
943#[cfg(test)]
944mod tests {
945 use super::*;
946
947 #[test]
948 fn test_wasm_kem_context_creation() {
949 let context = WasmKemContext::new();
950 assert_eq!(context.security_level(), 256);
951 }
952
953 #[test]
954 fn test_wasm_signature_context_creation() {
955 let context = WasmSignatureContext::new();
956 assert_eq!(context.security_level(), 256);
957 }
958
959 #[test]
960 fn test_wasm_hash_context_creation() {
961 let context = WasmHashContext::new();
962 assert_eq!(context.security_level(), 256);
963 }
964
965 #[test]
966 fn test_wasm_aead_context_creation() {
967 let context = WasmAeadContext::new();
968 assert_eq!(context.security_level(), 256);
969 }
970
971 #[test]
972 fn test_wasm_crypto_provider_creation() {
973 let provider = WasmCryptoProvider::new();
974 let info = provider.info();
975 assert!(info.contains("lib-Q") || info == "{}");
976 }
977
978 #[test]
979 #[cfg(target_arch = "wasm32")]
980 fn test_wasm_kem_context_operations() {
981 let mut context = WasmKemContext::new();
982
983 let result = context.generate_keypair("ml-kem-512", None);
985 assert!(result.is_err());
986 if let Err(error) = result {
987 let error_str = error.as_string().unwrap_or_default();
988 assert!(error_str.contains("NotImplemented") || error_str.contains("WASM"));
989 }
990 }
991
992 #[test]
993 #[cfg(target_arch = "wasm32")]
994 fn test_wasm_signature_context_operations() {
995 let mut context = WasmSignatureContext::new();
996
997 let result = context.generate_keypair("ml-dsa-65", None);
999 assert!(result.is_err());
1000 if let Err(error) = result {
1001 let error_str = error.as_string().unwrap_or_default();
1002 assert!(error_str.contains("NotImplemented") || error_str.contains("WASM"));
1003 }
1004 }
1005
1006 #[test]
1007 #[cfg(target_arch = "wasm32")]
1008 fn test_wasm_hash_context_operations() {
1009 let mut context = WasmHashContext::new();
1010
1011 let data = Uint8Array::new_with_length(10);
1013 let result = context.hash("sha3-256", &data);
1014 assert!(result.is_err());
1015 if let Err(error) = result {
1016 let error_str = error.as_string().unwrap_or_default();
1017 assert!(error_str.contains("NotImplemented") || error_str.contains("WASM"));
1018 }
1019 }
1020
1021 #[test]
1022 #[cfg(target_arch = "wasm32")]
1023 fn test_wasm_aead_context_operations() {
1024 let mut context = WasmAeadContext::new();
1025
1026 let key = Uint8Array::new_with_length(32);
1028 let nonce = Uint8Array::new_with_length(16);
1029 let plaintext = Uint8Array::new_with_length(10);
1030
1031 let result = context.encrypt("saturnin", &key, &nonce, &plaintext, None);
1032 assert!(result.is_err());
1033 if let Err(error) = result {
1034 let error_str = error.as_string().unwrap_or_default();
1035 assert!(
1036 error_str.contains("Provider not configured") ||
1037 error_str.contains("NotImplemented") ||
1038 error_str.contains("WASM")
1039 );
1040 }
1041 }
1042}