Skip to main content

Module rng

Module rng 

Source
Available on crate feature std only.
Expand description

RngProvider — the indirection through which Phantom Protocol obtains cryptographic randomness. Default is OsRng, which delegates to getrandom::getrandom and therefore picks up the platform’s CSPRNG on every supported target (Linux getrandom(2), macOS / iOS CCRandomGenerateBytes, Windows BCryptGenRandom, wasm32 via the js feature → crypto.getRandomValues, etc.).

Embedders can swap in their own provider by implementing this trait and threading it into the relevant _with_provider entry points (e.g. HybridSigningKey::generate_with_provider, which mints a keypair from an injected RNG). The trait is the seam; all in-crate production code uses the OsRng default, and target-specific embedders (embedded HALs without a getrandom-shaped entropy source) supply their own provider.

§Module scope

Trait + default OsRng impl + tests. The OsRng substrate forks on the build: getrandom on the default build, AWS-LC’s CTR_DRBG under --features fips (see the two impl RngProvider for OsRng blocks below). Beyond those, the module deliberately ships no other providers:

  • A software NIST SP 800-90A DRBG of our own (e.g. HMAC-DRBG). Not needed: the fips build delegates to AWS-LC’s FIPS-validated CTR_DRBG rather than carrying an in-tree DRBG. The trait is still shaped to accept one — see the illustrative skeleton below — for embedders who want a custom DRBG.
  • A hardware-RNG impl. Those are inherently target-specific and belong in a downstream HAL adapter crate, not in phantom_protocol itself.

§Slotting in alternative providers

§Hardware TRNG on embedded

On microcontrollers exposing a true-RNG peripheral (e.g., the STM32 RNG, the nRF52 RNG, RP2040 ROSC, …), the HAL crate typically exposes a blocking reader (embedded_hal::blocking::rng::Read or the rand_core::RngCore impl that newer HALs wrap it in). A downstream adapter looks roughly like:

use phantom_protocol::crypto::rng::RngProvider;
use core::sync::atomic::AtomicBool;
use spin::Mutex;          // or critical_section::Mutex on no_std-no-alloc

pub struct HwRng<R> {
    inner: Mutex<R>,
}

impl<R> HwRng<R> {
    pub fn new(peripheral: R) -> Self {
        Self { inner: Mutex::new(peripheral) }
    }
}

impl<R> RngProvider for HwRng<R>
where
    R: rand_core::RngCore + Send + 'static,
{
    fn fill_bytes(&self, dest: &mut [u8]) {
        self.inner.lock().fill_bytes(dest);
    }
}

The Mutex is needed because fill_bytes takes &self. A real HAL adapter should also surface health-test failures from the peripheral (most TRNGs have a stuck-bit / continuous-test register) rather than returning silently-biased bytes.

§Software DRBG provider (illustration)

The shipped --features fips build does NOT use an in-tree DRBG — it delegates OsRng to AWS-LC’s FIPS-validated CTR_DRBG (see the fips impl RngProvider for OsRng below). An embedder who wants their own software DRBG (e.g. an HmacDrbg, SP 800-90A § 10.1.2, keyed from getrandom at boot and re-seeded per SP 800-90A § 9) can shape it as a provider like this:

use phantom_protocol::crypto::rng::RngProvider;
use std::sync::Mutex;

pub struct HmacDrbg { /* V, Key, reseed_counter, ... */ }
impl HmacDrbg {
    pub fn from_entropy() -> Self { /* seed from getrandom */ todo!() }
    fn generate(&mut self, out: &mut [u8]) { /* SP 800-90A 10.1.2.5 */ todo!() }
}

pub struct FipsDrbg(Mutex<HmacDrbg>);
impl RngProvider for FipsDrbg {
    fn fill_bytes(&self, dest: &mut [u8]) {
        self.0.lock().expect("DRBG poisoned").generate(dest);
    }
}

See docs/compliance/fips-readiness.md for the larger picture.

§Deterministic test fixture

See tests::CounterRng below for a tiny in-tree example.

Structs§

OsRng
Default RngProvider — delegates to getrandom and therefore to the OS’s CSPRNG on every supported target.

Traits§

RngProvider
Source of cryptographically secure random bytes.