//! RNG based on the `wyrand` pseudorandom number generator. //! //! This crate uses the random number generator for exactly two things: //! //! * Generating DevNonces for join requests //! * Selecting random channels when transmitting uplinks. //! //! The good news is that both these operations don't require true //! cryptographic randomness. In fact, in both cases, we don't even care about //! predictability! A pseudorandom number generator initialized with a seed //! generated by a true random number generator is plenty enough: //! //! * DevNonces must only be unique with a low chance of collision. //! The 1.0.4 LoRaWAN spec even explicitly requires the DevNonces to be //! a sequence of incrementing integers, which is obviously predictable. //! * No one cares if the channel selected for the next uplink is predictable, //! as long as the channel selection yields an uniform distribution. //! //! By providing a PRNG `RngCore` implementation, we enable the crate users the //! flexibility of choosing whether they want to provide their own RNG, or just //! a seed to instantiate this PRNG to generate the random numbers for them. use fastrand::Rng; use rand_core::RngCore; #[derive(Clone)] /// A pseudorandom number generator utilizing Wyrand algorithm via /// the `fastrand` crate. pub struct Prng(Rng); impl Prng { pub(crate) fn new(seed: u64) -> Self { Self(Rng::with_seed(seed)) } } impl RngCore for Prng { fn next_u32(&mut self) -> u32 { self.0.u32(..) } fn next_u64(&mut self) -> u64 { self.0.u64(..) } fn fill_bytes(&mut self, dest: &mut [u8]) { rand_core::impls::fill_bytes_via_next(self, dest) } fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), rand_core::Error> { self.fill_bytes(dest); Ok(()) } }