Files
lora-card-reader/lorawan-device-patch/src/rng.rs
2026-03-30 15:32:51 +08:00

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(())
}
}