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