deadbolt_crypto/
encryption.rs

1use std::error::Error;
2
3use aes_gcm::{
4    aead::{generic_array::GenericArray, Aead, KeyInit},
5    aes::cipher::ArrayLength,
6    Aes256Gcm, Nonce,
7};
8
9use chacha20::ChaCha8;
10use chacha20::{
11    cipher::{KeyIvInit, StreamCipher, StreamCipherSeek},
12    ChaCha20,
13};
14
15use chacha20poly1305::ChaCha20Poly1305;
16use rand::Rng;
17use secrecy::{ExposeSecret, SecretVec};
18pub struct Encryption {
19    aes_cipher: Aes256Gcm,
20    chacha_cipher: ChaCha20Poly1305,
21}
22
23pub struct EncryptionPayload {
24    pub data: Vec<u8>,
25    pub nonce: [u8; 12],
26}
27
28impl Encryption {
29    pub fn new(master_key: &SecretVec<u8>) -> Encryption {
30        Encryption {
31            aes_cipher: Aes256Gcm::new(GenericArray::from_slice(master_key.expose_secret())),
32            chacha_cipher: ChaCha20Poly1305::new(GenericArray::from_slice(
33                master_key.expose_secret(),
34            )),
35        }
36    }
37
38    pub fn encrypt(
39        &mut self,
40        plaintext: Vec<u8>,
41        algorithm: u8,
42    ) -> Result<EncryptionPayload, Box<dyn Error>> {
43        let mut nonce: [u8; 12] = [0; 12];
44        let mut rng = rand::thread_rng();
45        rng.fill(&mut nonce);
46
47        match algorithm {
48            1 => {
49                let encryption_result = self
50                    .aes_cipher
51                    .encrypt(GenericArray::from_slice(&nonce), plaintext.as_ref());
52
53                match encryption_result {
54                    Ok(ciphertext) => Ok(EncryptionPayload {
55                        data: ciphertext,
56                        nonce,
57                    }),
58                    Err(e) => Err(e.to_string().into()),
59                }
60            }
61            2 => {
62                let encryption_result = self
63                    .chacha_cipher
64                    .encrypt(GenericArray::from_slice(&nonce), plaintext.as_ref());
65
66                match encryption_result {
67                    Ok(ciphertext) => Ok(EncryptionPayload {
68                        data: ciphertext,
69                        nonce,
70                    }),
71                    Err(e) => Err(e.to_string().into()),
72                }
73            }
74            _ => Err("Unknown algorithm".to_string().into()),
75        }
76    }
77
78    pub fn decrypt(
79        &mut self,
80        nonce: [u8; 12],
81        ciphertext: Vec<u8>,
82        algorithm: u8,
83    ) -> Result<EncryptionPayload, Box<dyn Error>> {
84        match algorithm {
85            1 => {
86                let decryption_result = self.aes_cipher.decrypt(
87                    GenericArray::from_slice(nonce.as_ref()),
88                    ciphertext.as_ref(),
89                );
90
91                match decryption_result {
92                    Ok(plaintext) => Ok(EncryptionPayload {
93                        data: plaintext,
94                        nonce,
95                    }),
96                    Err(e) => Err(e.to_string().into()),
97                }
98            }
99            2 => {
100                let decryption_result = self.chacha_cipher.decrypt(
101                    GenericArray::from_slice(nonce.as_ref()),
102                    ciphertext.as_ref(),
103                );
104
105                match decryption_result {
106                    Ok(plaintext) => Ok(EncryptionPayload {
107                        data: plaintext,
108                        nonce,
109                    }),
110                    Err(e) => Err(e.to_string().into()),
111                }
112            }
113            _ => Err("Unknown algorithm".to_string().into()),
114        }
115    }
116}
117
118pub struct StreamEncryption {}
119
120impl StreamEncryption {
121    pub fn encrypt(child_key: &SecretVec<u8>, plaintext: &[u8]) -> Vec<u8> {
122        let mut nonce: [u8; 12] = [0; 12];
123        let mut rng = rand::thread_rng();
124        rng.fill(&mut nonce);
125
126        let key = GenericArray::from_slice(child_key.expose_secret());
127
128        let mut cipher = ChaCha8::new(key, &nonce.into());
129        let mut buffer = plaintext.to_owned();
130
131        cipher.apply_keystream(&mut buffer);
132
133        let mut ciphertext: Vec<u8> = nonce.to_vec();
134        ciphertext.extend(buffer);
135
136        ciphertext
137    }
138
139    pub fn decrypt(child_key: &SecretVec<u8>, ciphertext: &[u8]) -> Vec<u8> {
140        let key = GenericArray::from_slice(child_key.expose_secret());
141
142        let mut cipher = ChaCha8::new(key, ciphertext[..12].try_into().unwrap());
143        let mut buffer = ciphertext[12..].to_vec();
144
145        cipher.apply_keystream(&mut buffer);
146
147        buffer
148    }
149}