1#[cfg(feature = "wasm")]
11extern crate alloc;
12#[cfg(feature = "wasm")]
13use alloc::boxed::Box;
14
15#[cfg(feature = "wasm")]
16use js_sys::Uint8Array;
17#[cfg(feature = "wasm")]
18use wasm_bindgen::prelude::*;
19
20use crate::api::{
21 AlgorithmCategory,
23};
24use crate::contexts::{
25 AeadContext,
26 HashContext,
27 KemContext,
28 SignatureContext,
29};
30use crate::providers::LibQCryptoProvider;
32use crate::security::SecurityValidator;
33use crate::traits::{
34 AeadKey,
35 Nonce,
36 };
38use crate::wasm::conversions::WASM_SIGNATURE_ALGORITHM_IDS;
39use crate::wasm::error::{
40 convert_result,
41 parse_algorithm_wasm,
43 secure_serialize,
44};
45
46#[cfg_attr(feature = "wasm", wasm_bindgen)]
54pub struct SecureWasmKemContext {
55 inner: KemContext,
56 security_validator: SecurityValidator,
57}
58
59#[cfg_attr(feature = "wasm", wasm_bindgen)]
60impl SecureWasmKemContext {
61 #[cfg_attr(feature = "wasm", wasm_bindgen(constructor))]
63 pub fn new() -> Result<SecureWasmKemContext, JsValue> {
64 let provider = Box::new(LibQCryptoProvider::new()?);
65 let inner = KemContext::with_provider(provider);
66 let security_validator = SecurityValidator::new()?;
67
68 Ok(SecureWasmKemContext {
69 inner,
70 security_validator,
71 })
72 }
73
74 pub fn generate_keypair(
76 &mut self,
77 algorithm: &str,
78 randomness: Option<Uint8Array>,
79 ) -> Result<JsValue, JsValue> {
80 let algorithm = parse_algorithm_wasm(algorithm)?;
82
83 match convert_result(
85 self.security_validator
86 .validate_algorithm_category(algorithm, AlgorithmCategory::Kem),
87 ) {
88 Ok(_) => {}
89 Err(error) => return Err(error),
90 }
91
92 let randomness_bytes = randomness.map(|rand| rand.to_vec());
94
95 let keypair = convert_result(
97 self.inner
98 .generate_keypair(algorithm, randomness_bytes.as_deref()),
99 )?;
100
101 match secure_serialize(&keypair) {
103 Ok(value) => Ok(value),
104 Err(error) => Err(error),
105 }
106 }
107
108 pub fn encapsulate(
110 &self,
111 algorithm: &str,
112 public_key: &Uint8Array,
113 randomness: Option<Uint8Array>,
114 ) -> Result<JsValue, JsValue> {
115 let algorithm = parse_algorithm_wasm(algorithm)?;
117
118 match convert_result(
120 self.security_validator
121 .validate_algorithm_category(algorithm, AlgorithmCategory::Kem),
122 ) {
123 Ok(_) => {}
124 Err(error) => return Err(error),
125 }
126
127 let public_key_bytes = public_key.to_vec();
129 let randomness_bytes = randomness.map(|rand| rand.to_vec());
130
131 match convert_result(self.security_validator.validate_key_size(
133 algorithm,
134 &public_key_bytes,
135 false,
136 )) {
137 Ok(_) => {}
138 Err(error) => return Err(error),
139 }
140
141 let public_key = crate::traits::KemPublicKey::new(public_key_bytes.to_vec());
143
144 let result = convert_result(self.inner.encapsulate(
146 algorithm,
147 &public_key,
148 randomness_bytes.as_deref(),
149 ))?;
150
151 match secure_serialize(&result) {
153 Ok(value) => Ok(value),
154 Err(error) => Err(error),
155 }
156 }
157
158 pub fn decapsulate(
160 &self,
161 algorithm: &str,
162 private_key: &Uint8Array,
163 ciphertext: &Uint8Array,
164 ) -> Result<JsValue, JsValue> {
165 let algorithm = parse_algorithm_wasm(algorithm)?;
167
168 match convert_result(
170 self.security_validator
171 .validate_algorithm_category(algorithm, AlgorithmCategory::Kem),
172 ) {
173 Ok(_) => {}
174 Err(error) => return Err(error),
175 }
176
177 let private_key_bytes = private_key.to_vec();
179 let ciphertext_bytes = ciphertext.to_vec();
180
181 match convert_result(self.security_validator.validate_key_size(
183 algorithm,
184 &private_key_bytes,
185 true,
186 )) {
187 Ok(_) => {}
188 Err(error) => return Err(error),
189 }
190
191 let secret_key = crate::traits::KemSecretKey::new(private_key_bytes.to_vec());
193
194 let result = convert_result(self.inner.decapsulate(
196 algorithm,
197 &secret_key,
198 &ciphertext_bytes,
199 ))?;
200
201 match secure_serialize(&result) {
203 Ok(value) => Ok(value),
204 Err(error) => Err(error),
205 }
206 }
207
208 pub fn get_supported_algorithms(&self) -> Result<JsValue, JsValue> {
210 let algorithms = alloc::vec!["ml-kem-512", "ml-kem-768", "ml-kem-1024"];
211 match secure_serialize(&algorithms) {
212 Ok(value) => Ok(value),
213 Err(error) => Err(error),
214 }
215 }
216}
217
218#[cfg_attr(feature = "wasm", wasm_bindgen)]
226pub struct SecureWasmSignatureContext {
227 inner: SignatureContext,
228 security_validator: SecurityValidator,
229}
230
231#[cfg_attr(feature = "wasm", wasm_bindgen)]
232impl SecureWasmSignatureContext {
233 #[cfg_attr(feature = "wasm", wasm_bindgen(constructor))]
235 pub fn new() -> Result<SecureWasmSignatureContext, JsValue> {
236 let provider = Box::new(LibQCryptoProvider::new()?);
237 let inner = SignatureContext::with_provider(provider);
238 let security_validator = SecurityValidator::new()?;
239
240 Ok(SecureWasmSignatureContext {
241 inner,
242 security_validator,
243 })
244 }
245
246 pub fn generate_keypair(
248 &mut self,
249 algorithm: &str,
250 randomness: Option<Uint8Array>,
251 ) -> Result<JsValue, JsValue> {
252 let algorithm = parse_algorithm_wasm(algorithm)?;
254
255 match convert_result(
257 self.security_validator
258 .validate_algorithm_category(algorithm, AlgorithmCategory::Signature),
259 ) {
260 Ok(_) => {}
261 Err(error) => return Err(error),
262 }
263
264 let randomness_bytes = randomness.map(|rand| rand.to_vec());
266
267 let keypair = convert_result(
269 self.inner
270 .generate_keypair(algorithm, randomness_bytes.as_deref()),
271 )?;
272
273 match secure_serialize(&keypair) {
275 Ok(value) => Ok(value),
276 Err(error) => Err(error),
277 }
278 }
279
280 pub fn sign(
282 &self,
283 algorithm: &str,
284 private_key: &Uint8Array,
285 message: &Uint8Array,
286 randomness: Option<Uint8Array>,
287 ) -> Result<JsValue, JsValue> {
288 let algorithm = parse_algorithm_wasm(algorithm)?;
290
291 match convert_result(
293 self.security_validator
294 .validate_algorithm_category(algorithm, AlgorithmCategory::Signature),
295 ) {
296 Ok(_) => {}
297 Err(error) => return Err(error),
298 }
299
300 let private_key_bytes = private_key.to_vec();
302 let message_bytes = message.to_vec();
303 let randomness_bytes = randomness.map(|rand| rand.to_vec());
304
305 match convert_result(self.security_validator.validate_key_size(
307 algorithm,
308 &private_key_bytes,
309 true,
310 )) {
311 Ok(_) => {}
312 Err(error) => return Err(error),
313 }
314
315 match convert_result(
317 self.security_validator
318 .validate_signature_message(&message_bytes),
319 ) {
320 Ok(_) => {}
321 Err(error) => return Err(error),
322 }
323
324 let secret_key = crate::traits::SigSecretKey::new(private_key_bytes.to_vec());
326
327 let signature = convert_result(self.inner.sign(
329 algorithm,
330 &secret_key,
331 &message_bytes,
332 randomness_bytes.as_deref(),
333 ))?;
334
335 match secure_serialize(&signature) {
337 Ok(value) => Ok(value),
338 Err(error) => Err(error),
339 }
340 }
341
342 pub fn verify(
344 &self,
345 algorithm: &str,
346 public_key: &Uint8Array,
347 message: &Uint8Array,
348 signature: &Uint8Array,
349 ) -> Result<JsValue, JsValue> {
350 let algorithm = parse_algorithm_wasm(algorithm)?;
352
353 match convert_result(
355 self.security_validator
356 .validate_algorithm_category(algorithm, AlgorithmCategory::Signature),
357 ) {
358 Ok(_) => {}
359 Err(error) => return Err(error),
360 }
361
362 let public_key_bytes = public_key.to_vec();
364 let message_bytes = message.to_vec();
365 let signature_bytes = signature.to_vec();
366
367 match convert_result(self.security_validator.validate_key_size(
369 algorithm,
370 &public_key_bytes,
371 false,
372 )) {
373 Ok(_) => {}
374 Err(error) => return Err(error),
375 }
376
377 match convert_result(
379 self.security_validator
380 .validate_signature_message(&message_bytes),
381 ) {
382 Ok(_) => {}
383 Err(error) => return Err(error),
384 }
385
386 let public_key = crate::traits::SigPublicKey::new(public_key_bytes.to_vec());
388
389 let is_valid = convert_result(self.inner.verify(
391 algorithm,
392 &public_key,
393 &message_bytes,
394 &signature_bytes,
395 ))?;
396
397 match secure_serialize(&is_valid) {
399 Ok(value) => Ok(value),
400 Err(error) => Err(error),
401 }
402 }
403
404 pub fn sign_with_context(
409 &self,
410 algorithm: &str,
411 private_key: &Uint8Array,
412 message: &Uint8Array,
413 context: &Uint8Array,
414 randomness: Option<Uint8Array>,
415 ) -> Result<JsValue, JsValue> {
416 let algorithm = parse_algorithm_wasm(algorithm)?;
417
418 convert_result(
419 self.security_validator
420 .validate_algorithm_category(algorithm, AlgorithmCategory::Signature),
421 )?;
422
423 let private_key_bytes = private_key.to_vec();
424 let message_bytes = message.to_vec();
425 let context_bytes = context.to_vec();
426 let randomness_bytes = randomness.map(|rand| rand.to_vec());
427
428 convert_result(self.security_validator.validate_key_size(
429 algorithm,
430 &private_key_bytes,
431 true,
432 ))?;
433
434 convert_result(
435 self.security_validator
436 .validate_signature_message(&message_bytes),
437 )?;
438
439 let secret_key = crate::traits::SigSecretKey::new(private_key_bytes.to_vec());
440
441 let signature = convert_result(self.inner.sign_with_context(
442 algorithm,
443 &secret_key,
444 &message_bytes,
445 &context_bytes,
446 randomness_bytes.as_deref(),
447 ))?;
448
449 secure_serialize(&signature)
450 }
451
452 pub fn verify_with_context(
457 &self,
458 algorithm: &str,
459 public_key: &Uint8Array,
460 message: &Uint8Array,
461 context: &Uint8Array,
462 signature: &Uint8Array,
463 ) -> Result<JsValue, JsValue> {
464 let algorithm = parse_algorithm_wasm(algorithm)?;
465
466 convert_result(
467 self.security_validator
468 .validate_algorithm_category(algorithm, AlgorithmCategory::Signature),
469 )?;
470
471 let public_key_bytes = public_key.to_vec();
472 let message_bytes = message.to_vec();
473 let context_bytes = context.to_vec();
474 let signature_bytes = signature.to_vec();
475
476 convert_result(self.security_validator.validate_key_size(
477 algorithm,
478 &public_key_bytes,
479 false,
480 ))?;
481
482 convert_result(
483 self.security_validator
484 .validate_signature_message(&message_bytes),
485 )?;
486
487 let public_key = crate::traits::SigPublicKey::new(public_key_bytes.to_vec());
488
489 let is_valid = convert_result(self.inner.verify_with_context(
490 algorithm,
491 &public_key,
492 &message_bytes,
493 &context_bytes,
494 &signature_bytes,
495 ))?;
496
497 secure_serialize(&is_valid)
498 }
499
500 pub fn get_supported_algorithms(&self) -> Result<JsValue, JsValue> {
502 match secure_serialize(&WASM_SIGNATURE_ALGORITHM_IDS) {
503 Ok(value) => Ok(value),
504 Err(error) => Err(error),
505 }
506 }
507}
508
509#[cfg_attr(feature = "wasm", wasm_bindgen)]
517pub struct SecureWasmHashContext {
518 inner: HashContext,
519 security_validator: SecurityValidator,
520}
521
522#[cfg_attr(feature = "wasm", wasm_bindgen)]
523impl SecureWasmHashContext {
524 #[cfg_attr(feature = "wasm", wasm_bindgen(constructor))]
526 pub fn new() -> Result<SecureWasmHashContext, JsValue> {
527 let provider = Box::new(LibQCryptoProvider::new()?);
528 let inner = HashContext::with_provider(provider);
529 let security_validator = SecurityValidator::new()?;
530
531 Ok(SecureWasmHashContext {
532 inner,
533 security_validator,
534 })
535 }
536
537 pub fn hash(&mut self, algorithm: &str, data: &Uint8Array) -> Result<JsValue, JsValue> {
539 let algorithm = parse_algorithm_wasm(algorithm)?;
541
542 match convert_result(
544 self.security_validator
545 .validate_algorithm_category(algorithm, AlgorithmCategory::Hash),
546 ) {
547 Ok(_) => {}
548 Err(error) => return Err(error),
549 }
550
551 let data_bytes = data.to_vec();
553
554 match convert_result(self.security_validator.validate_hash_input(&data_bytes)) {
556 Ok(_) => {}
557 Err(error) => return Err(error),
558 }
559
560 let hash = convert_result(self.inner.hash(algorithm, &data_bytes))?;
562
563 match secure_serialize(&hash) {
565 Ok(value) => Ok(value),
566 Err(error) => Err(error),
567 }
568 }
569
570 pub fn get_supported_algorithms(&self) -> Result<JsValue, JsValue> {
572 let algorithms = alloc::vec![
573 "sha3-224", "sha3-256", "sha3-384", "sha3-512", "shake128", "shake256",
574 ];
575 match secure_serialize(&algorithms) {
576 Ok(value) => Ok(value),
577 Err(error) => Err(error),
578 }
579 }
580}
581
582#[cfg_attr(feature = "wasm", wasm_bindgen)]
590pub struct SecureWasmAeadContext {
591 inner: AeadContext,
592 security_validator: SecurityValidator,
593}
594
595#[cfg_attr(feature = "wasm", wasm_bindgen)]
596impl SecureWasmAeadContext {
597 #[cfg_attr(feature = "wasm", wasm_bindgen(constructor))]
599 pub fn new() -> Result<SecureWasmAeadContext, JsValue> {
600 let provider = Box::new(LibQCryptoProvider::new()?);
601 let inner = AeadContext::with_provider(provider);
602 let security_validator = SecurityValidator::new()?;
603
604 Ok(SecureWasmAeadContext {
605 inner,
606 security_validator,
607 })
608 }
609
610 pub fn encrypt(
612 &mut self,
613 algorithm: &str,
614 key: &Uint8Array,
615 nonce: &Uint8Array,
616 plaintext: &Uint8Array,
617 associated_data: Option<Uint8Array>,
618 ) -> Result<JsValue, JsValue> {
619 let algorithm = parse_algorithm_wasm(algorithm)?;
621
622 match convert_result(
624 self.security_validator
625 .validate_algorithm_category(algorithm, AlgorithmCategory::Aead),
626 ) {
627 Ok(_) => {}
628 Err(error) => return Err(error),
629 }
630
631 let key_bytes = key.to_vec();
633 let nonce_bytes = nonce.to_vec();
634 let plaintext_bytes = plaintext.to_vec();
635 let associated_data_bytes = associated_data.map(|ad| ad.to_vec());
636
637 match convert_result(
639 self.security_validator
640 .validate_key_size(algorithm, &key_bytes, true),
641 ) {
642 Ok(_) => {}
643 Err(error) => return Err(error),
644 }
645
646 match convert_result(self.security_validator.validate_nonce(&nonce_bytes)) {
648 Ok(_) => {}
649 Err(error) => return Err(error),
650 }
651
652 match convert_result(
654 self.security_validator
655 .validate_aead_message(&plaintext_bytes),
656 ) {
657 Ok(_) => {}
658 Err(error) => return Err(error),
659 }
660
661 let aead_key = AeadKey::new(key_bytes.to_vec());
663 let aead_nonce = Nonce::new(nonce_bytes.to_vec());
664
665 let ciphertext = convert_result(self.inner.encrypt(
667 algorithm,
668 &aead_key,
669 &aead_nonce,
670 &plaintext_bytes,
671 associated_data_bytes.as_deref(),
672 ))?;
673
674 match secure_serialize(&ciphertext) {
676 Ok(value) => Ok(value),
677 Err(error) => Err(error),
678 }
679 }
680
681 pub fn decrypt(
683 &self,
684 algorithm: &str,
685 key: &Uint8Array,
686 nonce: &Uint8Array,
687 ciphertext: &Uint8Array,
688 associated_data: Option<Uint8Array>,
689 ) -> Result<JsValue, JsValue> {
690 let algorithm = parse_algorithm_wasm(algorithm)?;
692
693 match convert_result(
695 self.security_validator
696 .validate_algorithm_category(algorithm, AlgorithmCategory::Aead),
697 ) {
698 Ok(_) => {}
699 Err(error) => return Err(error),
700 }
701
702 let key_bytes = key.to_vec();
704 let nonce_bytes = nonce.to_vec();
705 let ciphertext_bytes = ciphertext.to_vec();
706 let associated_data_bytes = associated_data.map(|ad| ad.to_vec());
707
708 match convert_result(
710 self.security_validator
711 .validate_key_size(algorithm, &key_bytes, true),
712 ) {
713 Ok(_) => {}
714 Err(error) => return Err(error),
715 }
716
717 match convert_result(self.security_validator.validate_nonce(&nonce_bytes)) {
719 Ok(_) => {}
720 Err(error) => return Err(error),
721 }
722
723 match convert_result(
725 self.security_validator
726 .validate_aead_message(&ciphertext_bytes),
727 ) {
728 Ok(_) => {}
729 Err(error) => return Err(error),
730 }
731
732 let aead_key = AeadKey::new(key_bytes.to_vec());
734 let aead_nonce = Nonce::new(nonce_bytes.to_vec());
735
736 let plaintext = convert_result(self.inner.decrypt(
738 algorithm,
739 &aead_key,
740 &aead_nonce,
741 &ciphertext_bytes,
742 associated_data_bytes.as_deref(),
743 ))?;
744
745 match secure_serialize(&plaintext) {
747 Ok(value) => Ok(value),
748 Err(error) => Err(error),
749 }
750 }
751
752 pub fn get_supported_algorithms(&self) -> Result<JsValue, JsValue> {
754 let algorithms = alloc::vec!["saturnin", "shake256-aead"];
755 match secure_serialize(&algorithms) {
756 Ok(value) => Ok(value),
757 Err(error) => Err(error),
758 }
759 }
760}