Skip to main content

crypto_common/
generate.rs

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