Crates.io | rand_jitter |
lib.rs | rand_jitter |
version | 0.4.0 |
source | src |
created_at | 2019-01-25 09:53:44.828929 |
updated_at | 2023-12-08 16:30:43.977689 |
description | Random number generator based on timing jitter |
homepage | |
repository | https://github.com/rust-random/rngs |
max_upload_size | |
id | 110592 |
size | 55,483 |
Non-physical true random number generator based on timing jitter.
Note that this RNG is not suited for use cases where cryptographic security is required (also see this discussion).
This crate depends on rand_core and is part of the Rand project.
This crate aims to support all of Rust's std
platforms with a system-provided
entropy source. Unlike other Rand crates, this crate does not support no_std
(handling this gracefully is a current discussion topic).
Links:
This crate has optional std
support which is disabled by default;
this feature is required to provide the JitterRng::new
function;
without std
support a timer must be supplied via JitterRng::new_with_timer
.
JitterRng::new()
has build-in, but limited, quality testing, however
before using JitterRng
on untested hardware, or after changes that could
effect how the code is optimized (such as a new LLVM version), it is
recommend to run the much more stringent
NIST SP 800-90B Entropy Estimation Suite.
Use the following code using timer_stats
to collect the data:
use rand_jitter::JitterRng;
use std::error::Error;
use std::fs::File;
use std::io::Write;
fn get_nstime() -> u64 {
use std::time::{SystemTime, UNIX_EPOCH};
let dur = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
// The correct way to calculate the current time is
// `dur.as_secs() * 1_000_000_000 + dur.subsec_nanos() as u64`
// But this is faster, and the difference in terms of entropy is
// negligible (log2(10^9) == 29.9).
dur.as_secs() << 30 | dur.subsec_nanos() as u64
}
fn main() -> Result<(), Box<dyn Error>> {
let mut rng = JitterRng::new_with_timer(get_nstime);
// 1_000_000 results are required for the
// NIST SP 800-90B Entropy Estimation Suite
const ROUNDS: usize = 1_000_000;
let mut deltas_variable: Vec<u8> = Vec::with_capacity(ROUNDS);
let mut deltas_minimal: Vec<u8> = Vec::with_capacity(ROUNDS);
for _ in 0..ROUNDS {
deltas_variable.push(rng.timer_stats(true) as u8);
deltas_minimal.push(rng.timer_stats(false) as u8);
}
// Write out after the statistics collection loop, to not disturb the
// test results.
File::create("jitter_rng_var.bin")?.write(&deltas_variable)?;
File::create("jitter_rng_min.bin")?.write(&deltas_minimal)?;
Ok(())
}
This will produce two files: jitter_rng_var.bin
and jitter_rng_min.bin
.
Run the Entropy Estimation Suite in three configurations, as outlined below.
Every run has two steps. One step to produce an estimation, another to
validate the estimation.
64 / test_timer()
.
python noniid_main.py -v jitter_rng_var.bin 8
restart.py -v jitter_rng_var.bin 8 <min-entropy>
3.70
is the minimum estimated entropy for true randomness.
python noniid_main.py -v -u 4 jitter_rng_var.bin 4
restart.py -v -u 4 jitter_rng_var.bin 4 <min-entropy>
python noniid_main.py -v -u 4 jitter_rng_min.bin 4
restart.py -v -u 4 jitter_rng_min.bin 4 <min-entropy>
rand_jitter
is distributed under the terms of both the MIT license and the
Apache License (Version 2.0).
See LICENSE-APACHE and LICENSE-MIT, and COPYRIGHT for details.