1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
pub use sodiumoxide::crypto::aead::xchacha20poly1305_ietf::Nonce;
use sodiumoxide::crypto::aead::xchacha20poly1305_ietf::{
    gen_key, gen_nonce, open, seal, Key as UnderlyingKey,
};

use crate::algo::{self as base, cipher::symmetric as symm};

#[derive(Clone)]
pub struct Key {
    store: Vec<u8>,
    key: UnderlyingKey,
}
impl base::SafeGenerateKey for Key {
    type Settings = ();
    fn safe_generate(_: &Self::Settings) -> Self {
        let key = gen_key();
        Self::new(key)
    }
}
impl symm::Key for Key {}
impl Key {
    pub fn new(key: UnderlyingKey) -> Self {
        Self {
            store: key.as_ref().to_vec(),
            key: key,
        }
    }
    fn underlying(&self) -> &'_ UnderlyingKey {
        &self.key
    }
}

pub struct EncryptArgs {
    pub plaintext: Vec<u8>,
    pub aad: Option<Vec<u8>>,
    pub nonce: Option<Nonce>,
}
pub struct DecryptArgs {
    pub ciphertext: Vec<u8>,
    pub aad: Option<Vec<u8>>,
    pub nonce: Nonce,
}

pub struct Algo;
impl base::Algo for Algo {
    type Key = Key;
    type ConstructionData = ();
    fn key_settings<'a>(
        &'a self,
    ) -> &'a <<Self as base::Algo>::Key as base::SafeGenerateKey>::Settings {
        &()
    }
    fn new(_: ()) -> Self {
        Self
    }
}
impl symm::Algo for Algo {}
impl symm::CanEncrypt for Algo {
    type EKey = Key;
    type Input = EncryptArgs;
    type Error = symm::EncryptError;
    fn encrypt(&self, key: &Self::EKey, msg: &Self::Input) -> Result<Vec<u8>, Self::Error> {
        let nonce = if let Some(n) = msg.nonce {
            n
        } else {
            gen_nonce()
        };
        Ok(seal(
            msg.plaintext.as_slice(),
            msg.aad.as_ref().map(|aad| aad.as_slice()),
            &nonce,
            key.underlying(),
        ))
    }
}
impl symm::CanDecrypt for Algo {
    type DKey = Key;
    type Input = DecryptArgs;
    type Error = symm::DecryptError;
    fn decrypt(&self, key: &Self::DKey, msg: &Self::Input) -> Result<Vec<u8>, Self::Error> {
        open(
            msg.ciphertext.as_slice(),
            msg.aad.as_ref().map(|aad| aad.as_slice()),
            &msg.nonce,
            key.underlying(),
        )
        .map_err(|_| symm::DecryptError::Base)
    }
}