55 lines
1.8 KiB
Rust
55 lines
1.8 KiB
Rust
//! 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(())
|
|
}
|
|
}
|