sare_core/encryption/
mod.rs

1pub mod error;
2
3use crate::encryption::error::*;
4use rand::RngCore;
5use serde::{Deserialize, Serialize};
6
7use aead::stream;
8use aes_kw::KekAes256;
9use chacha20poly1305::KeyInit;
10use chacha20poly1305::XChaCha20Poly1305;
11use secrecy::{ExposeSecret, SecretVec};
12use std::io::{Read, Write};
13use std::vec;
14
15const AEAD_BUFFER_LEN: usize = 2048;
16
17#[derive(Copy, Debug, Clone, Serialize, Deserialize)]
18pub enum EncryptionAlgorithm {
19    AES256GCM,
20    AES256KW,
21    XCHACHA20POLY1305,
22}
23
24pub struct KeyWrap {
25    input_key: SecretVec<u8>,
26}
27
28impl KeyWrap {
29    pub fn new(input_key: SecretVec<u8>) -> Result<Self, EncryptionError> {
30        if input_key.expose_secret().len() != 32 {
31            return Err(EncryptionError::InvalidKeyLength);
32        }
33
34        Ok(KeyWrap { input_key })
35    }
36
37    pub fn wrap(&self, data: &SecretVec<u8>) -> Result<Vec<u8>, EncryptionError> {
38        let mut output: Vec<u8> = vec![0; data.expose_secret().len() + 8];
39
40        let input_key = <[u8; 32]>::try_from(self.input_key.expose_secret().as_slice()).unwrap();
41
42        let kek = KekAes256::from(input_key);
43
44        kek.wrap_with_padding(data.expose_secret(), &mut output)?;
45
46        Ok(output)
47    }
48
49    pub fn dewrap(&self, wrapped_data: &SecretVec<u8>) -> Result<SecretVec<u8>, EncryptionError> {
50        let mut output: Vec<u8> = vec![0; wrapped_data.expose_secret().len() - 8];
51
52        let input_key = <[u8; 32]>::try_from(self.input_key.expose_secret().as_slice()).unwrap();
53
54        let kek = KekAes256::from(input_key);
55
56        kek.unwrap_with_padding(wrapped_data.expose_secret(), &mut output)?;
57
58        Ok(SecretVec::from(output))
59    }
60}
61
62pub struct Encryptor {
63    input_key: SecretVec<u8>,
64    pub nonce: Vec<u8>,
65    algorithm: EncryptionAlgorithm,
66}
67
68impl Encryptor {
69    pub fn new(input_key: SecretVec<u8>, algorithm: EncryptionAlgorithm) -> Self {
70        // TODO: Implement get_nonce_length() function for EncryptionAlgorithm enum
71        let mut nonce = vec![0; 19];
72        let mut rng = rand::thread_rng();
73        rng.fill_bytes(&mut nonce);
74
75        Encryptor {
76            input_key,
77            nonce,
78            algorithm,
79        }
80    }
81
82    pub fn encrypt<R: Read, W: Write>(
83        &self,
84        mut data: R,
85        mut output: W,
86    ) -> Result<(), EncryptionError> {
87        match self.algorithm {
88            EncryptionAlgorithm::XCHACHA20POLY1305 => {
89                self.encrypt_xchacha20poly1305(&mut data, &mut output)
90            }
91            _ => unimplemented!(),
92        }
93    }
94
95    // TODO: Needs Error Handling
96    pub fn encrypt_xchacha20poly1305<R: Read, W: Write>(
97        &self,
98        mut data: R,
99        mut output: W,
100    ) -> Result<(), EncryptionError> {
101        let input_key = <[u8; 32]>::try_from(self.input_key.expose_secret().as_slice()).unwrap();
102        let nonce = self.nonce.as_slice();
103
104        let aead = XChaCha20Poly1305::new(input_key.as_ref().into());
105        let mut stream_aead = stream::EncryptorBE32::from_aead(aead, nonce.as_ref().into());
106        let mut data_buffer = [0u8; AEAD_BUFFER_LEN];
107
108        loop {
109            let read_count = data.read(&mut data_buffer)?;
110
111            if read_count == AEAD_BUFFER_LEN {
112                let encrypted_data = stream_aead.encrypt_next(data_buffer.as_slice()).unwrap();
113
114                output.write_all(&encrypted_data)?;
115            } else {
116                let encrypted_data = stream_aead
117                    .encrypt_last(&data_buffer[..read_count])
118                    .unwrap();
119
120                output.write_all(&encrypted_data)?;
121                break;
122            }
123        }
124        Ok(())
125    }
126}
127
128pub struct Decryptor {
129    input_key: SecretVec<u8>,
130    nonce: Vec<u8>,
131    algorithm: EncryptionAlgorithm,
132}
133
134impl Decryptor {
135    pub fn new(input_key: SecretVec<u8>, nonce: Vec<u8>, algorithm: EncryptionAlgorithm) -> Self {
136        Decryptor {
137            input_key,
138            nonce,
139            algorithm,
140        }
141    }
142
143    pub fn decrypt<R: Read, W: Write>(
144        &self,
145        mut encrypted_data: R,
146        mut output: W,
147    ) -> Result<(), EncryptionError> {
148        match self.algorithm {
149            EncryptionAlgorithm::XCHACHA20POLY1305 => {
150                self.decrypt_xchacha20poly1305(&mut encrypted_data, &mut output)
151            }
152            _ => unimplemented!(),
153        }
154    }
155
156    // TODO: Needs Error Handling
157    pub fn decrypt_xchacha20poly1305<R: Read, W: Write>(
158        &self,
159        mut encrypted_data: R,
160        mut output: W,
161    ) -> Result<(), EncryptionError> {
162        let input_key = <[u8; 32]>::try_from(self.input_key.expose_secret().as_slice()).unwrap();
163        let nonce = self.nonce.as_slice();
164
165        let aead = XChaCha20Poly1305::new(input_key.as_ref().into());
166        let mut stream_aead = stream::DecryptorBE32::from_aead(aead, nonce.as_ref().into());
167        let mut encrypted_buffer = [0u8; AEAD_BUFFER_LEN + 16]; // 16bytes for AEAD tag
168
169        loop {
170            let read_count = encrypted_data.read(&mut encrypted_buffer)?;
171
172            if read_count == AEAD_BUFFER_LEN {
173                let decrypted_data = stream_aead
174                    .decrypt_next(encrypted_buffer.as_slice())
175                    .unwrap();
176
177                output.write(&decrypted_data)?;
178            } else {
179                let decrypted_data = stream_aead
180                    .decrypt_last(&encrypted_buffer[..read_count])
181                    .unwrap();
182
183                output.write(&decrypted_data)?;
184                break;
185            }
186        }
187
188        Ok(())
189    }
190}