dcrypt_algorithms/aead/
mod.rs1#![cfg_attr(not(feature = "std"), no_std)]
35
36#[cfg(feature = "alloc")]
37extern crate alloc;
38
39#[cfg(feature = "alloc")]
41pub mod gcm;
42
43#[cfg(feature = "alloc")]
44pub mod chacha20poly1305;
45
46#[cfg(feature = "alloc")]
47pub mod xchacha20poly1305;
48
49#[cfg(feature = "alloc")]
51pub use self::gcm::Gcm;
52
53#[cfg(feature = "alloc")]
54pub use self::chacha20poly1305::ChaCha20Poly1305;
55
56#[cfg(feature = "alloc")]
57pub use self::xchacha20poly1305::XChaCha20Poly1305;
58
59use crate::error::{Error, Result};
60use crate::types::{Nonce, SecretBytes};
61#[cfg(feature = "alloc")]
62use alloc::vec::Vec;
63use rand::{CryptoRng, RngCore};
64use zeroize::Zeroize;
65
66pub trait AeadAlgorithm {
68 const KEY_SIZE: usize;
70
71 const TAG_SIZE: usize;
73
74 fn name() -> &'static str;
76}
77
78pub enum ChaCha20Poly1305Algorithm {}
80
81impl AeadAlgorithm for ChaCha20Poly1305Algorithm {
82 const KEY_SIZE: usize = 32;
83 const TAG_SIZE: usize = 16;
84
85 fn name() -> &'static str {
86 "ChaCha20-Poly1305"
87 }
88}
89
90pub trait Operation<T> {
92 fn execute(self) -> Result<T>;
94
95 fn reset(&mut self);
97}
98
99pub trait AeadEncryptOperation<'a, A: AeadAlgorithm>: Operation<Vec<u8>> {
101 fn with_nonce(self, nonce: &'a Nonce<12>) -> Self;
103
104 fn with_aad(self, aad: &'a [u8]) -> Self;
106
107 fn encrypt(self, plaintext: &'a [u8]) -> Result<Vec<u8>>;
109}
110
111pub trait AeadDecryptOperation<'a, A: AeadAlgorithm>: Operation<Vec<u8>> {
113 fn with_nonce(self, nonce: &'a Nonce<12>) -> Self;
115
116 fn with_aad(self, aad: &'a [u8]) -> Self;
118
119 fn decrypt(self, ciphertext: &'a [u8]) -> Result<Vec<u8>>;
121}
122
123pub trait AeadCipher {
125 type Algorithm: AeadAlgorithm;
127
128 type Key: AsRef<[u8]> + AsMut<[u8]> + Clone + Zeroize;
130
131 fn new(key: &Self::Key) -> Result<Self>
133 where
134 Self: Sized;
135
136 fn encrypt(&self) -> impl AeadEncryptOperation<'_, Self::Algorithm>;
138
139 fn decrypt(&self) -> impl AeadDecryptOperation<'_, Self::Algorithm>;
141
142 fn generate_key<R: RngCore + CryptoRng>(rng: &mut R) -> Result<Self::Key>;
144
145 fn generate_nonce<R: RngCore + CryptoRng>(rng: &mut R) -> Result<Nonce<12>>;
147
148 fn name() -> &'static str {
150 Self::Algorithm::name()
151 }
152
153 fn key_size() -> usize {
155 Self::Algorithm::KEY_SIZE
156 }
157
158 fn tag_size() -> usize {
160 Self::Algorithm::TAG_SIZE
161 }
162}
163
164#[cfg(feature = "alloc")]
166pub struct ChaCha20Poly1305Cipher {
167 inner: chacha20poly1305::ChaCha20Poly1305,
168}
169
170#[cfg(feature = "alloc")]
171impl AeadCipher for ChaCha20Poly1305Cipher {
172 type Algorithm = ChaCha20Poly1305Algorithm;
173 type Key = SecretBytes<32>;
174
175 fn new(key: &Self::Key) -> Result<Self> {
176 let mut key_array = [0u8; 32];
177 key_array.copy_from_slice(key.as_ref());
178
179 let inner = chacha20poly1305::ChaCha20Poly1305::new(&key_array);
180
181 Ok(Self { inner })
182 }
183
184 fn encrypt(&self) -> impl AeadEncryptOperation<'_, Self::Algorithm> {
185 ChaCha20Poly1305EncryptOperation {
186 cipher: self,
187 nonce: None,
188 aad: None,
189 }
190 }
191
192 fn decrypt(&self) -> impl AeadDecryptOperation<'_, Self::Algorithm> {
193 ChaCha20Poly1305DecryptOperation {
194 cipher: self,
195 nonce: None,
196 aad: None,
197 }
198 }
199
200 fn generate_key<R: RngCore + CryptoRng>(rng: &mut R) -> Result<Self::Key> {
201 let mut key = [0u8; 32];
202 rng.fill_bytes(&mut key);
203 Ok(SecretBytes::new(key))
204 }
205
206 fn generate_nonce<R: RngCore + CryptoRng>(rng: &mut R) -> Result<Nonce<12>> {
207 let mut nonce = [0u8; 12];
208 rng.fill_bytes(&mut nonce);
209 Ok(Nonce::<12>::new(nonce))
210 }
211}
212
213#[cfg(feature = "alloc")]
215pub struct ChaCha20Poly1305EncryptOperation<'a> {
216 cipher: &'a ChaCha20Poly1305Cipher,
217 nonce: Option<&'a Nonce<12>>,
218 aad: Option<&'a [u8]>,
219}
220
221#[cfg(feature = "alloc")]
222impl Operation<Vec<u8>> for ChaCha20Poly1305EncryptOperation<'_> {
223 fn execute(self) -> Result<Vec<u8>> {
224 Err(Error::param("operation", "use encrypt method instead"))
225 }
226
227 fn reset(&mut self) {
228 self.nonce = None;
229 self.aad = None;
230 }
231}
232
233#[cfg(feature = "alloc")]
234impl<'a> AeadEncryptOperation<'a, ChaCha20Poly1305Algorithm>
235 for ChaCha20Poly1305EncryptOperation<'a>
236{
237 fn with_nonce(mut self, nonce: &'a Nonce<12>) -> Self {
238 self.nonce = Some(nonce);
239 self
240 }
241
242 fn with_aad(mut self, aad: &'a [u8]) -> Self {
243 self.aad = Some(aad);
244 self
245 }
246
247 fn encrypt(self, plaintext: &'a [u8]) -> Result<Vec<u8>> {
248 let nonce = self.nonce.ok_or_else(|| {
249 Error::param("nonce", "nonce is required for ChaCha20Poly1305 encryption")
250 })?;
251
252 self.cipher.inner.encrypt(nonce, plaintext, self.aad)
253 }
254}
255
256#[cfg(feature = "alloc")]
258pub struct ChaCha20Poly1305DecryptOperation<'a> {
259 cipher: &'a ChaCha20Poly1305Cipher,
260 nonce: Option<&'a Nonce<12>>,
261 aad: Option<&'a [u8]>,
262}
263
264#[cfg(feature = "alloc")]
265impl Operation<Vec<u8>> for ChaCha20Poly1305DecryptOperation<'_> {
266 fn execute(self) -> Result<Vec<u8>> {
267 Err(Error::param("operation", "use decrypt method instead"))
268 }
269
270 fn reset(&mut self) {
271 self.nonce = None;
272 self.aad = None;
273 }
274}
275
276#[cfg(feature = "alloc")]
277impl<'a> AeadDecryptOperation<'a, ChaCha20Poly1305Algorithm>
278 for ChaCha20Poly1305DecryptOperation<'a>
279{
280 fn with_nonce(mut self, nonce: &'a Nonce<12>) -> Self {
281 self.nonce = Some(nonce);
282 self
283 }
284
285 fn with_aad(mut self, aad: &'a [u8]) -> Self {
286 self.aad = Some(aad);
287 self
288 }
289
290 fn decrypt(self, ciphertext: &'a [u8]) -> Result<Vec<u8>> {
291 let nonce = self.nonce.ok_or_else(|| {
292 Error::param("nonce", "nonce is required for ChaCha20Poly1305 decryption")
293 })?;
294
295 self.cipher.inner.decrypt(nonce, ciphertext, self.aad)
296 }
297}