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}