crypto_common/
generate.rs

1use hybrid_array::{Array, ArraySize};
2use rand_core::{CryptoRng, TryCryptoRng};
3
4/// Secure random generation.
5pub trait Generate: Sized {
6    /// Generate random key using the provided [`TryCryptoRng`].
7    fn try_generate_from_rng<R: TryCryptoRng + ?Sized>(rng: &mut R) -> Result<Self, R::Error>;
8
9    /// Generate random key using the provided [`CryptoRng`].
10    fn generate_from_rng<R: CryptoRng + ?Sized>(rng: &mut R) -> Self {
11        let Ok(ret) = Self::try_generate_from_rng(rng);
12        ret
13    }
14
15    /// Randomly generate a value of this type using the system's ambient cryptographically secure
16    /// random number generator.
17    ///
18    /// # Errors
19    /// Returns [`getrandom::Error`] in the event the system's ambient RNG experiences an internal
20    /// failure.
21    #[cfg(feature = "getrandom")]
22    fn try_generate() -> Result<Self, getrandom::Error> {
23        Self::try_generate_from_rng(&mut getrandom::SysRng)
24    }
25
26    /// Randomly generate a value of this type using the system's ambient cryptographically secure
27    /// random number generator.
28    ///
29    /// # Panics
30    /// This method will panic in the event the system's ambient RNG experiences an internal
31    /// failure.
32    ///
33    /// This shouldn't happen on most modern operating systems.
34    #[cfg(feature = "getrandom")]
35    fn generate() -> Self {
36        Self::try_generate().expect("RNG failure")
37    }
38}
39
40impl Generate for u32 {
41    #[inline]
42    fn try_generate_from_rng<R: TryCryptoRng + ?Sized>(rng: &mut R) -> Result<Self, R::Error> {
43        rng.try_next_u32()
44    }
45}
46
47impl Generate for u64 {
48    #[inline]
49    fn try_generate_from_rng<R: TryCryptoRng + ?Sized>(rng: &mut R) -> Result<Self, R::Error> {
50        rng.try_next_u64()
51    }
52}
53
54impl<const N: usize> Generate for [u8; N] {
55    #[inline]
56    fn try_generate_from_rng<R: TryCryptoRng + ?Sized>(rng: &mut R) -> Result<Self, R::Error> {
57        let mut ret = [0u8; N];
58        rng.try_fill_bytes(&mut ret)?;
59        Ok(ret)
60    }
61}
62
63impl<U: ArraySize> Generate for Array<u8, U> {
64    #[inline]
65    fn try_generate_from_rng<R: TryCryptoRng + ?Sized>(rng: &mut R) -> Result<Self, R::Error> {
66        let mut ret = Self::default();
67        rng.try_fill_bytes(&mut ret)?;
68        Ok(ret)
69    }
70}
71
72impl<U: ArraySize> Generate for Array<u32, U> {
73    #[inline]
74    fn try_generate_from_rng<R: TryCryptoRng + ?Sized>(rng: &mut R) -> Result<Self, R::Error> {
75        Self::try_from_fn(|_| rng.try_next_u32())
76    }
77}
78
79impl<U: ArraySize> Generate for Array<u64, U> {
80    #[inline]
81    fn try_generate_from_rng<R: TryCryptoRng + ?Sized>(rng: &mut R) -> Result<Self, R::Error> {
82        Self::try_from_fn(|_| rng.try_next_u64())
83    }
84}