Skip to main content

random_detached/
bytes.rs

1use zeroize::{Zeroize, Zeroizing};
2
3#[cfg(feature = "const_cmp")]
4use subtle::ConstantTimeEq;
5
6use crate::Generator;
7
8pub struct RandomBytes<const N: usize>(Zeroizing<[u8; N]>);
9
10impl<const N: usize> Generator<N> for RandomBytes<N> {
11    fn new() -> Result<Self, getrandom::Error> {
12        Ok(Self(Self::generate()?))
13    }
14
15    fn expose(&self) -> &[u8; N] {
16        &self.0
17    }
18
19    fn take(self) -> Zeroizing<[u8; N]> {
20        self.0
21    }
22
23    fn zeroize_mem(&mut self) {
24        self.0.zeroize();
25    }
26
27    #[cfg(feature = "blake3_hash")]
28    fn hash(&self) -> blake3::Hash {
29        blake3::hash(self.expose())
30    }
31
32    #[cfg(feature = "const_cmp")]
33    fn const_cmp(&self, other: &Self) -> bool {
34        self.0.as_ref().ct_eq(other.0.as_ref()).into()
35    }
36}
37
38#[cfg(test)]
39mod sanity_checks {
40    use crate::{Generator, RandomBytes};
41
42    #[test]
43    fn generate_bytes() {
44        let mut bytes = RandomBytes::<32>::new().unwrap();
45        assert_eq!(bytes.0.len(), 32);
46        assert_ne!(*bytes.expose(), [0u8; 32]);
47
48        bytes.zeroize_mem();
49        assert_eq!(*(bytes.take()), [0u8; 32]);
50    }
51}