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 get_supported_algorithms(&self) -> Result<JsValue, JsValue> {
406 match secure_serialize(&WASM_SIGNATURE_ALGORITHM_IDS) {
407 Ok(value) => Ok(value),
408 Err(error) => Err(error),
409 }
410 }
411}
412
413#[cfg_attr(feature = "wasm", wasm_bindgen)]
421pub struct SecureWasmHashContext {
422 inner: HashContext,
423 security_validator: SecurityValidator,
424}
425
426#[cfg_attr(feature = "wasm", wasm_bindgen)]
427impl SecureWasmHashContext {
428 #[cfg_attr(feature = "wasm", wasm_bindgen(constructor))]
430 pub fn new() -> Result<SecureWasmHashContext, JsValue> {
431 let provider = Box::new(LibQCryptoProvider::new()?);
432 let inner = HashContext::with_provider(provider);
433 let security_validator = SecurityValidator::new()?;
434
435 Ok(SecureWasmHashContext {
436 inner,
437 security_validator,
438 })
439 }
440
441 pub fn hash(&mut self, algorithm: &str, data: &Uint8Array) -> Result<JsValue, JsValue> {
443 let algorithm = parse_algorithm_wasm(algorithm)?;
445
446 match convert_result(
448 self.security_validator
449 .validate_algorithm_category(algorithm, AlgorithmCategory::Hash),
450 ) {
451 Ok(_) => {}
452 Err(error) => return Err(error),
453 }
454
455 let data_bytes = data.to_vec();
457
458 match convert_result(self.security_validator.validate_hash_input(&data_bytes)) {
460 Ok(_) => {}
461 Err(error) => return Err(error),
462 }
463
464 let hash = convert_result(self.inner.hash(algorithm, &data_bytes))?;
466
467 match secure_serialize(&hash) {
469 Ok(value) => Ok(value),
470 Err(error) => Err(error),
471 }
472 }
473
474 pub fn get_supported_algorithms(&self) -> Result<JsValue, JsValue> {
476 let algorithms = alloc::vec![
477 "sha3-224", "sha3-256", "sha3-384", "sha3-512", "shake128", "shake256",
478 ];
479 match secure_serialize(&algorithms) {
480 Ok(value) => Ok(value),
481 Err(error) => Err(error),
482 }
483 }
484}
485
486#[cfg_attr(feature = "wasm", wasm_bindgen)]
494pub struct SecureWasmAeadContext {
495 inner: AeadContext,
496 security_validator: SecurityValidator,
497}
498
499#[cfg_attr(feature = "wasm", wasm_bindgen)]
500impl SecureWasmAeadContext {
501 #[cfg_attr(feature = "wasm", wasm_bindgen(constructor))]
503 pub fn new() -> Result<SecureWasmAeadContext, JsValue> {
504 let provider = Box::new(LibQCryptoProvider::new()?);
505 let inner = AeadContext::with_provider(provider);
506 let security_validator = SecurityValidator::new()?;
507
508 Ok(SecureWasmAeadContext {
509 inner,
510 security_validator,
511 })
512 }
513
514 pub fn encrypt(
516 &mut self,
517 algorithm: &str,
518 key: &Uint8Array,
519 nonce: &Uint8Array,
520 plaintext: &Uint8Array,
521 associated_data: Option<Uint8Array>,
522 ) -> Result<JsValue, JsValue> {
523 let algorithm = parse_algorithm_wasm(algorithm)?;
525
526 match convert_result(
528 self.security_validator
529 .validate_algorithm_category(algorithm, AlgorithmCategory::Aead),
530 ) {
531 Ok(_) => {}
532 Err(error) => return Err(error),
533 }
534
535 let key_bytes = key.to_vec();
537 let nonce_bytes = nonce.to_vec();
538 let plaintext_bytes = plaintext.to_vec();
539 let associated_data_bytes = associated_data.map(|ad| ad.to_vec());
540
541 match convert_result(
543 self.security_validator
544 .validate_key_size(algorithm, &key_bytes, true),
545 ) {
546 Ok(_) => {}
547 Err(error) => return Err(error),
548 }
549
550 match convert_result(self.security_validator.validate_nonce(&nonce_bytes)) {
552 Ok(_) => {}
553 Err(error) => return Err(error),
554 }
555
556 match convert_result(
558 self.security_validator
559 .validate_aead_message(&plaintext_bytes),
560 ) {
561 Ok(_) => {}
562 Err(error) => return Err(error),
563 }
564
565 let aead_key = AeadKey::new(key_bytes.to_vec());
567 let aead_nonce = Nonce::new(nonce_bytes.to_vec());
568
569 let ciphertext = convert_result(self.inner.encrypt(
571 algorithm,
572 &aead_key,
573 &aead_nonce,
574 &plaintext_bytes,
575 associated_data_bytes.as_deref(),
576 ))?;
577
578 match secure_serialize(&ciphertext) {
580 Ok(value) => Ok(value),
581 Err(error) => Err(error),
582 }
583 }
584
585 pub fn decrypt(
587 &self,
588 algorithm: &str,
589 key: &Uint8Array,
590 nonce: &Uint8Array,
591 ciphertext: &Uint8Array,
592 associated_data: Option<Uint8Array>,
593 ) -> Result<JsValue, JsValue> {
594 let algorithm = parse_algorithm_wasm(algorithm)?;
596
597 match convert_result(
599 self.security_validator
600 .validate_algorithm_category(algorithm, AlgorithmCategory::Aead),
601 ) {
602 Ok(_) => {}
603 Err(error) => return Err(error),
604 }
605
606 let key_bytes = key.to_vec();
608 let nonce_bytes = nonce.to_vec();
609 let ciphertext_bytes = ciphertext.to_vec();
610 let associated_data_bytes = associated_data.map(|ad| ad.to_vec());
611
612 match convert_result(
614 self.security_validator
615 .validate_key_size(algorithm, &key_bytes, true),
616 ) {
617 Ok(_) => {}
618 Err(error) => return Err(error),
619 }
620
621 match convert_result(self.security_validator.validate_nonce(&nonce_bytes)) {
623 Ok(_) => {}
624 Err(error) => return Err(error),
625 }
626
627 match convert_result(
629 self.security_validator
630 .validate_aead_message(&ciphertext_bytes),
631 ) {
632 Ok(_) => {}
633 Err(error) => return Err(error),
634 }
635
636 let aead_key = AeadKey::new(key_bytes.to_vec());
638 let aead_nonce = Nonce::new(nonce_bytes.to_vec());
639
640 let plaintext = convert_result(self.inner.decrypt(
642 algorithm,
643 &aead_key,
644 &aead_nonce,
645 &ciphertext_bytes,
646 associated_data_bytes.as_deref(),
647 ))?;
648
649 match secure_serialize(&plaintext) {
651 Ok(value) => Ok(value),
652 Err(error) => Err(error),
653 }
654 }
655
656 pub fn get_supported_algorithms(&self) -> Result<JsValue, JsValue> {
658 let algorithms = alloc::vec!["saturnin", "shake256-aead"];
659 match secure_serialize(&algorithms) {
660 Ok(value) => Ok(value),
661 Err(error) => Err(error),
662 }
663 }
664}