crypto_common/
generate.rs

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