redact_crypto/key/
sodiumoxide.rs

1use crate::{
2    nonce::sodiumoxide::{SodiumOxideAsymmetricNonce, SodiumOxideSymmetricNonce},
3    Algorithm, AsymmetricKeyBuilder, Builder, ByteAlgorithm, ByteSource, CryptoError, Entry,
4    HasBuilder, HasByteSource, HasIndex, HasPublicKey, KeyBuilder, PublicAsymmetricKeyBuilder,
5    PublicAsymmetricSealer, PublicAsymmetricUnsealer, SecretAsymmetricKeyBuilder,
6    SecretAsymmetricSealer, SecretAsymmetricUnsealer, Signer, StorableType, SymmetricKeyBuilder,
7    SymmetricSealer, SymmetricUnsealer, ToPublicAsymmetricByteAlgorithm,
8    ToSecretAsymmetricByteAlgorithm, ToSymmetricByteAlgorithm, TypeBuilder, TypeBuilderContainer,
9    Verifier,
10};
11use async_trait::async_trait;
12use futures::Future;
13use mongodb::bson::{self, Document};
14use serde::{Deserialize, Serialize};
15use sodiumoxide::crypto::{
16    box_::{
17        self,
18        curve25519xsalsa20poly1305::{
19            PublicKey as ExternalSodiumOxideCurve25519PublicAsymmetricKey,
20            SecretKey as ExternalSodiumOxideCurve25519SecretAsymmetricKey,
21            PUBLICKEYBYTES as EXTERNALSODIUMOXIDECURVE25519PUBLICASYMMETRICKEYBYTES,
22            SECRETKEYBYTES as EXTERNALSODIUMOXIDECURVE25519SECRETASYMMETRICKEYBYTES,
23        },
24    },
25    secretbox::{
26        self,
27        xsalsa20poly1305::{
28            Key as ExternalSodiumOxideSymmetricKey,
29            KEYBYTES as EXTERNALSODIUMOXIDESYMMETRICKEYBYTES,
30        },
31    },
32    sign::ed25519::{
33        self, PublicKey as ExternalSodiumOxideEd25519PublicAsymmetricKey,
34        SecretKey as ExternalSodiumOxideEd25519SecretAsymmetricKey, Signature,
35        PUBLICKEYBYTES as EXTERNALSODIUMOXIDEED25519PUBLICASYMMETRICKEYBYTES,
36        SECRETKEYBYTES as EXTERNALSODIUMOXIDEED25519SECRETASYMMETRICKEYBYTES,
37        SEEDBYTES as EXTERNALSODIUMOXIDEED25519SEEDBYTES,
38    },
39    sign::{self, Seed},
40};
41use spki::AlgorithmIdentifier;
42use std::{boxed::Box, convert::TryFrom};
43
44use super::HasAlgorithmIdentifier;
45use sodiumoxide::crypto::sign::Verifier as SodiumOxideVerifier;
46use std::convert::TryInto;
47
48// SYMMETRIC KEY \\
49#[derive(Serialize, Deserialize, Debug)]
50pub struct SodiumOxideSymmetricKeyAlgorithm {
51    pub key: Box<Entry<SodiumOxideSymmetricKey>>,
52    pub nonce: SodiumOxideSymmetricNonce,
53}
54
55#[async_trait]
56impl Algorithm for SodiumOxideSymmetricKeyAlgorithm {
57    type Source = ByteSource;
58    type Output = ByteSource;
59
60    async fn unseal(&self, source: &Self::Source) -> Result<Self::Output, CryptoError> {
61        let key = self.key.resolve().await?;
62        Ok(key.unseal(source, &self.nonce)?)
63    }
64
65    async fn seal(&self, source: &Self::Source) -> Result<Self::Output, CryptoError> {
66        let key = self.key.resolve().await?;
67        let (source, _) = key.seal(source, Some(&self.nonce))?;
68        Ok(source)
69    }
70}
71
72#[derive(Serialize, Deserialize, Debug, Copy, Clone)]
73pub struct SodiumOxideSymmetricKeyBuilder {}
74
75impl TryFrom<TypeBuilderContainer> for SodiumOxideSymmetricKeyBuilder {
76    type Error = CryptoError;
77
78    fn try_from(builder: TypeBuilderContainer) -> Result<Self, Self::Error> {
79        match builder.0 {
80            TypeBuilder::Key(KeyBuilder::Symmetric(SymmetricKeyBuilder::SodiumOxide(soskb))) => {
81                Ok(soskb)
82            }
83            _ => Err(CryptoError::NotDowncastable),
84        }
85    }
86}
87
88impl Builder for SodiumOxideSymmetricKeyBuilder {
89    type Output = SodiumOxideSymmetricKey;
90
91    fn build(&self, bytes: Option<&[u8]>) -> Result<Self::Output, CryptoError> {
92        match bytes {
93            Some(bytes) => Ok(SodiumOxideSymmetricKey {
94                key: ExternalSodiumOxideSymmetricKey::from_slice(&bytes).ok_or(
95                    CryptoError::InvalidKeyLength {
96                        expected: SodiumOxideSymmetricKey::KEYBYTES,
97                        actual: bytes.len(),
98                    },
99                )?,
100            }),
101            None => Ok(SodiumOxideSymmetricKey::new()),
102        }
103    }
104}
105
106impl From<SodiumOxideSymmetricKeyBuilder> for TypeBuilder {
107    fn from(b: SodiumOxideSymmetricKeyBuilder) -> TypeBuilder {
108        TypeBuilder::Key(KeyBuilder::Symmetric(SymmetricKeyBuilder::SodiumOxide(b)))
109    }
110}
111
112#[derive(Debug)]
113pub struct SodiumOxideSymmetricKey {
114    pub key: ExternalSodiumOxideSymmetricKey,
115}
116
117#[async_trait]
118impl ToSymmetricByteAlgorithm for SodiumOxideSymmetricKey {
119    type Key = Self;
120    type Nonce = SodiumOxideSymmetricNonce;
121
122    async fn to_byte_algorithm<F, Fut>(
123        self,
124        nonce: Option<Self::Nonce>,
125        f: F,
126    ) -> Result<ByteAlgorithm, CryptoError>
127    where
128        F: FnOnce(Self::Key) -> Fut + Send,
129        Fut: Future<Output = Result<Entry<Self::Key>, CryptoError>> + Send,
130    {
131        let nonce = match nonce {
132            Some(nonce) => nonce,
133            None => SodiumOxideSymmetricNonce {
134                nonce: secretbox::gen_nonce(),
135            },
136        };
137        let entry = f(self).await?;
138        Ok(ByteAlgorithm::SodiumOxideSymmetricKey(
139            SodiumOxideSymmetricKeyAlgorithm {
140                key: Box::new(entry),
141                nonce,
142            },
143        ))
144    }
145}
146
147impl StorableType for SodiumOxideSymmetricKey {}
148
149impl SymmetricSealer for SodiumOxideSymmetricKey {
150    type SealedOutput = ByteSource;
151    type Nonce = SodiumOxideSymmetricNonce;
152
153    fn seal(
154        &self,
155        plaintext: &ByteSource,
156        nonce: Option<&Self::Nonce>,
157    ) -> Result<(Self::SealedOutput, Self::Nonce), CryptoError> {
158        let new_nonce = SodiumOxideSymmetricNonce {
159            nonce: secretbox::gen_nonce(),
160        };
161        let nonce = match nonce {
162            Some(n) => n,
163            None => &new_nonce,
164        };
165        let plaintext = plaintext.get()?;
166        let ciphertext = secretbox::seal(plaintext, &nonce.nonce, &self.key);
167        Ok((ciphertext.as_slice().into(), nonce.to_owned()))
168    }
169}
170
171impl SymmetricUnsealer for SodiumOxideSymmetricKey {
172    type UnsealedOutput = ByteSource;
173    type Nonce = SodiumOxideSymmetricNonce;
174
175    fn unseal(
176        &self,
177        ciphertext: &ByteSource,
178        nonce: &Self::Nonce,
179    ) -> Result<Self::UnsealedOutput, CryptoError> {
180        let plaintext = secretbox::open(ciphertext.get()?, &nonce.nonce, &self.key)
181            .map_err(|_| CryptoError::CiphertextFailedVerification)?;
182        Ok(plaintext.as_slice().into())
183    }
184}
185
186impl HasIndex for SodiumOxideSymmetricKey {
187    type Index = Document;
188
189    fn get_index() -> Option<Self::Index> {
190        Some(bson::doc! {
191        "c": {
192            "builder": {
193        "t": "Key",
194        "c": {
195            "t": "Symmetric",
196        "c": {
197        "t": "SodiumOxide"
198        }
199        }
200            }
201        }
202            })
203    }
204}
205
206impl HasBuilder for SodiumOxideSymmetricKey {
207    type Builder = SodiumOxideSymmetricKeyBuilder;
208
209    fn builder(&self) -> Self::Builder {
210        SodiumOxideSymmetricKeyBuilder {}
211    }
212}
213
214impl HasByteSource for SodiumOxideSymmetricKey {
215    fn byte_source(&self) -> ByteSource {
216        self.key.as_ref().into()
217    }
218}
219
220impl SodiumOxideSymmetricKey {
221    pub const KEYBYTES: usize = EXTERNALSODIUMOXIDESYMMETRICKEYBYTES;
222
223    pub fn new() -> Self {
224        SodiumOxideSymmetricKey {
225            key: secretbox::gen_key(),
226        }
227    }
228}
229
230// SECRET ASYMMETRIC KEY \\
231#[derive(Serialize, Deserialize, Debug)]
232pub struct SodiumOxideSecretAsymmetricKeyAlgorithm {
233    pub secret_key: Box<Entry<SodiumOxideCurve25519SecretAsymmetricKey>>,
234    pub nonce: SodiumOxideAsymmetricNonce,
235    pub public_key: Option<Box<Entry<SodiumOxideCurve25519PublicAsymmetricKey>>>,
236}
237
238#[async_trait]
239impl Algorithm for SodiumOxideSecretAsymmetricKeyAlgorithm {
240    type Source = ByteSource;
241    type Output = ByteSource;
242
243    async fn unseal(&self, source: &Self::Source) -> Result<Self::Output, CryptoError> {
244        let secret_key = self.secret_key.resolve().await?;
245        let public_key = match self.public_key {
246            Some(ref public_key) => Ok::<_, CryptoError>(Some(public_key.resolve().await?)),
247            None => Ok(None),
248        }?;
249        Ok(secret_key.unseal(&source, public_key, &self.nonce)?)
250    }
251
252    async fn seal(&self, source: &Self::Source) -> Result<Self::Output, CryptoError> {
253        let secret_key = self.secret_key.resolve().await?;
254        let public_key = match self.public_key {
255            Some(ref public_key) => Ok::<_, CryptoError>(Some(public_key.resolve().await?)),
256            None => Ok(None),
257        }?;
258        let (source, _) = secret_key.seal(&source, public_key, Some(&self.nonce))?;
259        Ok(source)
260    }
261}
262
263#[derive(Serialize, Deserialize, Debug, Clone, Copy)]
264pub struct SodiumOxideCurve25519SecretAsymmetricKeyBuilder {}
265
266impl TryFrom<TypeBuilderContainer> for SodiumOxideCurve25519SecretAsymmetricKeyBuilder {
267    type Error = CryptoError;
268
269    fn try_from(builder: TypeBuilderContainer) -> Result<Self, Self::Error> {
270        match builder.0 {
271            TypeBuilder::Key(KeyBuilder::Asymmetric(AsymmetricKeyBuilder::Secret(
272                SecretAsymmetricKeyBuilder::SodiumOxideCurve25519(sosakb),
273            ))) => Ok(sosakb),
274            _ => Err(CryptoError::NotDowncastable),
275        }
276    }
277}
278
279impl Builder for SodiumOxideCurve25519SecretAsymmetricKeyBuilder {
280    type Output = SodiumOxideCurve25519SecretAsymmetricKey;
281
282    fn build(&self, bytes: Option<&[u8]>) -> Result<Self::Output, CryptoError> {
283        match bytes {
284            Some(bytes) => Ok(SodiumOxideCurve25519SecretAsymmetricKey {
285                secret_key: ExternalSodiumOxideCurve25519SecretAsymmetricKey::from_slice(&bytes)
286                    .ok_or(CryptoError::InvalidKeyLength {
287                        expected: SodiumOxideCurve25519SecretAsymmetricKey::KEYBYTES,
288                        actual: bytes.len(),
289                    })?,
290            }),
291            None => Ok(SodiumOxideCurve25519SecretAsymmetricKey::new()),
292        }
293    }
294}
295
296impl From<SodiumOxideCurve25519SecretAsymmetricKeyBuilder> for TypeBuilder {
297    fn from(b: SodiumOxideCurve25519SecretAsymmetricKeyBuilder) -> TypeBuilder {
298        TypeBuilder::Key(KeyBuilder::Asymmetric(AsymmetricKeyBuilder::Secret(
299            SecretAsymmetricKeyBuilder::SodiumOxideCurve25519(b),
300        )))
301    }
302}
303
304#[derive(Debug)]
305pub struct SodiumOxideCurve25519SecretAsymmetricKey {
306    pub secret_key: ExternalSodiumOxideCurve25519SecretAsymmetricKey,
307}
308
309#[async_trait]
310impl ToSecretAsymmetricByteAlgorithm for SodiumOxideCurve25519SecretAsymmetricKey {
311    type SecretKey = Self;
312    type Nonce = SodiumOxideAsymmetricNonce;
313    type PublicKey = SodiumOxideCurve25519PublicAsymmetricKey;
314
315    async fn to_byte_algorithm<F, Fut>(
316        self,
317        public_key: Option<Entry<Self::PublicKey>>,
318        nonce: Option<Self::Nonce>,
319        f: F,
320    ) -> Result<ByteAlgorithm, CryptoError>
321    where
322        F: FnOnce(Self::SecretKey) -> Fut + Send,
323        Fut: Future<Output = Result<Entry<Self::SecretKey>, CryptoError>> + Send,
324    {
325        let nonce = match nonce {
326            Some(nonce) => nonce,
327            None => SodiumOxideAsymmetricNonce {
328                nonce: box_::gen_nonce(),
329            },
330        };
331        let public_key = public_key.map(Box::new);
332        let secret_key = Box::new(f(self).await?);
333        Ok(ByteAlgorithm::SodiumOxideSecretAsymmetricKey(
334            SodiumOxideSecretAsymmetricKeyAlgorithm {
335                secret_key,
336                nonce,
337                public_key,
338            },
339        ))
340    }
341}
342
343impl StorableType for SodiumOxideCurve25519SecretAsymmetricKey {}
344
345impl SecretAsymmetricSealer for SodiumOxideCurve25519SecretAsymmetricKey {
346    type SealedOutput = ByteSource;
347    type Nonce = SodiumOxideAsymmetricNonce;
348    type PublicKey = SodiumOxideCurve25519PublicAsymmetricKey;
349
350    fn seal(
351        &self,
352        plaintext: &ByteSource,
353        public_key: Option<&Self::PublicKey>,
354        nonce: Option<&Self::Nonce>,
355    ) -> Result<(Self::SealedOutput, Self::Nonce), CryptoError> {
356        let new_nonce = SodiumOxideAsymmetricNonce {
357            nonce: box_::gen_nonce(),
358        };
359        let nonce = match nonce {
360            Some(n) => n,
361            None => &new_nonce,
362        };
363        let plaintext = plaintext.get()?;
364        let self_public_key = SodiumOxideCurve25519PublicAsymmetricKey {
365            public_key: self.secret_key.public_key(),
366        };
367        let public_key = match public_key {
368            Some(sopak) => sopak,
369            None => &self_public_key,
370        };
371        let precomputed_key = box_::precompute(&public_key.public_key, &self.secret_key);
372        let ciphertext = box_::seal_precomputed(plaintext, &nonce.nonce, &precomputed_key);
373        Ok((ciphertext.as_slice().into(), nonce.to_owned()))
374    }
375}
376
377impl SecretAsymmetricUnsealer for SodiumOxideCurve25519SecretAsymmetricKey {
378    type UnsealedOutput = ByteSource;
379    type Nonce = SodiumOxideAsymmetricNonce;
380    type PublicKey = SodiumOxideCurve25519PublicAsymmetricKey;
381
382    fn unseal(
383        &self,
384        ciphertext: &ByteSource,
385        public_key: Option<&Self::PublicKey>,
386        nonce: &Self::Nonce,
387    ) -> Result<Self::UnsealedOutput, CryptoError> {
388        let ciphertext = ciphertext.get()?;
389        let self_public_key = SodiumOxideCurve25519PublicAsymmetricKey {
390            public_key: self.secret_key.public_key(),
391        };
392        let public_key = match public_key {
393            Some(sopak) => sopak,
394            None => &self_public_key,
395        };
396        let precomputed_key = box_::precompute(&public_key.public_key, &self.secret_key);
397        let plaintext = box_::open_precomputed(ciphertext, &nonce.nonce, &precomputed_key)
398            .map_err(|_| CryptoError::CiphertextFailedVerification)?;
399        Ok(plaintext.as_slice().into())
400    }
401}
402
403impl HasIndex for SodiumOxideCurve25519SecretAsymmetricKey {
404    type Index = Document;
405
406    fn get_index() -> Option<Self::Index> {
407        Some(bson::doc! {
408        "c": {
409            "builder": {
410        "t": "Key",
411        "c": {
412            "t": "Asymmetric",
413        "c": {
414            "t": "Secret",
415        "c": {
416        "t": "SodiumOxideCurve25519"
417        }
418        }
419        }
420            }
421        }
422            })
423    }
424}
425
426impl HasBuilder for SodiumOxideCurve25519SecretAsymmetricKey {
427    type Builder = SodiumOxideCurve25519SecretAsymmetricKeyBuilder;
428
429    fn builder(&self) -> Self::Builder {
430        SodiumOxideCurve25519SecretAsymmetricKeyBuilder {}
431    }
432}
433
434impl HasByteSource for SodiumOxideCurve25519SecretAsymmetricKey {
435    fn byte_source(&self) -> ByteSource {
436        self.secret_key.as_ref().into()
437    }
438}
439
440impl Default for SodiumOxideCurve25519SecretAsymmetricKey {
441    fn default() -> Self {
442        Self::new()
443    }
444}
445
446impl SodiumOxideCurve25519SecretAsymmetricKey {
447    pub const KEYBYTES: usize = EXTERNALSODIUMOXIDECURVE25519SECRETASYMMETRICKEYBYTES;
448
449    pub fn new() -> Self {
450        let (_, key) = box_::gen_keypair();
451        SodiumOxideCurve25519SecretAsymmetricKey { secret_key: key }
452    }
453
454    pub fn get_signing_key(&self) -> Result<SodiumOxideEd25519SecretAsymmetricKey, CryptoError> {
455        sign::ed25519::Seed::from_slice(&self.secret_key.as_ref())
456            .ok_or(CryptoError::InvalidKeyLength {
457                expected: sign::ed25519::SEEDBYTES,
458                actual: self.secret_key.as_ref().len(),
459            })
460            .map(|seed| {
461                let (_, sk) = sign::ed25519::keypair_from_seed(&seed);
462                SodiumOxideEd25519SecretAsymmetricKey { secret_key: sk }
463            })
464    }
465}
466
467// PUBLIC ASYMMETRIC KEY \\
468#[derive(Serialize, Deserialize, Debug)]
469pub struct SodiumOxidePublicAsymmetricKeyAlgorithm {
470    pub public_key: Box<Entry<SodiumOxideCurve25519PublicAsymmetricKey>>,
471    pub nonce: SodiumOxideAsymmetricNonce,
472    pub secret_key: Box<Entry<SodiumOxideCurve25519SecretAsymmetricKey>>,
473}
474
475#[async_trait]
476impl Algorithm for SodiumOxidePublicAsymmetricKeyAlgorithm {
477    type Source = ByteSource;
478    type Output = ByteSource;
479
480    async fn unseal(&self, source: &Self::Source) -> Result<Self::Output, CryptoError> {
481        let secret_key = self.secret_key.resolve().await?;
482        let public_key = self.public_key.resolve().await?;
483        Ok(public_key.unseal(source, secret_key, &self.nonce)?)
484    }
485
486    async fn seal(&self, source: &Self::Source) -> Result<Self::Output, CryptoError> {
487        let secret_key = self.secret_key.resolve().await?;
488        let public_key = self.public_key.resolve().await?;
489        let (source, _) = public_key.seal(source, secret_key, Some(&self.nonce))?;
490        Ok(source)
491    }
492}
493
494#[derive(Serialize, Deserialize, Debug, Clone, Copy)]
495pub struct SodiumOxideCurve25519PublicAsymmetricKeyBuilder {}
496
497impl TryFrom<TypeBuilderContainer> for SodiumOxideCurve25519PublicAsymmetricKeyBuilder {
498    type Error = CryptoError;
499
500    fn try_from(builder: TypeBuilderContainer) -> Result<Self, Self::Error> {
501        match builder.0 {
502            TypeBuilder::Key(KeyBuilder::Asymmetric(AsymmetricKeyBuilder::Public(
503                PublicAsymmetricKeyBuilder::SodiumOxideCurve25519(sopakb),
504            ))) => Ok(sopakb),
505            _ => Err(CryptoError::NotDowncastable),
506        }
507    }
508}
509
510impl Builder for SodiumOxideCurve25519PublicAsymmetricKeyBuilder {
511    type Output = SodiumOxideCurve25519PublicAsymmetricKey;
512
513    fn build(&self, bytes: Option<&[u8]>) -> Result<Self::Output, CryptoError> {
514        match bytes {
515            Some(bytes) => Ok(SodiumOxideCurve25519PublicAsymmetricKey {
516                public_key: ExternalSodiumOxideCurve25519PublicAsymmetricKey::from_slice(&bytes)
517                    .ok_or(CryptoError::InvalidKeyLength {
518                        expected: SodiumOxideCurve25519PublicAsymmetricKey::KEYBYTES,
519                        actual: bytes.len(),
520                    })?,
521            }),
522            None => {
523                let (pk, _) = SodiumOxideCurve25519PublicAsymmetricKey::new();
524                Ok(pk)
525            }
526        }
527    }
528}
529
530impl From<SodiumOxideCurve25519PublicAsymmetricKeyBuilder> for TypeBuilder {
531    fn from(b: SodiumOxideCurve25519PublicAsymmetricKeyBuilder) -> TypeBuilder {
532        TypeBuilder::Key(KeyBuilder::Asymmetric(AsymmetricKeyBuilder::Public(
533            PublicAsymmetricKeyBuilder::SodiumOxideCurve25519(b),
534        )))
535    }
536}
537
538#[derive(Debug)]
539pub struct SodiumOxideCurve25519PublicAsymmetricKey {
540    pub public_key: ExternalSodiumOxideCurve25519PublicAsymmetricKey,
541}
542
543#[async_trait]
544impl ToPublicAsymmetricByteAlgorithm for SodiumOxideCurve25519PublicAsymmetricKey {
545    type SecretKey = SodiumOxideCurve25519SecretAsymmetricKey;
546    type Nonce = SodiumOxideAsymmetricNonce;
547    type PublicKey = Self;
548
549    async fn to_byte_algorithm<F, Fut>(
550        self,
551        secret_key: Entry<Self::SecretKey>,
552        nonce: Option<Self::Nonce>,
553        f: F,
554    ) -> Result<ByteAlgorithm, CryptoError>
555    where
556        F: FnOnce(Self::PublicKey) -> Fut + Send,
557        Fut: Future<Output = Result<Entry<Self::PublicKey>, CryptoError>> + Send,
558    {
559        let nonce = match nonce {
560            Some(nonce) => nonce,
561            None => SodiumOxideAsymmetricNonce {
562                nonce: box_::gen_nonce(),
563            },
564        };
565        let secret_key = Box::new(secret_key);
566        let public_key = Box::new(f(self).await?);
567        Ok(ByteAlgorithm::SodiumOxidePublicAsymmetricKey(
568            SodiumOxidePublicAsymmetricKeyAlgorithm {
569                secret_key,
570                nonce,
571                public_key,
572            },
573        ))
574    }
575}
576
577impl StorableType for SodiumOxideCurve25519PublicAsymmetricKey {}
578
579impl PublicAsymmetricSealer for SodiumOxideCurve25519PublicAsymmetricKey {
580    type SealedOutput = ByteSource;
581    type Nonce = SodiumOxideAsymmetricNonce;
582    type SecretKey = SodiumOxideCurve25519SecretAsymmetricKey;
583
584    fn seal(
585        &self,
586        plaintext: &ByteSource,
587        secret_key: &Self::SecretKey,
588        nonce: Option<&Self::Nonce>,
589    ) -> Result<(Self::SealedOutput, Self::Nonce), CryptoError> {
590        let new_nonce = SodiumOxideAsymmetricNonce {
591            nonce: box_::gen_nonce(),
592        };
593        let nonce = match nonce {
594            Some(n) => n,
595            None => &new_nonce,
596        };
597        let plaintext = plaintext.get()?;
598        let precomputed_key = box_::precompute(&self.public_key, &secret_key.secret_key);
599        let ciphertext = box_::seal_precomputed(plaintext, &nonce.nonce, &precomputed_key);
600        Ok((ciphertext.as_slice().into(), nonce.to_owned()))
601    }
602}
603
604impl PublicAsymmetricUnsealer for SodiumOxideCurve25519PublicAsymmetricKey {
605    type UnsealedOutput = ByteSource;
606    type Nonce = SodiumOxideAsymmetricNonce;
607    type SecretKey = SodiumOxideCurve25519SecretAsymmetricKey;
608
609    fn unseal(
610        &self,
611        ciphertext: &ByteSource,
612        secret_key: &Self::SecretKey,
613        nonce: &Self::Nonce,
614    ) -> Result<Self::UnsealedOutput, CryptoError> {
615        let ciphertext = ciphertext.get()?;
616        let precomputed_key = box_::precompute(&self.public_key, &secret_key.secret_key);
617        let plaintext = box_::open_precomputed(ciphertext, &nonce.nonce, &precomputed_key)
618            .map_err(|_| CryptoError::CiphertextFailedVerification)?;
619        Ok(plaintext.as_slice().into())
620    }
621}
622
623impl HasIndex for SodiumOxideCurve25519PublicAsymmetricKey {
624    type Index = Document;
625
626    fn get_index() -> Option<Self::Index> {
627        Some(bson::doc! {
628        "c": {
629            "builder": {
630        "t": "Key",
631        "c": {
632            "t": "Asymmetric",
633        "c": {
634            "t": "Public",
635        "c": {
636        "t": "SodiumOxideCurve25519"
637        }
638        }
639        }
640            }
641        }
642            })
643    }
644}
645
646impl HasBuilder for SodiumOxideCurve25519PublicAsymmetricKey {
647    type Builder = SodiumOxideCurve25519PublicAsymmetricKeyBuilder;
648
649    fn builder(&self) -> Self::Builder {
650        SodiumOxideCurve25519PublicAsymmetricKeyBuilder {}
651    }
652}
653
654impl HasByteSource for SodiumOxideCurve25519PublicAsymmetricKey {
655    fn byte_source(&self) -> ByteSource {
656        self.public_key.as_ref().into()
657    }
658}
659
660impl HasAlgorithmIdentifier for SodiumOxideCurve25519PublicAsymmetricKey {
661    fn algorithm_identifier<'a>(&self) -> AlgorithmIdentifier<'a> {
662        AlgorithmIdentifier {
663            oid: spki::ObjectIdentifier::new("1.3.101.110"),
664            parameters: None,
665        }
666    }
667}
668
669impl SodiumOxideCurve25519PublicAsymmetricKey {
670    pub const KEYBYTES: usize = EXTERNALSODIUMOXIDECURVE25519PUBLICASYMMETRICKEYBYTES;
671
672    pub fn new() -> (Self, SodiumOxideCurve25519SecretAsymmetricKey) {
673        let (public_key, secret_key) = box_::gen_keypair();
674        (
675            SodiumOxideCurve25519PublicAsymmetricKey { public_key },
676            SodiumOxideCurve25519SecretAsymmetricKey { secret_key },
677        )
678    }
679}
680
681impl HasPublicKey for SodiumOxideCurve25519SecretAsymmetricKey {
682    type PublicKey = SodiumOxideCurve25519PublicAsymmetricKey;
683
684    fn public_key(&self) -> Result<Self::PublicKey, CryptoError> {
685        Ok(SodiumOxideCurve25519PublicAsymmetricKey {
686            public_key: self.secret_key.public_key(),
687        })
688    }
689}
690
691impl HasAlgorithmIdentifier for SodiumOxideCurve25519SecretAsymmetricKey {
692    fn algorithm_identifier<'a>(&self) -> AlgorithmIdentifier<'a> {
693        AlgorithmIdentifier {
694            oid: spki::ObjectIdentifier::new("1.3.101.110"),
695            parameters: None,
696        }
697    }
698}
699
700// SECRET SIGNING KEY \\
701#[derive(Serialize, Deserialize, Debug, Clone, Copy)]
702pub struct SodiumOxideEd25519SecretAsymmetricKeyBuilder {}
703
704impl TryFrom<TypeBuilderContainer> for SodiumOxideEd25519SecretAsymmetricKeyBuilder {
705    type Error = CryptoError;
706
707    fn try_from(builder: TypeBuilderContainer) -> Result<Self, Self::Error> {
708        match builder.0 {
709            TypeBuilder::Key(KeyBuilder::Asymmetric(AsymmetricKeyBuilder::Secret(
710                SecretAsymmetricKeyBuilder::SodiumOxideEd25519(sopakb),
711            ))) => Ok(sopakb),
712            _ => Err(CryptoError::NotDowncastable),
713        }
714    }
715}
716
717impl Builder for SodiumOxideEd25519SecretAsymmetricKeyBuilder {
718    type Output = SodiumOxideEd25519SecretAsymmetricKey;
719
720    fn build(&self, bytes: Option<&[u8]>) -> Result<Self::Output, CryptoError> {
721        match bytes {
722            Some(bytes) => {
723                let len = bytes.len();
724                if len == EXTERNALSODIUMOXIDEED25519SEEDBYTES {
725                    let seed = Seed::from_slice(bytes).ok_or(CryptoError::InvalidSeedLength {
726                        expected: EXTERNALSODIUMOXIDEED25519SEEDBYTES,
727                        actual: len,
728                    })?;
729                    let (_, secret_key) = ed25519::keypair_from_seed(&seed);
730                    Ok(SodiumOxideEd25519SecretAsymmetricKey { secret_key })
731                } else {
732                    Ok(SodiumOxideEd25519SecretAsymmetricKey {
733                        secret_key: ExternalSodiumOxideEd25519SecretAsymmetricKey::from_slice(
734                            bytes,
735                        )
736                        .ok_or(CryptoError::InvalidKeyLength {
737                            expected: SodiumOxideEd25519SecretAsymmetricKey::KEYBYTES,
738                            actual: bytes.len(),
739                        })?,
740                    })
741                }
742            }
743            None => {
744                let sk = SodiumOxideEd25519SecretAsymmetricKey::new();
745                Ok(sk)
746            }
747        }
748    }
749}
750
751impl From<SodiumOxideEd25519SecretAsymmetricKeyBuilder> for TypeBuilder {
752    fn from(b: SodiumOxideEd25519SecretAsymmetricKeyBuilder) -> TypeBuilder {
753        TypeBuilder::Key(KeyBuilder::Asymmetric(AsymmetricKeyBuilder::Secret(
754            SecretAsymmetricKeyBuilder::SodiumOxideEd25519(b),
755        )))
756    }
757}
758
759#[derive(Debug)]
760pub struct SodiumOxideEd25519SecretAsymmetricKey {
761    pub secret_key: ExternalSodiumOxideEd25519SecretAsymmetricKey,
762}
763
764impl StorableType for SodiumOxideEd25519SecretAsymmetricKey {}
765
766impl Signer for SodiumOxideEd25519SecretAsymmetricKey {
767    fn sign(&self, bytes: ByteSource) -> Result<ByteSource, CryptoError> {
768        Ok(sign::sign_detached(bytes.get()?, &self.secret_key)
769            .to_bytes()
770            .as_ref()
771            .into())
772    }
773}
774
775impl HasIndex for SodiumOxideEd25519SecretAsymmetricKey {
776    type Index = Document;
777
778    fn get_index() -> Option<Self::Index> {
779        Some(bson::doc! {
780        "c": {
781            "builder": {
782        "t": "Key",
783        "c": {
784            "t": "Asymmetric",
785        "c": {
786            "t": "Secret",
787        "c": {
788        "t": "SodiumOxideEd25519"
789        }
790        }
791        }
792            }
793        }
794            })
795    }
796}
797
798impl HasBuilder for SodiumOxideEd25519SecretAsymmetricKey {
799    type Builder = SodiumOxideEd25519SecretAsymmetricKeyBuilder;
800
801    fn builder(&self) -> Self::Builder {
802        SodiumOxideEd25519SecretAsymmetricKeyBuilder {}
803    }
804}
805
806impl HasByteSource for SodiumOxideEd25519SecretAsymmetricKey {
807    fn byte_source(&self) -> ByteSource {
808        self.secret_key.as_ref().into()
809    }
810}
811
812impl SodiumOxideEd25519SecretAsymmetricKey {
813    pub const KEYBYTES: usize = EXTERNALSODIUMOXIDEED25519SECRETASYMMETRICKEYBYTES;
814
815    pub fn new() -> Self {
816        let (_, secret_key) = sign::gen_keypair();
817        SodiumOxideEd25519SecretAsymmetricKey { secret_key }
818    }
819}
820
821impl Default for SodiumOxideEd25519SecretAsymmetricKey {
822    fn default() -> Self {
823        Self::new()
824    }
825}
826
827// PUBLIC SIGNING KEY \\
828#[derive(Serialize, Deserialize, Debug, Clone, Copy)]
829pub struct SodiumOxideEd25519PublicAsymmetricKeyBuilder {}
830
831impl TryFrom<TypeBuilderContainer> for SodiumOxideEd25519PublicAsymmetricKeyBuilder {
832    type Error = CryptoError;
833
834    fn try_from(builder: TypeBuilderContainer) -> Result<Self, Self::Error> {
835        match builder.0 {
836            TypeBuilder::Key(KeyBuilder::Asymmetric(AsymmetricKeyBuilder::Public(
837                PublicAsymmetricKeyBuilder::SodiumOxideEd25519(sopakb),
838            ))) => Ok(sopakb),
839            _ => Err(CryptoError::NotDowncastable),
840        }
841    }
842}
843
844impl Builder for SodiumOxideEd25519PublicAsymmetricKeyBuilder {
845    type Output = SodiumOxideEd25519PublicAsymmetricKey;
846
847    fn build(&self, bytes: Option<&[u8]>) -> Result<Self::Output, CryptoError> {
848        match bytes {
849            Some(bytes) => Ok(SodiumOxideEd25519PublicAsymmetricKey {
850                public_key: ExternalSodiumOxideEd25519PublicAsymmetricKey::from_slice(&bytes)
851                    .ok_or(CryptoError::InvalidKeyLength {
852                        expected: SodiumOxideEd25519PublicAsymmetricKey::KEYBYTES,
853                        actual: bytes.len(),
854                    })?,
855            }),
856            None => {
857                let (pk, _) = SodiumOxideEd25519PublicAsymmetricKey::new();
858                Ok(pk)
859            }
860        }
861    }
862}
863
864impl From<SodiumOxideEd25519PublicAsymmetricKeyBuilder> for TypeBuilder {
865    fn from(b: SodiumOxideEd25519PublicAsymmetricKeyBuilder) -> TypeBuilder {
866        TypeBuilder::Key(KeyBuilder::Asymmetric(AsymmetricKeyBuilder::Public(
867            PublicAsymmetricKeyBuilder::SodiumOxideEd25519(b),
868        )))
869    }
870}
871
872#[derive(Debug)]
873pub struct SodiumOxideEd25519PublicAsymmetricKey {
874    pub public_key: ExternalSodiumOxideEd25519PublicAsymmetricKey,
875}
876
877impl Verifier for SodiumOxideEd25519PublicAsymmetricKey {
878    fn verify(&self, msg: ByteSource, signature: ByteSource) -> Result<(), CryptoError> {
879        let signature_arr: [u8; 64] = signature
880            .get()
881            .map_err(|_e| CryptoError::BadSignature)?
882            .try_into()
883            .map_err(|_e| CryptoError::BadSignature)?;
884        self.public_key
885            .verify(
886                msg.get().map_err(|e| CryptoError::InternalError {
887                    source: Box::new(e),
888                })?,
889                &Signature::new(signature_arr),
890            )
891            .map_err(|_e| CryptoError::BadSignature)
892    }
893}
894
895impl StorableType for SodiumOxideEd25519PublicAsymmetricKey {}
896
897impl HasIndex for SodiumOxideEd25519PublicAsymmetricKey {
898    type Index = Document;
899
900    fn get_index() -> Option<Self::Index> {
901        Some(bson::doc! {
902        "c": {
903            "builder": {
904        "t": "Key",
905        "c": {
906            "t": "Asymmetric",
907        "c": {
908            "t": "Public",
909        "c": {
910        "t": "SodiumOxideEd25519"
911        }
912        }
913        }
914            }
915        }
916            })
917    }
918}
919
920impl HasBuilder for SodiumOxideEd25519PublicAsymmetricKey {
921    type Builder = SodiumOxideEd25519PublicAsymmetricKeyBuilder;
922
923    fn builder(&self) -> Self::Builder {
924        SodiumOxideEd25519PublicAsymmetricKeyBuilder {}
925    }
926}
927
928impl HasByteSource for SodiumOxideEd25519PublicAsymmetricKey {
929    fn byte_source(&self) -> ByteSource {
930        self.public_key.as_ref().into()
931    }
932}
933
934impl HasAlgorithmIdentifier for SodiumOxideEd25519PublicAsymmetricKey {
935    fn algorithm_identifier<'a>(&self) -> AlgorithmIdentifier<'a> {
936        AlgorithmIdentifier {
937            oid: spki::ObjectIdentifier::new("1.3.101.112"),
938            parameters: None,
939        }
940    }
941}
942
943impl SodiumOxideEd25519PublicAsymmetricKey {
944    pub const KEYBYTES: usize = EXTERNALSODIUMOXIDEED25519PUBLICASYMMETRICKEYBYTES;
945
946    pub fn new() -> (Self, SodiumOxideEd25519SecretAsymmetricKey) {
947        let (public_key, secret_key) = sign::gen_keypair();
948        (
949            SodiumOxideEd25519PublicAsymmetricKey { public_key },
950            SodiumOxideEd25519SecretAsymmetricKey { secret_key },
951        )
952    }
953}
954
955impl HasPublicKey for SodiumOxideEd25519SecretAsymmetricKey {
956    type PublicKey = SodiumOxideEd25519PublicAsymmetricKey;
957
958    fn public_key(&self) -> Result<Self::PublicKey, CryptoError> {
959        Ok(SodiumOxideEd25519PublicAsymmetricKey {
960            public_key: self.secret_key.public_key(),
961        })
962    }
963}
964
965impl HasAlgorithmIdentifier for SodiumOxideEd25519SecretAsymmetricKey {
966    fn algorithm_identifier<'a>(&self) -> AlgorithmIdentifier<'a> {
967        AlgorithmIdentifier {
968            oid: spki::ObjectIdentifier::new("1.3.101.112"),
969            parameters: None,
970        }
971    }
972}
973
974#[cfg(test)]
975mod tests {
976    use super::{
977        SodiumOxideCurve25519PublicAsymmetricKey, SodiumOxideCurve25519PublicAsymmetricKeyBuilder,
978        SodiumOxideCurve25519SecretAsymmetricKey, SodiumOxideCurve25519SecretAsymmetricKeyBuilder,
979        SodiumOxideSymmetricKey, SodiumOxideSymmetricKeyBuilder,
980    };
981    use crate::key::sodiumoxide::{
982        SodiumOxideEd25519PublicAsymmetricKey, SodiumOxideEd25519PublicAsymmetricKeyBuilder,
983    };
984    use crate::{
985        nonce::sodiumoxide::{SodiumOxideAsymmetricNonce, SodiumOxideSymmetricNonce},
986        storage::tests::MockIndexedStorer,
987        storage::tests::MockStorer,
988        Algorithm, AsymmetricKeyBuilder, BoolDataBuilder, Builder, ByteSource, CryptoError, Data,
989        DataBuilder, HasBuilder, HasByteSource, HasIndex, HasPublicKey, KeyBuilder,
990        PublicAsymmetricKeyBuilder, PublicAsymmetricSealer, PublicAsymmetricUnsealer,
991        SecretAsymmetricKeyBuilder, SecretAsymmetricSealer, SecretAsymmetricUnsealer,
992        SymmetricKeyBuilder, SymmetricSealer, SymmetricUnsealer, ToEntry, ToSymmetricByteAlgorithm,
993        TypeBuilder, TypeBuilderContainer, VectorByteSource, Verifier,
994    };
995    use mongodb::bson;
996    use sodiumoxide::crypto::{
997        box_,
998        secretbox::{self, xsalsa20poly1305::Nonce as ExternalSodiumOxideSymmetricNonce},
999        sign,
1000    };
1001    use std::convert::TryInto;
1002
1003    //////////////////////////////////////////////
1004    /// PUBLIC ASYMMETRIC KEY HELPER FUNCTIONS ///
1005    //////////////////////////////////////////////
1006    fn get_sopak_ciphertext(
1007        plaintext: &[u8],
1008        secret_key: Option<&SodiumOxideCurve25519SecretAsymmetricKey>,
1009    ) -> Vec<u8> {
1010        let new_key = get_sosak();
1011        let secret_key = match secret_key {
1012            Some(sk) => sk,
1013            None => &new_key,
1014        };
1015        let (public_key, _) = get_sopak();
1016        let nonce = get_soan();
1017        let precomputed_key = box_::precompute(&public_key.public_key, &secret_key.secret_key);
1018        box_::seal_precomputed(plaintext, &nonce.nonce, &precomputed_key)
1019    }
1020
1021    fn get_sopak() -> (
1022        SodiumOxideCurve25519PublicAsymmetricKey,
1023        SodiumOxideCurve25519SecretAsymmetricKey,
1024    ) {
1025        let key_bytes: [u8; 32] = [
1026            77, 166, 178, 227, 216, 254, 219, 202, 41, 198, 74, 141, 126, 196, 68, 179, 19, 218,
1027            34, 107, 174, 121, 199, 180, 254, 254, 161, 219, 225, 158, 220, 56,
1028        ];
1029        let sosakb = SodiumOxideCurve25519SecretAsymmetricKeyBuilder {};
1030        let secret_key = sosakb.build(Some(&key_bytes)).unwrap();
1031        let public_key = SodiumOxideCurve25519PublicAsymmetricKey {
1032            public_key: secret_key.secret_key.public_key(),
1033        };
1034
1035        (public_key, secret_key)
1036    }
1037
1038    // fn get_unsealed_sopak(path: EntryPath) -> Entry<SodiumOxideCurve25519PublicAsymmetricKey> {
1039    //     let (public_key, _) = get_sopak();
1040    //     public_key.to_unsealed_entry(path).unwrap()
1041    // }
1042
1043    // fn get_referenced_sopak(
1044    //     path: EntryPath,
1045    //     storer: MockStorer,
1046    // ) -> Entry<SodiumOxideCurve25519PublicAsymmetricKey> {
1047    //     let (public_key, _) = get_sopak();
1048    //     public_key.to_ref_entry(path, storer).unwrap()
1049    // }
1050
1051    // async fn get_sealed_sopak_with_unsealed_key(
1052    //     path: EntryPath,
1053    // ) -> Entry<SodiumOxideCurve25519PublicAsymmetricKey> {
1054    //     let (public_key, _) = get_sopak();
1055    //     let encryption_key = get_sosk();
1056    //     let algorithm = encryption_key
1057    //         .to_byte_algorithm(Some(get_sosn()), |key| async move {
1058    //             key.to_unsealed_entry(".encryptionkey.".to_owned())
1059    //         })
1060    //         .await
1061    //         .unwrap();
1062    //     public_key.to_sealed_entry(path, algorithm).await.unwrap()
1063    // }
1064
1065    // async fn get_sealed_sopak_with_referenced_key(
1066    //     path: EntryPath,
1067    //     storer: MockStorer,
1068    // ) -> Entry<SodiumOxideCurve25519PublicAsymmetricKey> {
1069    //     let (public_key, _) = get_sopak();
1070    //     let encryption_key = get_sosk();
1071    //     let algorithm = encryption_key
1072    //         .to_byte_algorithm(Some(get_sosn()), |key| async move {
1073    //             key.to_ref_entry(".encryptionkey.".to_owned(), TypeStorer::Mock(storer))
1074    //         })
1075    //         .await
1076    //         .unwrap();
1077    //     public_key.to_sealed_entry(path, algorithm).await.unwrap()
1078    // }
1079
1080    //////////////////////////////////////////////
1081    /// SECRET ASYMMETRIC KEY HELPER FUNCTIONS ///
1082    //////////////////////////////////////////////
1083    fn get_sosak_ciphertext(
1084        plaintext: &[u8],
1085        public_key: &Option<SodiumOxideCurve25519PublicAsymmetricKey>,
1086    ) -> Vec<u8> {
1087        let key = get_sosak();
1088        let nonce = get_soan();
1089        let own_key = SodiumOxideCurve25519PublicAsymmetricKey {
1090            public_key: key.secret_key.public_key(),
1091        };
1092        let public_key = match public_key {
1093            Some(k) => k,
1094            None => &own_key,
1095        };
1096        let precomputed_key = box_::precompute(&public_key.public_key, &key.secret_key);
1097        box_::seal_precomputed(plaintext, &nonce.nonce, &precomputed_key)
1098    }
1099
1100    fn get_sosak() -> SodiumOxideCurve25519SecretAsymmetricKey {
1101        let key_bytes: [u8; 32] = [
1102            77, 166, 178, 227, 216, 254, 219, 202, 41, 198, 74, 141, 126, 196, 68, 179, 19, 218,
1103            34, 107, 174, 121, 199, 180, 254, 254, 161, 219, 225, 158, 220, 56,
1104        ];
1105        let sosakb = SodiumOxideCurve25519SecretAsymmetricKeyBuilder {};
1106        sosakb.build(Some(&key_bytes)).unwrap()
1107    }
1108
1109    fn get_soan() -> SodiumOxideAsymmetricNonce {
1110        let nonce_bytes: [u8; 24] = [
1111            24, 101, 189, 110, 189, 19, 129, 254, 163, 80, 137, 144, 100, 21, 11, 191, 22, 47, 64,
1112            132, 80, 122, 1, 237,
1113        ];
1114        let nonce = box_::curve25519xsalsa20poly1305::Nonce::from_slice(&nonce_bytes).unwrap();
1115        SodiumOxideAsymmetricNonce { nonce }
1116    }
1117
1118    // fn get_unsealed_sosak(path: EntryPath) -> Entry<SodiumOxideCurve25519SecretAsymmetricKey> {
1119    //     let key = get_sosak();
1120    //     key.to_unsealed_entry(path).unwrap()
1121    // }
1122
1123    // fn get_referenced_sosak(
1124    //     path: EntryPath,
1125    //     storer: MockStorer,
1126    // ) -> Entry<SodiumOxideCurve25519SecretAsymmetricKey> {
1127    //     let key = get_sosak();
1128    //     key.to_ref_entry(path, storer).unwrap()
1129    // }
1130
1131    // async fn get_sealed_sosak_with_unsealed_key(
1132    //     path: EntryPath,
1133    // ) -> Entry<SodiumOxideCurve25519SecretAsymmetricKey> {
1134    //     let key = get_sosak();
1135    //     let encryption_key = get_sosk();
1136    //     let algorithm = encryption_key
1137    //         .to_byte_algorithm(Some(get_sosn()), |key| async move {
1138    //             key.to_unsealed_entry(".encryptionkey.".to_owned())
1139    //         })
1140    //         .await
1141    //         .unwrap();
1142    //     key.to_sealed_entry(path, algorithm).await.unwrap()
1143    // }
1144
1145    // async fn get_sealed_sosak_with_referenced_key(
1146    //     path: EntryPath,
1147    //     storer: MockStorer,
1148    // ) -> Entry<SodiumOxideCurve25519SecretAsymmetricKey> {
1149    //     let key = get_sosak();
1150    //     let encryption_key = get_sosk();
1151    //     let algorithm = encryption_key
1152    //         .to_byte_algorithm(Some(get_sosn()), |key| async move {
1153    //             key.to_ref_entry(".encryptionkey.".to_owned(), TypeStorer::Mock(storer))
1154    //         })
1155    //         .await
1156    //         .unwrap();
1157    //     key.to_sealed_entry(path, algorithm).await.unwrap()
1158    // }
1159
1160    //////////////////////////////////////
1161    /// SYMMETRIC KEY HELPER FUNCTIONS ///
1162    //////////////////////////////////////
1163    /// Returns the ciphertext for the given text using the key from get_sosk()
1164    /// and the nonce from get_sosn()
1165    fn get_sosk_ciphertext(plaintext: &[u8]) -> Vec<u8> {
1166        let key = get_sosk();
1167        let nonce = get_sosn();
1168        secretbox::seal(plaintext, &nonce.nonce, &key.key)
1169    }
1170
1171    /// Returns the exact same symmetric key on every call
1172    fn get_sosk() -> SodiumOxideSymmetricKey {
1173        let key_bytes: [u8; 32] = [
1174            188, 223, 72, 202, 66, 168, 65, 178, 120, 109, 80, 156, 14, 16, 212, 28, 77, 40, 207,
1175            216, 211, 141, 66, 62, 17, 156, 76, 160, 132, 29, 145, 18,
1176        ];
1177        let soskb = SodiumOxideSymmetricKeyBuilder {};
1178        soskb.build(Some(&key_bytes)).unwrap()
1179    }
1180
1181    /// Returns the exact same symmetric nonce on every call
1182    fn get_sosn() -> SodiumOxideSymmetricNonce {
1183        let nonce_bytes: [u8; 24] = [
1184            13, 7, 8, 143, 25, 5, 250, 134, 70, 171, 199, 182, 68, 69, 45, 89, 178, 90, 14, 31,
1185            220, 196, 79, 116,
1186        ];
1187        SodiumOxideSymmetricNonce {
1188            nonce: ExternalSodiumOxideSymmetricNonce::from_slice(&nonce_bytes).unwrap(),
1189        }
1190    }
1191
1192    // /// Returns the key from get_sosk() wrapped in a States::Unsealed
1193    // fn get_unsealed_sosk(path: EntryPath) -> Entry<SodiumOxideSymmetricKey> {
1194    //     let sosk = get_sosk();
1195    //     sosk.to_unsealed_entry(path).unwrap()
1196    // }
1197
1198    // /// Returns the key from get_sosk() wrapped in a States::Referenced
1199    // fn get_referenced_sosk(path: EntryPath, storer: MockStorer) -> Entry<SodiumOxideSymmetricKey> {
1200    //     let sosk = get_sosk();
1201    //     sosk.to_ref_entry(path, storer).unwrap()
1202    // }
1203
1204    // /// Returns the key from get_sosk() wrapped in a States::Sealed and decrypted
1205    // /// by an unsealed version of the key from get_sosk()
1206    // async fn get_sealed_sosk_with_unsealed_key(path: EntryPath) -> Entry<SodiumOxideSymmetricKey> {
1207    //     let sosk = get_sosk();
1208    //     let encryption_key = get_sosk();
1209    //     let algorithm = encryption_key
1210    //         .to_byte_algorithm(Some(get_sosn()), |key| async move {
1211    //             key.to_unsealed_entry(".encryptionkey.".to_owned())
1212    //         })
1213    //         .await
1214    //         .unwrap();
1215    //     sosk.to_sealed_entry(path, algorithm).await.unwrap()
1216    // }
1217
1218    // /// Returns the key from get_sosk() wrapped in a States::Sealed and decrypted
1219    // /// by a States::Referenced with the given path
1220    // async fn get_sealed_sosk_with_referenced_key(
1221    //     path: EntryPath,
1222    //     storer: MockStorer,
1223    // ) -> Entry<SodiumOxideSymmetricKey> {
1224    //     let sosk = get_sosk();
1225    //     let encryption_key = get_sosk();
1226    //     let algorithm = encryption_key
1227    //         .to_byte_algorithm(Some(get_sosn()), |key| async move {
1228    //             key.to_ref_entry(".encryptionkey.".to_owned(), storer)
1229    //         })
1230    //         .await
1231    //         .unwrap();
1232    //     sosk.to_sealed_entry(path, algorithm).await.unwrap()
1233    // }
1234
1235    ///////////////////////////
1236    /// SYMMETRIC KEY TESTS ///
1237    ///////////////////////////
1238
1239    /// SYMMETRIC BYTE ALGORITHM - SEAL ///
1240    #[tokio::test]
1241    async fn test_seal_symmetricbytealgorithm_with_unsealed_key() {
1242        let data = Data::String("hello, world!".to_owned());
1243        let key = get_sosk();
1244        let algorithm = key
1245            .to_byte_algorithm(Some(get_sosn()), |key| async move {
1246                key.to_unsealed_entry(".encryptionkey.".to_owned())
1247            })
1248            .await
1249            .unwrap();
1250        let ciphertext = algorithm.seal(&data.byte_source()).await.unwrap();
1251        assert_eq!(
1252            ciphertext.get().unwrap(),
1253            get_sosk_ciphertext(b"hello, world!")
1254        );
1255    }
1256
1257    #[tokio::test]
1258    async fn test_seal_symmetricbytealgorithm_with_referenced_key() {
1259        let data = Data::String("hello, world!".to_owned());
1260        let unsealed_key = get_sosk()
1261            .to_unsealed_entry(".encryptionkey.".to_owned())
1262            .unwrap();
1263        let mut storer = MockStorer::new();
1264        storer
1265            .expect_private_get::<SodiumOxideSymmetricKey>()
1266            .withf(|path| path == ".encryptionkey.")
1267            .return_once(move |_| Ok(unsealed_key));
1268        let ref_key = get_sosk()
1269            .to_ref_entry(".encryptionkey.".to_owned(), storer)
1270            .unwrap();
1271        let algorithm = ref_key
1272            .to_symmetric_byte_algorithm(Some(get_sosn()))
1273            .await
1274            .unwrap();
1275        let ciphertext = algorithm.seal(&data.byte_source()).await.unwrap();
1276        assert_eq!(
1277            ciphertext.get().unwrap(),
1278            get_sosk_ciphertext(b"hello, world!")
1279        );
1280    }
1281
1282    #[tokio::test]
1283    async fn test_seal_symmetricbytealgorithm_with_sealed_key_with_unsealed_decryption_key() {
1284        let data = Data::String("hello, world!".to_owned());
1285        let key = get_sosk();
1286        let key_encryption_key = get_sosk();
1287        let key_encryption_algorithm = key_encryption_key
1288            .to_byte_algorithm(Some(get_sosn()), |key| async move {
1289                key.to_unsealed_entry(".keyencryptionkey.".to_owned())
1290            })
1291            .await
1292            .unwrap();
1293        let algorithm = key
1294            .to_byte_algorithm(Some(get_sosn()), |key| async move {
1295                key.to_sealed_entry(".encryptionkey.".to_owned(), key_encryption_algorithm)
1296                    .await
1297            })
1298            .await
1299            .unwrap();
1300        let ciphertext = algorithm.seal(&data.byte_source()).await.unwrap();
1301        assert_eq!(
1302            ciphertext.get().unwrap(),
1303            get_sosk_ciphertext(b"hello, world!")
1304        );
1305    }
1306
1307    #[tokio::test]
1308    async fn test_seal_symmetricbytealgorithm_with_sealed_key_with_referenced_decryption_key() {
1309        let unsealed_key_encryption_key = get_sosk()
1310            .to_unsealed_entry(".keyencryptionkey.".to_owned())
1311            .unwrap();
1312        let mut storer = MockStorer::new();
1313        storer
1314            .expect_private_get::<SodiumOxideSymmetricKey>()
1315            .withf(|path| path == ".keyencryptionkey.")
1316            .return_once(move |_| Ok(unsealed_key_encryption_key));
1317        let data = Data::String("hello, world!".to_owned());
1318        let key = get_sosk();
1319        let referenced_key_encryption_key = get_sosk()
1320            .to_ref_entry(".keyencryptionkey.".to_owned(), storer)
1321            .unwrap();
1322        let key_encryption_algorithm = referenced_key_encryption_key
1323            .to_symmetric_byte_algorithm(Some(get_sosn()))
1324            .await
1325            .unwrap();
1326        let algorithm = key
1327            .to_byte_algorithm(Some(get_sosn()), |key| async move {
1328                key.to_sealed_entry(".encryptionkey.".to_owned(), key_encryption_algorithm)
1329                    .await
1330            })
1331            .await
1332            .unwrap();
1333        let ciphertext = algorithm.seal(&data.byte_source()).await.unwrap();
1334        assert_eq!(
1335            ciphertext.get().unwrap(),
1336            get_sosk_ciphertext(b"hello, world!")
1337        );
1338    }
1339
1340    /// SYMMETRIC BYTE ALGORITHM - UNSEAL ///
1341    #[tokio::test]
1342    async fn test_unseal_symmetricbytealgorithm_with_unsealed_key() {
1343        let data = Data::String("hello, world!".to_owned());
1344        let key = get_sosk();
1345        let algorithm = key
1346            .to_byte_algorithm(Some(get_sosn()), |key| async move {
1347                key.to_unsealed_entry(".encryptionkey.".to_owned())
1348            })
1349            .await
1350            .unwrap();
1351        let ciphertext = get_sosk_ciphertext(data.byte_source().get().unwrap());
1352        let plaintext = algorithm
1353            .unseal(&ByteSource::Vector(
1354                AsRef::<[u8]>::as_ref(&ciphertext).into(),
1355            ))
1356            .await
1357            .unwrap();
1358        assert_eq!(data.byte_source().get().unwrap(), plaintext.get().unwrap());
1359    }
1360
1361    #[tokio::test]
1362    async fn test_unseal_symmetricbytealgorithm_with_referenced_key() {
1363        let data = Data::String("hello, world!".to_owned());
1364        let unsealed_key = get_sosk()
1365            .to_unsealed_entry(".encryptionkey.".to_owned())
1366            .unwrap();
1367        let mut storer = MockStorer::new();
1368        storer
1369            .expect_private_get::<SodiumOxideSymmetricKey>()
1370            .withf(|path| path == ".encryptionkey.")
1371            .return_once(move |_| Ok(unsealed_key));
1372        let ref_key = get_sosk()
1373            .to_ref_entry(".encryptionkey.".to_owned(), storer)
1374            .unwrap();
1375        let algorithm = ref_key
1376            .to_symmetric_byte_algorithm(Some(get_sosn()))
1377            .await
1378            .unwrap();
1379        let ciphertext = get_sosk_ciphertext(data.byte_source().get().unwrap());
1380        let plaintext = algorithm
1381            .unseal(&ByteSource::Vector(
1382                AsRef::<[u8]>::as_ref(&ciphertext).into(),
1383            ))
1384            .await
1385            .unwrap();
1386        assert_eq!(data.byte_source().get().unwrap(), plaintext.get().unwrap());
1387    }
1388
1389    #[tokio::test]
1390    async fn test_unseal_symmetricbytealgorithm_with_sealed_key_with_unsealed_decryption_key() {
1391        let data = Data::String("hello, world!".to_owned());
1392        let key = get_sosk();
1393        let key_encryption_key = get_sosk();
1394        let key_encryption_algorithm = key_encryption_key
1395            .to_byte_algorithm(Some(get_sosn()), |key| async move {
1396                key.to_unsealed_entry(".keyencryptionkey.".to_owned())
1397            })
1398            .await
1399            .unwrap();
1400        let algorithm = key
1401            .to_byte_algorithm(Some(get_sosn()), |key| async move {
1402                key.to_sealed_entry(".encryptionkey.".to_owned(), key_encryption_algorithm)
1403                    .await
1404            })
1405            .await
1406            .unwrap();
1407        let ciphertext = get_sosk_ciphertext(data.byte_source().get().unwrap());
1408        let plaintext = algorithm
1409            .unseal(&ByteSource::Vector(
1410                AsRef::<[u8]>::as_ref(&ciphertext).into(),
1411            ))
1412            .await
1413            .unwrap();
1414        assert_eq!(data.byte_source().get().unwrap(), plaintext.get().unwrap());
1415    }
1416
1417    #[tokio::test]
1418    async fn test_unseal_symmetricbytealgorithm_with_sealed_key_with_referenced_decryption_key() {
1419        let unsealed_key_encryption_key = get_sosk()
1420            .to_unsealed_entry(".keyencryptionkey.".to_owned())
1421            .unwrap();
1422        let mut storer = MockStorer::new();
1423        storer
1424            .expect_private_get::<SodiumOxideSymmetricKey>()
1425            .withf(|path| path == ".keyencryptionkey.")
1426            .return_once(move |_| Ok(unsealed_key_encryption_key));
1427        let data = Data::String("hello, world!".to_owned());
1428        let key = get_sosk();
1429        let referenced_key_encryption_key = get_sosk()
1430            .to_ref_entry(".keyencryptionkey.".to_owned(), storer)
1431            .unwrap();
1432        let key_encryption_algorithm = referenced_key_encryption_key
1433            .to_symmetric_byte_algorithm(Some(get_sosn()))
1434            .await
1435            .unwrap();
1436        let algorithm = key
1437            .to_byte_algorithm(Some(get_sosn()), |key| async move {
1438                key.to_sealed_entry(".encryptionkey.".to_owned(), key_encryption_algorithm)
1439                    .await
1440            })
1441            .await
1442            .unwrap();
1443        let ciphertext = get_sosk_ciphertext(data.byte_source().get().unwrap());
1444        let plaintext = algorithm
1445            .unseal(&ByteSource::Vector(
1446                AsRef::<[u8]>::as_ref(&ciphertext).into(),
1447            ))
1448            .await
1449            .unwrap();
1450        assert_eq!(data.byte_source().get().unwrap(), plaintext.get().unwrap());
1451    }
1452
1453    /// SYMMETRIC KEY - BUILDER ///
1454    #[test]
1455    fn test_sodiumoxidesymmetrickeybuilder_build_valid() {
1456        let soskb = SodiumOxideSymmetricKeyBuilder {};
1457        let external_key = secretbox::gen_key();
1458        let key = soskb.build(Some(external_key.as_ref())).unwrap();
1459        assert_eq!(key.key.as_ref(), external_key.as_ref());
1460    }
1461
1462    #[test]
1463    #[should_panic]
1464    fn test_sodiumoxidesymmetrickeybuilder_build_invalid() {
1465        let soskb = SodiumOxideSymmetricKeyBuilder {};
1466        let _ = soskb.build(Some(b"bla")).unwrap();
1467    }
1468
1469    #[test]
1470    fn test_sodiumoxidesymmetrickeybuilder_from_typebuildercontainer_valid() {
1471        let tbc = TypeBuilderContainer(TypeBuilder::Key(KeyBuilder::Symmetric(
1472            SymmetricKeyBuilder::SodiumOxide(SodiumOxideSymmetricKeyBuilder {}),
1473        )));
1474        let soskb: SodiumOxideSymmetricKeyBuilder = tbc.try_into().unwrap();
1475        let key = SodiumOxideSymmetricKey::new();
1476        soskb.build(Some(key.key.as_ref())).unwrap();
1477    }
1478
1479    #[test]
1480    #[should_panic]
1481    fn test_sodiumoxidesymmetrickeybuilder_from_typebuildercontainer_invalid() {
1482        let tbc = TypeBuilderContainer(TypeBuilder::Data(DataBuilder::Bool(BoolDataBuilder {})));
1483        let _: SodiumOxideSymmetricKeyBuilder = tbc.try_into().unwrap();
1484    }
1485
1486    /// SYMMETRIC KEY - SEAL AND UNSEAL ///
1487    #[test]
1488    fn test_seal_symmetrickey() {
1489        let plaintext = "hello, world!".into();
1490        let sosk = get_sosk();
1491        let (cipher_source, _) = sosk.seal(&plaintext, Some(&get_sosn())).unwrap();
1492        assert_eq!(
1493            get_sosk_ciphertext(b"hello, world!"),
1494            cipher_source.get().unwrap().to_vec(),
1495        );
1496    }
1497
1498    #[test]
1499    #[should_panic(expected = "CiphertextFailedVerification")]
1500    fn test_symmetrickey_unseal_with_invalid_bytes() {
1501        let sosk = get_sosk();
1502        let ciphertext = "bla".into();
1503        let _ = sosk.unseal(&ciphertext, &get_sosn()).unwrap();
1504    }
1505
1506    #[test]
1507    #[should_panic(expected = "CiphertextFailedVerification")]
1508    fn test_symmetrickey_unseal_with_invalid_nonce() {
1509        let sosk = get_sosk();
1510        let ciphertext = get_sosk_ciphertext(b"hello, world!");
1511        let _ = sosk
1512            .unseal(
1513                &ciphertext.as_slice().into(),
1514                &SodiumOxideSymmetricNonce {
1515                    nonce: secretbox::gen_nonce(),
1516                },
1517            )
1518            .unwrap();
1519    }
1520
1521    #[test]
1522    fn test_symmetrickey_to_index() {
1523        let index = SodiumOxideSymmetricKey::get_index();
1524        assert_eq!(
1525            index,
1526            Some(bson::doc! {
1527            "c": {
1528                "builder": {
1529            "t": "Key",
1530            "c": {
1531                "t": "Symmetric",
1532            "c": {
1533            "t": "SodiumOxide"
1534            }
1535            }
1536                }
1537            }
1538                })
1539        )
1540    }
1541
1542    #[test]
1543    fn test_symmetrickey_to_builder() {
1544        let sosk = SodiumOxideSymmetricKey::new();
1545        let builder = sosk.builder();
1546        let key_bytes = sosk.key.as_ref();
1547        let built_key = builder.build(Some(key_bytes)).unwrap();
1548        assert_eq!(built_key.key.as_ref(), sosk.key.as_ref());
1549    }
1550
1551    #[test]
1552    fn test_symmetrickey_new() {
1553        let sosk = SodiumOxideSymmetricKey::new();
1554        assert!(!sosk.key.as_ref().is_empty());
1555    }
1556
1557    ///////////////////////////////////
1558    /// SECRET ASYMMETRIC KEY TESTS ///
1559    ///////////////////////////////////
1560
1561    /// SECRET ASYMMETRIC BYTE ALGORITHM - SEAL ///
1562    #[tokio::test]
1563    async fn test_seal_secretasymmetricbytealgorithm_with_unsealed_key() {
1564        let data = Data::String("hello, world!".to_owned());
1565        let alice_key = get_sosak()
1566            .to_unsealed_entry(".alicesecretkey.".to_owned())
1567            .unwrap();
1568        let bob_key = SodiumOxideCurve25519SecretAsymmetricKey::new()
1569            .public_key()
1570            .unwrap()
1571            .to_unsealed_entry(".bobpublickey.".to_owned())
1572            .unwrap();
1573        let bob_key_bytes = bob_key.resolve().await.unwrap().byte_source();
1574        let algorithm = alice_key
1575            .to_secret_asymmetric_byte_algorithm(Some(bob_key), Some(get_soan()))
1576            .await
1577            .unwrap();
1578        let ciphertext = algorithm.seal(&data.byte_source()).await.unwrap();
1579        let bob_key_copy = SodiumOxideCurve25519PublicAsymmetricKeyBuilder {}
1580            .build(Some(bob_key_bytes.get().unwrap()))
1581            .unwrap();
1582        assert_eq!(
1583            ciphertext.get().unwrap(),
1584            get_sosak_ciphertext(b"hello, world!", &Some(bob_key_copy))
1585        );
1586    }
1587
1588    #[tokio::test]
1589    async fn test_seal_secretasymmetricbytealgorithm_with_referenced_key() {
1590        let data = Data::String("hello, world!".to_owned());
1591        let unsealed_alice_key = get_sosak()
1592            .to_unsealed_entry(".alicesecretkey.".to_owned())
1593            .unwrap();
1594        let unsealed_bob_key = SodiumOxideCurve25519SecretAsymmetricKey::new()
1595            .public_key()
1596            .unwrap()
1597            .to_unsealed_entry(".bobpublickey.".to_owned())
1598            .unwrap();
1599        let bob_key_bytes = unsealed_bob_key.resolve().await.unwrap().byte_source();
1600        let mut storer = MockIndexedStorer::new();
1601        storer
1602            .expect_private_get::<SodiumOxideCurve25519SecretAsymmetricKey>()
1603            .withf(|path| path == ".alicesecretkey.")
1604            .return_once(move |_| Ok(unsealed_alice_key));
1605        let ref_alice_key = get_sosak()
1606            .to_ref_entry(".alicesecretkey.".to_owned(), storer)
1607            .unwrap();
1608        let algorithm = ref_alice_key
1609            .to_secret_asymmetric_byte_algorithm(Some(unsealed_bob_key), Some(get_soan()))
1610            .await
1611            .unwrap();
1612        let ciphertext = algorithm.seal(&data.byte_source()).await.unwrap();
1613        let bob_key_copy = SodiumOxideCurve25519PublicAsymmetricKeyBuilder {}
1614            .build(Some(bob_key_bytes.get().unwrap()))
1615            .unwrap();
1616        assert_eq!(
1617            ciphertext.get().unwrap(),
1618            get_sosak_ciphertext(b"hello, world!", &Some(bob_key_copy))
1619        );
1620    }
1621
1622    #[tokio::test]
1623    async fn test_seal_secretasymmetricbytealgorithm_with_sealed_key_with_unsealed_decryption_key()
1624    {
1625        let data = Data::String("hello, world!".to_owned());
1626        let alice_decryption_key = get_sosk()
1627            .to_unsealed_entry(".alicedecryptionkey.".to_owned())
1628            .unwrap();
1629        let alice_decryption_algorithm = alice_decryption_key
1630            .to_symmetric_byte_algorithm(Some(get_sosn()))
1631            .await
1632            .unwrap();
1633        let alice_key = get_sosak()
1634            .to_sealed_entry(".alicesecretkey.".to_owned(), alice_decryption_algorithm)
1635            .await
1636            .unwrap();
1637        let bob_key = SodiumOxideCurve25519SecretAsymmetricKey::new()
1638            .public_key()
1639            .unwrap()
1640            .to_unsealed_entry(".bobpublickey.".to_owned())
1641            .unwrap();
1642        let bob_key_bytes = bob_key.resolve().await.unwrap().byte_source();
1643        let algorithm = alice_key
1644            .to_secret_asymmetric_byte_algorithm(Some(bob_key), Some(get_soan()))
1645            .await
1646            .unwrap();
1647        let ciphertext = algorithm.seal(&data.byte_source()).await.unwrap();
1648        let bob_key_copy = SodiumOxideCurve25519PublicAsymmetricKeyBuilder {}
1649            .build(Some(bob_key_bytes.get().unwrap()))
1650            .unwrap();
1651        assert_eq!(
1652            ciphertext.get().unwrap(),
1653            get_sosak_ciphertext(b"hello, world!", &Some(bob_key_copy))
1654        );
1655    }
1656
1657    #[tokio::test]
1658    async fn test_seal_secretasymmetricbytealgorithm_with_sealed_key_with_referenced_decryption_key(
1659    ) {
1660        let data = Data::String("hello, world!".to_owned());
1661        let unsealed_alice_decryption_key = get_sosk()
1662            .to_unsealed_entry(".alicedecryptionkey.".to_owned())
1663            .unwrap();
1664        let mut storer = MockStorer::new();
1665        storer
1666            .expect_private_get::<SodiumOxideSymmetricKey>()
1667            .withf(|path| path == ".alicedecryptionkey.")
1668            .return_once(move |_| Ok(unsealed_alice_decryption_key));
1669        let ref_alice_decryption_key = get_sosk()
1670            .to_ref_entry(".alicedecryptionkey.".to_owned(), storer)
1671            .unwrap();
1672        let alice_decryption_algorithm = ref_alice_decryption_key
1673            .to_symmetric_byte_algorithm(Some(get_sosn()))
1674            .await
1675            .unwrap();
1676        let sealed_alice_key = get_sosak()
1677            .to_sealed_entry(".alicesecretkey.".to_owned(), alice_decryption_algorithm)
1678            .await
1679            .unwrap();
1680        let unsealed_bob_key = SodiumOxideCurve25519SecretAsymmetricKey::new()
1681            .public_key()
1682            .unwrap()
1683            .to_unsealed_entry(".bobpublickey.".to_owned())
1684            .unwrap();
1685        let bob_key_bytes = unsealed_bob_key.resolve().await.unwrap().byte_source();
1686        let algorithm = sealed_alice_key
1687            .to_secret_asymmetric_byte_algorithm(Some(unsealed_bob_key), Some(get_soan()))
1688            .await
1689            .unwrap();
1690        let ciphertext = algorithm.seal(&data.byte_source()).await.unwrap();
1691        let bob_key_copy = SodiumOxideCurve25519PublicAsymmetricKeyBuilder {}
1692            .build(Some(bob_key_bytes.get().unwrap()))
1693            .unwrap();
1694        assert_eq!(
1695            ciphertext.get().unwrap(),
1696            get_sosak_ciphertext(b"hello, world!", &Some(bob_key_copy))
1697        );
1698    }
1699
1700    /// SECRET ASYMMETRIC BYTE ALGORITHM - UNSEAL ///
1701    #[tokio::test]
1702    async fn test_unseal_secretasymmetricbytealgorithm_with_unsealed_key() {
1703        let data = Data::String("hello, world!".to_owned());
1704        let alice_key = get_sosak()
1705            .to_unsealed_entry(".alicesecretkey.".to_owned())
1706            .unwrap();
1707        let bob_key = SodiumOxideCurve25519SecretAsymmetricKey::new()
1708            .public_key()
1709            .unwrap()
1710            .to_unsealed_entry(".bobpublickey.".to_owned())
1711            .unwrap();
1712        let bob_key_bytes = bob_key.resolve().await.unwrap().byte_source();
1713        let bob_key_copy = SodiumOxideCurve25519PublicAsymmetricKeyBuilder {}
1714            .build(Some(bob_key_bytes.get().unwrap()))
1715            .unwrap();
1716        let ciphertext = get_sosak_ciphertext(b"hello, world!", &Some(bob_key_copy));
1717        let algorithm = alice_key
1718            .to_secret_asymmetric_byte_algorithm(Some(bob_key), Some(get_soan()))
1719            .await
1720            .unwrap();
1721        let plaintext = algorithm
1722            .unseal(&ByteSource::Vector(
1723                AsRef::<[u8]>::as_ref(&ciphertext).into(),
1724            ))
1725            .await
1726            .unwrap();
1727        assert_eq!(data.byte_source().get().unwrap(), plaintext.get().unwrap());
1728    }
1729
1730    #[tokio::test]
1731    async fn test_unseal_secretasymmetricbytealgorithm_with_referenced_key() {
1732        let data = Data::String("hello, world!".to_owned());
1733        let unsealed_alice_key = get_sosak()
1734            .to_unsealed_entry(".alicesecretkey.".to_owned())
1735            .unwrap();
1736        let unsealed_bob_key = SodiumOxideCurve25519SecretAsymmetricKey::new()
1737            .public_key()
1738            .unwrap()
1739            .to_unsealed_entry(".bobpublickey.".to_owned())
1740            .unwrap();
1741        let bob_key_bytes = unsealed_bob_key.resolve().await.unwrap().byte_source();
1742        let bob_key_copy = SodiumOxideCurve25519PublicAsymmetricKeyBuilder {}
1743            .build(Some(bob_key_bytes.get().unwrap()))
1744            .unwrap();
1745        let mut storer = MockStorer::new();
1746        storer
1747            .expect_private_get::<SodiumOxideCurve25519SecretAsymmetricKey>()
1748            .withf(|path| path == ".alicesecretkey.")
1749            .return_once(move |_| Ok(unsealed_alice_key));
1750        let ref_alice_key = get_sosak()
1751            .to_ref_entry(".alicesecretkey.".to_owned(), storer)
1752            .unwrap();
1753        let ciphertext = get_sosak_ciphertext(b"hello, world!", &Some(bob_key_copy));
1754        let algorithm = ref_alice_key
1755            .to_secret_asymmetric_byte_algorithm(Some(unsealed_bob_key), Some(get_soan()))
1756            .await
1757            .unwrap();
1758        let plaintext = algorithm
1759            .unseal(&ByteSource::Vector(
1760                AsRef::<[u8]>::as_ref(&ciphertext).into(),
1761            ))
1762            .await
1763            .unwrap();
1764        assert_eq!(data.byte_source().get().unwrap(), plaintext.get().unwrap());
1765    }
1766
1767    #[tokio::test]
1768    async fn test_unseal_secretasymmetricbytealgorithm_with_sealed_key_with_unsealed_decryption_key(
1769    ) {
1770        let data = Data::String("hello, world!".to_owned());
1771        let alice_decryption_key = get_sosk()
1772            .to_unsealed_entry(".alicedecryptionkey.".to_owned())
1773            .unwrap();
1774        let alice_decryption_algorithm = alice_decryption_key
1775            .to_symmetric_byte_algorithm(Some(get_sosn()))
1776            .await
1777            .unwrap();
1778        let alice_key = get_sosak()
1779            .to_sealed_entry(".alicesecretkey.".to_owned(), alice_decryption_algorithm)
1780            .await
1781            .unwrap();
1782        let bob_key = SodiumOxideCurve25519SecretAsymmetricKey::new()
1783            .public_key()
1784            .unwrap()
1785            .to_unsealed_entry(".bobpublickey.".to_owned())
1786            .unwrap();
1787        let bob_key_bytes = bob_key.resolve().await.unwrap().byte_source();
1788        let bob_key_copy = SodiumOxideCurve25519PublicAsymmetricKeyBuilder {}
1789            .build(Some(bob_key_bytes.get().unwrap()))
1790            .unwrap();
1791        let ciphertext = get_sosak_ciphertext(b"hello, world!", &Some(bob_key_copy));
1792        let algorithm = alice_key
1793            .to_secret_asymmetric_byte_algorithm(Some(bob_key), Some(get_soan()))
1794            .await
1795            .unwrap();
1796        let plaintext = algorithm
1797            .unseal(&ByteSource::Vector(
1798                AsRef::<[u8]>::as_ref(&ciphertext).into(),
1799            ))
1800            .await
1801            .unwrap();
1802        assert_eq!(data.byte_source().get().unwrap(), plaintext.get().unwrap());
1803    }
1804
1805    #[tokio::test]
1806    async fn test_unseal_secretasymmetricbytealgorithm_with_sealed_key_with_referenced_decryption_key(
1807    ) {
1808        let data = Data::String("hello, world!".to_owned());
1809        let unsealed_alice_decryption_key = get_sosk()
1810            .to_unsealed_entry(".alicedecryptionkey.".to_owned())
1811            .unwrap();
1812        let mut storer = MockStorer::new();
1813        storer
1814            .expect_private_get::<SodiumOxideSymmetricKey>()
1815            .withf(|path| path == ".alicedecryptionkey.")
1816            .return_once(move |_| Ok(unsealed_alice_decryption_key));
1817        let ref_alice_decryption_key = get_sosk()
1818            .to_ref_entry(".alicedecryptionkey.".to_owned(), storer)
1819            .unwrap();
1820        let alice_decryption_algorithm = ref_alice_decryption_key
1821            .to_symmetric_byte_algorithm(Some(get_sosn()))
1822            .await
1823            .unwrap();
1824        let sealed_alice_key = get_sosak()
1825            .to_sealed_entry(".alicesecretkey.".to_owned(), alice_decryption_algorithm)
1826            .await
1827            .unwrap();
1828        let unsealed_bob_key = SodiumOxideCurve25519SecretAsymmetricKey::new()
1829            .public_key()
1830            .unwrap()
1831            .to_unsealed_entry(".bobpublickey.".to_owned())
1832            .unwrap();
1833        let bob_key_bytes = unsealed_bob_key.resolve().await.unwrap().byte_source();
1834        let bob_key_copy = SodiumOxideCurve25519PublicAsymmetricKeyBuilder {}
1835            .build(Some(bob_key_bytes.get().unwrap()))
1836            .unwrap();
1837        let ciphertext = get_sosak_ciphertext(b"hello, world!", &Some(bob_key_copy));
1838        let algorithm = sealed_alice_key
1839            .to_secret_asymmetric_byte_algorithm(Some(unsealed_bob_key), Some(get_soan()))
1840            .await
1841            .unwrap();
1842        let plaintext = algorithm
1843            .unseal(&ByteSource::Vector(
1844                AsRef::<[u8]>::as_ref(&ciphertext).into(),
1845            ))
1846            .await
1847            .unwrap();
1848        assert_eq!(data.byte_source().get().unwrap(), plaintext.get().unwrap(),);
1849    }
1850
1851    /// SECRET ASYMMETRIC KEY - BUILDER \\\
1852    #[test]
1853    fn test_sodiumoxidesecretasymmetrickeybuilder_build_valid() {
1854        let sosakb = SodiumOxideCurve25519SecretAsymmetricKeyBuilder {};
1855        let (_, sk) = box_::gen_keypair();
1856        let key = sosakb.build(Some(sk.as_ref())).unwrap();
1857        assert_eq!(key.secret_key.as_ref(), sk.as_ref());
1858    }
1859
1860    #[test]
1861    #[should_panic]
1862    fn test_sodiumoxidesecretasymmetrickeybuilder_build_invalid() {
1863        let sosakb = SodiumOxideCurve25519SecretAsymmetricKeyBuilder {};
1864        let _ = sosakb.build(Some(b"bla")).unwrap();
1865    }
1866
1867    #[test]
1868    fn test_sodiumoxidesecretasymmetrickeybuilder_from_typebuildercontainer_valid() {
1869        let tbc = TypeBuilderContainer(TypeBuilder::Key(KeyBuilder::Asymmetric(
1870            AsymmetricKeyBuilder::Secret(SecretAsymmetricKeyBuilder::SodiumOxideCurve25519(
1871                SodiumOxideCurve25519SecretAsymmetricKeyBuilder {},
1872            )),
1873        )));
1874        let sosakb: SodiumOxideCurve25519SecretAsymmetricKeyBuilder = tbc.try_into().unwrap();
1875        let key = SodiumOxideCurve25519SecretAsymmetricKey::new();
1876        sosakb.build(Some(key.secret_key.as_ref())).unwrap();
1877    }
1878
1879    #[test]
1880    #[should_panic]
1881    fn test_sodiumoxidesecretasymmetrickeybuilder_from_typebuildercontainer_invalid() {
1882        let tbc = TypeBuilderContainer(TypeBuilder::Data(DataBuilder::Bool(BoolDataBuilder {})));
1883        let _: SodiumOxideCurve25519SecretAsymmetricKeyBuilder = tbc.try_into().unwrap();
1884    }
1885
1886    /// SECRET ASYMMETRIC KEY - SEAL AND UNSEAL ///
1887    #[test]
1888    fn test_seal_secretasymmetrickey_with_non_referenced_key() {
1889        let plaintext = "hello, world!".into();
1890        let sosak = get_sosak();
1891        let (cipher_source, _) = sosak.seal(&plaintext, None, Some(&get_soan())).unwrap();
1892        assert_eq!(
1893            get_sosak_ciphertext(b"hello, world!", &None),
1894            cipher_source.get().unwrap().to_vec(),
1895        );
1896    }
1897
1898    #[test]
1899    #[should_panic(expected = "CiphertextFailedVerification")]
1900    fn test_secretasymmetrickey_unseal_with_invalid_bytes() {
1901        let sosak = get_sosak();
1902        let ciphertext = "bla".into();
1903        let _ = sosak.unseal(&ciphertext, None, &get_soan()).unwrap();
1904    }
1905
1906    #[test]
1907    #[should_panic(expected = "CiphertextFailedVerification")]
1908    fn test_secretasymmetrickey_unseal_with_invalid_nonce() {
1909        let sosak = get_sosak();
1910        let ciphertext = get_sosak_ciphertext(b"hello, world!", &None);
1911        let _ = sosak
1912            .unseal(
1913                &ciphertext.as_slice().into(),
1914                None,
1915                &SodiumOxideAsymmetricNonce {
1916                    nonce: box_::gen_nonce(),
1917                },
1918            )
1919            .unwrap();
1920    }
1921
1922    #[test]
1923    fn test_secretasymmetrickey_to_index() {
1924        let index = SodiumOxideCurve25519SecretAsymmetricKey::get_index();
1925        assert_eq!(
1926            index,
1927            Some(bson::doc! {
1928                "c": {
1929                    "builder": {
1930                "t": "Key",
1931                "c": {
1932                    "t": "Asymmetric",
1933                "c": {
1934            "t": "Secret",
1935                "c": {
1936                "t": "SodiumOxideCurve25519"
1937                }
1938                }
1939                }
1940                    }
1941                }
1942                    })
1943        )
1944    }
1945
1946    #[test]
1947    fn test_secretasymmetrickey_to_builder() {
1948        let sosak = SodiumOxideCurve25519SecretAsymmetricKey::new();
1949        let builder = sosak.builder();
1950        let key_bytes = sosak.secret_key.as_ref();
1951        let built_key = builder.build(Some(key_bytes)).unwrap();
1952        assert_eq!(built_key.secret_key.as_ref(), sosak.secret_key.as_ref());
1953    }
1954
1955    #[test]
1956    fn test_secretasymmetrickey_new() {
1957        let sosak = SodiumOxideCurve25519SecretAsymmetricKey::new();
1958        assert!(!sosak.secret_key.as_ref().is_empty());
1959    }
1960
1961    ///////////////////////////////////
1962    /// PUBLIC ASYMMETRIC KEY TESTS ///
1963    ///////////////////////////////////
1964
1965    /// PUBLIC ASYMMETRIC BYTE ALGORITHM - SEAL ///
1966    #[tokio::test]
1967    async fn test_seal_publicasymmetricbytealgorithm_with_unsealed_key() {
1968        let data = Data::String("hello, world!".to_owned());
1969        let (alice_public_key, _) = get_sopak();
1970        let unsealed_alice_public_key = alice_public_key
1971            .to_unsealed_entry(".alicepublickey.".to_owned())
1972            .unwrap();
1973        let bob_key = SodiumOxideCurve25519SecretAsymmetricKey::new()
1974            .to_unsealed_entry(".bobsecretkey.".to_owned())
1975            .unwrap();
1976        let bob_key_bytes = bob_key.resolve().await.unwrap().byte_source();
1977        let algorithm = unsealed_alice_public_key
1978            .to_public_asymmetric_byte_algorithm(bob_key, Some(get_soan()))
1979            .await
1980            .unwrap();
1981        let ciphertext = algorithm.seal(&data.byte_source()).await.unwrap();
1982        let bob_key_copy = SodiumOxideCurve25519SecretAsymmetricKeyBuilder {}
1983            .build(Some(bob_key_bytes.get().unwrap()))
1984            .unwrap();
1985        assert_eq!(
1986            ciphertext.get().unwrap(),
1987            get_sopak_ciphertext(b"hello, world!", Some(&bob_key_copy))
1988        );
1989    }
1990
1991    #[tokio::test]
1992    async fn test_seal_publicasymmetricbytealgorithm_with_referenced_key() {
1993        let data = Data::String("hello, world!".to_owned());
1994        let (alice_public_key, _) = get_sopak();
1995        let unsealed_alice_public_key = alice_public_key
1996            .to_unsealed_entry(".alicepublickey.".to_owned())
1997            .unwrap();
1998        let unsealed_bob_key = SodiumOxideCurve25519SecretAsymmetricKey::new()
1999            .to_unsealed_entry(".bobsecretkey.".to_owned())
2000            .unwrap();
2001        let bob_key_bytes = unsealed_bob_key.resolve().await.unwrap().byte_source();
2002        let mut storer = MockStorer::new();
2003        storer
2004            .expect_private_get::<SodiumOxideCurve25519PublicAsymmetricKey>()
2005            .withf(|path| path == ".alicepublickey.")
2006            .return_once(move |_| Ok(unsealed_alice_public_key));
2007        let (alice_public_key, _) = get_sopak();
2008        let ref_alice_public_key = alice_public_key
2009            .to_ref_entry(".alicepublickey.".to_owned(), storer)
2010            .unwrap();
2011        let algorithm = ref_alice_public_key
2012            .to_public_asymmetric_byte_algorithm(unsealed_bob_key, Some(get_soan()))
2013            .await
2014            .unwrap();
2015        let ciphertext = algorithm.seal(&data.byte_source()).await.unwrap();
2016        let bob_key_copy = SodiumOxideCurve25519SecretAsymmetricKeyBuilder {}
2017            .build(Some(bob_key_bytes.get().unwrap()))
2018            .unwrap();
2019        assert_eq!(
2020            ciphertext.get().unwrap(),
2021            get_sopak_ciphertext(b"hello, world!", Some(&bob_key_copy))
2022        );
2023    }
2024
2025    #[tokio::test]
2026    async fn test_seal_publicasymmetricbytealgorithm_with_sealed_key_with_unsealed_decryption_key()
2027    {
2028        let data = Data::String("hello, world!".to_owned());
2029        let alice_decryption_key = get_sosk()
2030            .to_unsealed_entry(".alicedecryptionkey.".to_owned())
2031            .unwrap();
2032        let alice_decryption_algorithm = alice_decryption_key
2033            .to_symmetric_byte_algorithm(Some(get_sosn()))
2034            .await
2035            .unwrap();
2036        let (alice_public_key, _) = get_sopak();
2037        let sealed_alice_public_key = alice_public_key
2038            .to_sealed_entry(".alicepublickey.".to_owned(), alice_decryption_algorithm)
2039            .await
2040            .unwrap();
2041        let bob_key = SodiumOxideCurve25519SecretAsymmetricKey::new()
2042            .to_unsealed_entry(".bobsecretkey.".to_owned())
2043            .unwrap();
2044        let bob_key_bytes = bob_key.resolve().await.unwrap().byte_source();
2045        let algorithm = sealed_alice_public_key
2046            .to_public_asymmetric_byte_algorithm(bob_key, Some(get_soan()))
2047            .await
2048            .unwrap();
2049        let ciphertext = algorithm.seal(&data.byte_source()).await.unwrap();
2050        let bob_key_copy = SodiumOxideCurve25519SecretAsymmetricKeyBuilder {}
2051            .build(Some(bob_key_bytes.get().unwrap()))
2052            .unwrap();
2053        assert_eq!(
2054            ciphertext.get().unwrap(),
2055            get_sopak_ciphertext(b"hello, world!", Some(&bob_key_copy))
2056        );
2057    }
2058
2059    #[tokio::test]
2060    async fn test_seal_publicasymmetricbytealgorithm_with_sealed_key_with_referenced_decryption_key(
2061    ) {
2062        let data = Data::String("hello, world!".to_owned());
2063        let unsealed_alice_decryption_key = get_sosk()
2064            .to_unsealed_entry(".alicedecryptionkey.".to_owned())
2065            .unwrap();
2066        let mut storer = MockStorer::new();
2067        storer
2068            .expect_private_get::<SodiumOxideSymmetricKey>()
2069            .withf(|path| path == ".alicedecryptionkey.")
2070            .return_once(move |_| Ok(unsealed_alice_decryption_key));
2071        let ref_alice_decryption_key = get_sosk()
2072            .to_ref_entry(".alicedecryptionkey.".to_owned(), storer)
2073            .unwrap();
2074        let alice_decryption_algorithm = ref_alice_decryption_key
2075            .to_symmetric_byte_algorithm(Some(get_sosn()))
2076            .await
2077            .unwrap();
2078        let (alice_public_key, _) = get_sopak();
2079        let sealed_alice_public_key = alice_public_key
2080            .to_sealed_entry(".alicepublickey.".to_owned(), alice_decryption_algorithm)
2081            .await
2082            .unwrap();
2083        let unsealed_bob_key = SodiumOxideCurve25519SecretAsymmetricKey::new()
2084            .to_unsealed_entry(".bobsecretkey.".to_owned())
2085            .unwrap();
2086        let bob_key_bytes = unsealed_bob_key.resolve().await.unwrap().byte_source();
2087        let algorithm = sealed_alice_public_key
2088            .to_public_asymmetric_byte_algorithm(unsealed_bob_key, Some(get_soan()))
2089            .await
2090            .unwrap();
2091        let ciphertext = algorithm.seal(&data.byte_source()).await.unwrap();
2092        let bob_key_copy = SodiumOxideCurve25519SecretAsymmetricKeyBuilder {}
2093            .build(Some(bob_key_bytes.get().unwrap()))
2094            .unwrap();
2095        assert_eq!(
2096            ciphertext.get().unwrap(),
2097            get_sopak_ciphertext(b"hello, world!", Some(&bob_key_copy))
2098        );
2099    }
2100
2101    /// PUBLIC ASYMMETRIC BYTE ALGORITHM - UNSEAL ///
2102    #[tokio::test]
2103    async fn test_unseal_publicasymmetricbytealgorithm_with_unsealed_key() {
2104        let data = Data::String("hello, world!".to_owned());
2105        let (alice_public_key, _) = get_sopak();
2106        let unsealed_alice_public_key = alice_public_key
2107            .to_unsealed_entry(".alicepublickey.".to_owned())
2108            .unwrap();
2109        let bob_key = SodiumOxideCurve25519SecretAsymmetricKey::new()
2110            .to_unsealed_entry(".bobsecretkey.".to_owned())
2111            .unwrap();
2112        let bob_key_bytes = bob_key.resolve().await.unwrap().byte_source();
2113        let bob_key_copy = SodiumOxideCurve25519SecretAsymmetricKeyBuilder {}
2114            .build(Some(bob_key_bytes.get().unwrap()))
2115            .unwrap();
2116        let ciphertext = get_sopak_ciphertext(b"hello, world!", Some(&bob_key_copy));
2117        let algorithm = unsealed_alice_public_key
2118            .to_public_asymmetric_byte_algorithm(bob_key, Some(get_soan()))
2119            .await
2120            .unwrap();
2121        let plaintext = algorithm
2122            .unseal(&ByteSource::Vector(
2123                AsRef::<[u8]>::as_ref(&ciphertext).into(),
2124            ))
2125            .await
2126            .unwrap();
2127        assert_eq!(data.byte_source().get().unwrap(), plaintext.get().unwrap());
2128    }
2129
2130    #[tokio::test]
2131    async fn test_unseal_publicasymmetricbytealgorithm_with_referenced_key() {
2132        let data = Data::String("hello, world!".to_owned());
2133        let (alice_public_key, _) = get_sopak();
2134        let unsealed_alice_public_key = alice_public_key
2135            .to_unsealed_entry(".alicepublickey.".to_owned())
2136            .unwrap();
2137        let unsealed_bob_key = SodiumOxideCurve25519SecretAsymmetricKey::new()
2138            .to_unsealed_entry(".bobsecretkey.".to_owned())
2139            .unwrap();
2140        let bob_key_bytes = unsealed_bob_key.resolve().await.unwrap().byte_source();
2141        let bob_key_copy = SodiumOxideCurve25519SecretAsymmetricKeyBuilder {}
2142            .build(Some(bob_key_bytes.get().unwrap()))
2143            .unwrap();
2144        let mut storer = MockStorer::new();
2145        storer
2146            .expect_private_get::<SodiumOxideCurve25519PublicAsymmetricKey>()
2147            .withf(|path| path == ".alicepublickey.")
2148            .return_once(move |_| Ok(unsealed_alice_public_key));
2149        let (alice_public_key, _) = get_sopak();
2150        let ref_alice_public_key = alice_public_key
2151            .to_ref_entry(".alicepublickey.".to_owned(), storer)
2152            .unwrap();
2153        let ciphertext = get_sopak_ciphertext(b"hello, world!", Some(&bob_key_copy));
2154        let algorithm = ref_alice_public_key
2155            .to_public_asymmetric_byte_algorithm(unsealed_bob_key, Some(get_soan()))
2156            .await
2157            .unwrap();
2158        let plaintext = algorithm
2159            .unseal(&ByteSource::Vector(
2160                AsRef::<[u8]>::as_ref(&ciphertext).into(),
2161            ))
2162            .await
2163            .unwrap();
2164        assert_eq!(data.byte_source().get().unwrap(), plaintext.get().unwrap());
2165    }
2166
2167    #[tokio::test]
2168    async fn test_unseal_publicasymmetricbytealgorithm_with_sealed_key_with_unsealed_decryption_key(
2169    ) {
2170        let data = Data::String("hello, world!".to_owned());
2171        let alice_decryption_key = get_sosk()
2172            .to_unsealed_entry(".alicedecryptionkey.".to_owned())
2173            .unwrap();
2174        let alice_decryption_algorithm = alice_decryption_key
2175            .to_symmetric_byte_algorithm(Some(get_sosn()))
2176            .await
2177            .unwrap();
2178        let (alice_public_key, _) = get_sopak();
2179        let sealed_alice_public_key = alice_public_key
2180            .to_sealed_entry(".alicepublickey.".to_owned(), alice_decryption_algorithm)
2181            .await
2182            .unwrap();
2183        let bob_key = SodiumOxideCurve25519SecretAsymmetricKey::new()
2184            .to_unsealed_entry(".bobsecretkey.".to_owned())
2185            .unwrap();
2186        let bob_key_bytes = bob_key.resolve().await.unwrap().byte_source();
2187        let bob_key_copy = SodiumOxideCurve25519SecretAsymmetricKeyBuilder {}
2188            .build(Some(bob_key_bytes.get().unwrap()))
2189            .unwrap();
2190        let ciphertext = get_sopak_ciphertext(b"hello, world!", Some(&bob_key_copy));
2191        let algorithm = sealed_alice_public_key
2192            .to_public_asymmetric_byte_algorithm(bob_key, Some(get_soan()))
2193            .await
2194            .unwrap();
2195        let plaintext = algorithm
2196            .unseal(&ByteSource::Vector(
2197                AsRef::<[u8]>::as_ref(&ciphertext).into(),
2198            ))
2199            .await
2200            .unwrap();
2201        assert_eq!(data.byte_source().get().unwrap(), plaintext.get().unwrap());
2202    }
2203
2204    #[tokio::test]
2205    async fn test_unseal_publicasymmetricbytealgorithm_with_sealed_key_with_referenced_decryption_key(
2206    ) {
2207        let data = Data::String("hello, world!".to_owned());
2208        let unsealed_alice_decryption_key = get_sosk()
2209            .to_unsealed_entry(".alicedecryptionkey.".to_owned())
2210            .unwrap();
2211        let mut storer = MockStorer::new();
2212        storer
2213            .expect_private_get::<SodiumOxideSymmetricKey>()
2214            .withf(|path| path == ".alicedecryptionkey.")
2215            .return_once(move |_| Ok(unsealed_alice_decryption_key));
2216        let ref_alice_decryption_key = get_sosk()
2217            .to_ref_entry(".alicedecryptionkey.".to_owned(), storer)
2218            .unwrap();
2219        let alice_decryption_algorithm = ref_alice_decryption_key
2220            .to_symmetric_byte_algorithm(Some(get_sosn()))
2221            .await
2222            .unwrap();
2223        let (alice_public_key, _) = get_sopak();
2224        let sealed_alice_key = alice_public_key
2225            .to_sealed_entry(".alicepublickey.".to_owned(), alice_decryption_algorithm)
2226            .await
2227            .unwrap();
2228        let unsealed_bob_key = SodiumOxideCurve25519SecretAsymmetricKey::new()
2229            .to_unsealed_entry(".bobsecretkey.".to_owned())
2230            .unwrap();
2231        let bob_key_bytes = unsealed_bob_key.resolve().await.unwrap().byte_source();
2232        let bob_key_copy = SodiumOxideCurve25519SecretAsymmetricKeyBuilder {}
2233            .build(Some(bob_key_bytes.get().unwrap()))
2234            .unwrap();
2235        let ciphertext = get_sopak_ciphertext(b"hello, world!", Some(&bob_key_copy));
2236        let algorithm = sealed_alice_key
2237            .to_public_asymmetric_byte_algorithm(unsealed_bob_key, Some(get_soan()))
2238            .await
2239            .unwrap();
2240        let plaintext = algorithm
2241            .unseal(&ByteSource::Vector(
2242                AsRef::<[u8]>::as_ref(&ciphertext).into(),
2243            ))
2244            .await
2245            .unwrap();
2246        assert_eq!(data.byte_source().get().unwrap(), plaintext.get().unwrap(),);
2247    }
2248
2249    #[test]
2250    fn test_sodiumoxideed25519publicasymmetrickey_verify() {
2251        let sopakb = SodiumOxideEd25519PublicAsymmetricKeyBuilder {};
2252        let public_key_base64 = "ovk3UE3A2xCRUErmWiOFFBbflsAxb67gG+i3UUQpJ/w=";
2253        let public_key: SodiumOxideEd25519PublicAsymmetricKey = sopakb
2254            .build(Some(base64::decode(public_key_base64).unwrap().as_ref()))
2255            .unwrap();
2256        let message = ByteSource::Vector(VectorByteSource::new(Some("abc".as_ref())));
2257        let signature = ByteSource::Vector(
2258            VectorByteSource::new(
2259                Some(base64::decode("XZOGd+nbEkrP5cdAjed0DdjLCrhMTW3/PU2UztdTK241N2yQyG/GVPxC+jHm96+QDFMssxHU1mMm2+e4e3m7Cw==")
2260                    .unwrap()
2261                    .as_ref())
2262            )
2263        );
2264
2265        public_key.verify(message, signature).unwrap();
2266    }
2267
2268    #[test]
2269    fn test_sodiumoxideed25519publicasymmetrickey_verify_with_different_message() {
2270        let sopakb = SodiumOxideEd25519PublicAsymmetricKeyBuilder {};
2271        let public_key_base64 = "ovk3UE3A2xCRUErmWiOFFBbflsAxb67gG+i3UUQpJ/w=";
2272        let public_key: SodiumOxideEd25519PublicAsymmetricKey = sopakb
2273            .build(Some(base64::decode(public_key_base64).unwrap().as_ref()))
2274            .unwrap();
2275        let message = ByteSource::Vector(VectorByteSource::new(
2276            Some("abcde".as_ref()), // not the message signed with the hardcoded signature
2277        ));
2278        let signature = ByteSource::Vector(
2279            VectorByteSource::new(
2280                Some(base64::decode("XZOGd+nbEkrP5cdAjed0DdjLCrhMTW3/PU2UztdTK241N2yQyG/GVPxC+jHm96+QDFMssxHU1mMm2+e4e3m7Cw==")
2281                    .unwrap()
2282                    .as_ref())
2283            )
2284        );
2285
2286        let result = public_key.verify(message, signature);
2287        assert!(matches!(result, Err(CryptoError::BadSignature)));
2288    }
2289
2290    #[test]
2291    fn test_sodiumoxideed25519publicasymmetrickey_verify_with_invalid_signature() {
2292        let sopakb = SodiumOxideEd25519PublicAsymmetricKeyBuilder {};
2293        // generate the keypair so it does not match hardcoded signature
2294        let (pk, _) = sign::gen_keypair();
2295        let public_key: SodiumOxideEd25519PublicAsymmetricKey =
2296            sopakb.build(Some(pk.as_ref())).unwrap();
2297
2298        let message = ByteSource::Vector(VectorByteSource::new(Some("abc".as_ref())));
2299        let signature = ByteSource::Vector(
2300            VectorByteSource::new(
2301                Some(base64::decode("XZOGd+nbEkrP5cdAjed0DdjLCrhMTW3/PU2UztdTK241N2yQyG/GVPxC+jHm96+QDFMssxHU1mMm2+e4e3m7Cw==")
2302                    .unwrap()
2303                    .as_ref())
2304            )
2305        );
2306        assert!(matches!(
2307            public_key.verify(message, signature),
2308            Err(CryptoError::BadSignature)
2309        ));
2310    }
2311
2312    #[test]
2313    fn test_sodiumoxideed25519publicasymmetrickey_verify_with_invalid_signature_bytes() {
2314        let sopakb = SodiumOxideEd25519PublicAsymmetricKeyBuilder {};
2315        // generate the keypair so it does not match hardcoded signature
2316        let (pk, _) = sign::gen_keypair();
2317        let public_key: SodiumOxideEd25519PublicAsymmetricKey =
2318            sopakb.build(Some(pk.as_ref())).unwrap();
2319
2320        let message = ByteSource::Vector(VectorByteSource::new(Some("abc".as_ref())));
2321        let signature = ByteSource::Vector(VectorByteSource::new(Some(
2322            base64::decode("YWFzZA==").unwrap().as_ref(),
2323        )));
2324        assert!(matches!(
2325            public_key.verify(message, signature),
2326            Err(CryptoError::BadSignature)
2327        ));
2328    }
2329
2330    /// PUBLIC ASYMMETRIC KEY - BUILDER ///
2331    #[test]
2332    fn test_sodiumoxidepublicasymmetrickeybuilder_build_valid() {
2333        let sopakb = SodiumOxideCurve25519PublicAsymmetricKeyBuilder {};
2334        let (_, sk) = box_::gen_keypair();
2335        let key = sopakb.build(Some(sk.as_ref())).unwrap();
2336        assert_eq!(key.public_key.as_ref(), sk.as_ref());
2337    }
2338
2339    #[test]
2340    #[should_panic]
2341    fn test_sodiumoxidepublicasymmetrickeybuilder_build_invalid() {
2342        let sopakb = SodiumOxideCurve25519PublicAsymmetricKeyBuilder {};
2343        let _ = sopakb.build(Some(b"bla")).unwrap();
2344    }
2345
2346    #[test]
2347    fn test_sodiumoxidepublicasymmetrickeybuilder_from_typebuildercontainer_valid() {
2348        let tbc = TypeBuilderContainer(TypeBuilder::Key(KeyBuilder::Asymmetric(
2349            AsymmetricKeyBuilder::Public(PublicAsymmetricKeyBuilder::SodiumOxideCurve25519(
2350                SodiumOxideCurve25519PublicAsymmetricKeyBuilder {},
2351            )),
2352        )));
2353        let sopakb: SodiumOxideCurve25519PublicAsymmetricKeyBuilder = tbc.try_into().unwrap();
2354        let (public_key, _) = SodiumOxideCurve25519PublicAsymmetricKey::new();
2355        sopakb.build(Some(public_key.public_key.as_ref())).unwrap();
2356    }
2357
2358    #[test]
2359    #[should_panic]
2360    fn test_sodiumoxidepublicasymmetrickeybuilder_from_typebuildercontainer_invalid() {
2361        let tbc = TypeBuilderContainer(TypeBuilder::Data(DataBuilder::Bool(BoolDataBuilder {})));
2362        let _: SodiumOxideCurve25519PublicAsymmetricKeyBuilder = tbc.try_into().unwrap();
2363    }
2364
2365    /// PUBLIC ASYMMETRIC KEY - SEAL AND UNSEAL ///
2366    #[test]
2367    fn test_seal_publicasymmetrickey_with_non_referenced_key() {
2368        let plaintext = "hello, world!".into();
2369        let (sopak, sosak) = get_sopak();
2370        let (cipher_source, _) = sopak.seal(&plaintext, &sosak, Some(&get_soan())).unwrap();
2371        assert_eq!(
2372            get_sopak_ciphertext(b"hello, world!", None),
2373            cipher_source.get().unwrap().to_vec(),
2374        );
2375    }
2376
2377    #[test]
2378    #[should_panic(expected = "CiphertextFailedVerification")]
2379    fn test_publicasymmetrickey_unseal_with_invalid_bytes() {
2380        let (sopak, sosak) = get_sopak();
2381        let ciphertext = "bla".into();
2382        let _ = sopak.unseal(&ciphertext, &sosak, &get_soan()).unwrap();
2383    }
2384
2385    #[test]
2386    #[should_panic(expected = "CiphertextFailedVerification")]
2387    fn test_publicasymmetrickey_unseal_with_invalid_nonce() {
2388        let (sopak, sosak) = get_sopak();
2389        let ciphertext = get_sopak_ciphertext(b"hello, world!", None);
2390        let _ = sopak
2391            .unseal(
2392                &ciphertext.as_slice().into(),
2393                &sosak,
2394                &SodiumOxideAsymmetricNonce {
2395                    nonce: box_::gen_nonce(),
2396                },
2397            )
2398            .unwrap();
2399    }
2400
2401    #[test]
2402    fn test_publicasymmetrickey_to_index() {
2403        let index = SodiumOxideCurve25519PublicAsymmetricKey::get_index();
2404        assert_eq!(
2405            index,
2406            Some(bson::doc! {
2407                "c": {
2408                    "builder": {
2409                "t": "Key",
2410                "c": {
2411                    "t": "Asymmetric",
2412                "c": {
2413            "t": "Public",
2414            "c": {
2415                "t": "SodiumOxideCurve25519"
2416            }
2417                }
2418                }
2419                    }
2420                }
2421                    })
2422        )
2423    }
2424
2425    #[test]
2426    fn test_publicasymmetrickey_to_builder() {
2427        let (sopak, _) = SodiumOxideCurve25519PublicAsymmetricKey::new();
2428        let builder = sopak.builder();
2429        let key_bytes = sopak.public_key.as_ref();
2430        let built_key = builder.build(Some(key_bytes)).unwrap();
2431        assert_eq!(built_key.public_key.as_ref(), sopak.public_key.as_ref());
2432    }
2433
2434    #[test]
2435    fn test_publicasymmetrickey_new() {
2436        let (sopak, _) = SodiumOxideCurve25519PublicAsymmetricKey::new();
2437        assert!(!sopak.public_key.as_ref().is_empty());
2438    }
2439}