vitaminc_aead/
nonce.rs

1use crate::Unspecified;
2use std::cell::RefCell;
3use vitaminc_random::{Generatable, SafeRand, SeedableRng};
4
5/// Represents a nonce used in AEAD encryption of `N` bytes length.
6pub struct Nonce<const N: usize>([u8; N]);
7
8impl<const N: usize> AsRef<[u8]> for Nonce<N> {
9    fn as_ref(&self) -> &[u8] {
10        &self.0
11    }
12}
13
14impl<const N: usize> Nonce<N> {
15    pub(crate) fn new(inner: [u8; N]) -> Self {
16        Self(inner)
17    }
18
19    pub fn into_inner(self) -> [u8; N] {
20        self.0
21    }
22}
23
24// TODO: Make this a trait that can be implemented for a cipher rather than an associated type on the Cipher
25// That way we can have multiple implementations of the same cipher with different nonce generation strategies
26pub trait NonceGenerator<const N: usize> {
27    fn init() -> Self;
28    fn generate(&self) -> Result<Nonce<N>, Unspecified>;
29}
30
31pub struct RandomNonceGenerator<const N: usize>(RefCell<SafeRand>);
32
33impl<const N: usize> NonceGenerator<N> for RandomNonceGenerator<N> {
34    fn init() -> Self {
35        let rng = SafeRand::from_entropy();
36        Self(RefCell::new(rng))
37    }
38
39    fn generate(&self) -> Result<Nonce<N>, Unspecified> {
40        let mut rng = self.0.borrow_mut();
41        Generatable::random(&mut rng)
42            .map_err(|_| Unspecified)
43            .map(Nonce::new)
44    }
45}