Skip to content

Commit 98b940f

Browse files
authored
Merge pull request #441 from pitdicker/rngs_doc
Rngs module documentation
2 parents b1c3585 + f4d2812 commit 98b940f

File tree

10 files changed

+308
-123
lines changed

10 files changed

+308
-123
lines changed

benches/generators.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use test::{black_box, Bencher};
1212
use rand::prelude::*;
1313
use rand::prng::{XorShiftRng, Hc128Rng, IsaacRng, Isaac64Rng, ChaChaRng};
1414
use rand::prng::hc128::Hc128Core;
15-
use rand::rngs::adaptor::ReseedingRng;
15+
use rand::rngs::adapter::ReseedingRng;
1616
use rand::rngs::{OsRng, JitterRng, EntropyRng};
1717

1818
macro_rules! gen_bytes {

rand_core/src/block.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@
5151
//! [`BlockRngCore`]: trait.BlockRngCore.html
5252
//! [`RngCore`]: ../trait.RngCore.html
5353
//! [`fill_bytes`]: ../trait.RngCore.html#tymethod.fill_bytes
54-
//! [`ReseedingRng`]: ../../rand/rngs/adaptor/struct.ReseedingRng.html
54+
//! [`ReseedingRng`]: ../../rand/rngs/adapter/struct.ReseedingRng.html
5555
5656
use core::convert::AsRef;
5757
use core::fmt;

src/lib.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@
156156
//! [`JitterRng`]: rngs/struct.JitterRng.html
157157
//! [`StdRng`]: rngs/struct.StdRng.html
158158
//! [`SmallRng`]: rngs/struct.SmallRng.html
159-
//! [`ReseedingRng`]: rngs/adaptor/struct.ReseedingRng.html
159+
//! [`ReseedingRng`]: rngs/adapter/struct.ReseedingRng.html
160160
//! [`prng`]: prng/index.html
161161
//! [`IsaacRng::new_from_u64`]: prng/isaac/struct.IsaacRng.html#method.new_from_u64
162162
//! [`Hc128Rng`]: prng/hc128/struct.Hc128Rng.html
@@ -219,8 +219,8 @@ pub mod rngs;
219219
////////////////////////////////////////////////////////////////////////////////
220220
// Compatibility re-exports. Documentation is hidden; will be removed eventually.
221221

222-
#[cfg(feature="std")] #[doc(hidden)] pub use rngs::adaptor::read;
223-
#[doc(hidden)] pub use rngs::adaptor::ReseedingRng;
222+
#[cfg(feature="std")] #[doc(hidden)] pub use rngs::adapter::read;
223+
#[doc(hidden)] pub use rngs::adapter::ReseedingRng;
224224

225225
#[doc(hidden)] pub use rngs::jitter;
226226
#[cfg(feature="std")] #[doc(hidden)] pub use rngs::{os, EntropyRng, OsRng};
@@ -252,7 +252,7 @@ use distributions::uniform::SampleUniform;
252252

253253
/// A type that can be randomly generated using an [`Rng`].
254254
///
255-
/// This is merely an adaptor around the [`Standard`] distribution for
255+
/// This is merely an adapter around the [`Standard`] distribution for
256256
/// convenience and backwards-compatibility.
257257
///
258258
/// [`Rng`]: trait.Rng.html

src/rngs/adaptor/mod.rs renamed to src/rngs/adapter/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
//! Wrappers / adaptors forming RNGs
11+
//! Wrappers / adapters forming RNGs
1212
1313
#[cfg(feature="std")] #[doc(hidden)] pub mod read;
1414
mod reseeding;

src/rngs/adaptor/read.rs renamed to src/rngs/adapter/read.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,14 @@ use std::io::Read;
1515
use rand_core::{RngCore, Error, ErrorKind, impls};
1616

1717

18-
/// An RNG that reads random bytes straight from a `Read`.
18+
/// An RNG that reads random bytes straight from any type supporting
19+
/// `std::io::Read`, for example files.
1920
///
2021
/// This will work best with an infinite reader, but that is not required.
2122
///
23+
/// This can be used with `/dev/urandom` on Unix but it is recommended to use
24+
/// [`OsRng`] instead.
25+
///
2226
/// # Panics
2327
///
2428
/// `ReadRng` uses `std::io::read_exact`, which retries on interrupts. All other
@@ -35,6 +39,8 @@ use rand_core::{RngCore, Error, ErrorKind, impls};
3539
/// let mut rng = read::ReadRng::new(&data[..]);
3640
/// println!("{:x}", rng.gen::<u32>());
3741
/// ```
42+
///
43+
/// [`OsRng`]: ../struct.OsRng.html
3844
#[derive(Debug)]
3945
pub struct ReadRng<R> {
4046
reader: R
File renamed without changes.

src/rngs/jitter.rs

Lines changed: 88 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@
1818
1919
// Note: the C implementation of `Jitterentropy` relies on being compiled
2020
// without optimizations. This implementation goes through lengths to make the
21-
// compiler not optimise out what is technically dead code, but that does
22-
// influence timing jitter.
21+
// compiler not optimize out code which does influence timing jitter, but is
22+
// technically dead code.
2323

2424
use rand_core::{RngCore, CryptoRng, Error, ErrorKind, impls};
2525

@@ -47,10 +47,90 @@ const MEMORY_SIZE: usize = MEMORY_BLOCKS * MEMORY_BLOCKSIZE;
4747
/// Use of `JitterRng` is recommended for initializing cryptographic PRNGs when
4848
/// [`OsRng`] is not available.
4949
///
50+
/// `JitterRng` can be used without the standard library, but not conveniently,
51+
/// you must provide a high-precision timer and carefully have to follow the
52+
/// instructions of [`new_with_timer`].
53+
///
5054
/// This implementation is based on
5155
/// [Jitterentropy](http://www.chronox.de/jent.html) version 2.1.0.
5256
///
57+
/// # Quality testing
58+
///
59+
/// [`JitterRng::new()`] has build-in, but limited, quality testing, however
60+
/// before using `JitterRng` on untested hardware, or after changes that could
61+
/// effect how the code is optimized (such as a new LLVM version), it is
62+
/// recommend to run the much more stringent
63+
/// [NIST SP 800-90B Entropy Estimation Suite](
64+
/// https://github.com/usnistgov/SP800-90B_EntropyAssessment).
65+
///
66+
/// Use the following code using [`timer_stats`] to collect the data:
67+
///
68+
/// ```no_run
69+
/// use rand::jitter::JitterRng;
70+
/// #
71+
/// # use std::error::Error;
72+
/// # use std::fs::File;
73+
/// # use std::io::Write;
74+
/// #
75+
/// # fn try_main() -> Result<(), Box<Error>> {
76+
/// let mut rng = JitterRng::new()?;
77+
///
78+
/// // 1_000_000 results are required for the
79+
/// // NIST SP 800-90B Entropy Estimation Suite
80+
/// const ROUNDS: usize = 1_000_000;
81+
/// let mut deltas_variable: Vec<u8> = Vec::with_capacity(ROUNDS);
82+
/// let mut deltas_minimal: Vec<u8> = Vec::with_capacity(ROUNDS);
83+
///
84+
/// for _ in 0..ROUNDS {
85+
/// deltas_variable.push(rng.timer_stats(true) as u8);
86+
/// deltas_minimal.push(rng.timer_stats(false) as u8);
87+
/// }
88+
///
89+
/// // Write out after the statistics collection loop, to not disturb the
90+
/// // test results.
91+
/// File::create("jitter_rng_var.bin")?.write(&deltas_variable)?;
92+
/// File::create("jitter_rng_min.bin")?.write(&deltas_minimal)?;
93+
/// #
94+
/// # Ok(())
95+
/// # }
96+
/// #
97+
/// # fn main() {
98+
/// # try_main().unwrap();
99+
/// # }
100+
/// ```
101+
///
102+
/// This will produce two files: `jitter_rng_var.bin` and `jitter_rng_min.bin`.
103+
/// Run the Entropy Estimation Suite in three configurations, as outlined below.
104+
/// Every run has two steps. One step to produce an estimation, another to
105+
/// validate the estimation.
106+
///
107+
/// 1. Estimate the expected amount of entropy that is at least available with
108+
/// each round of the entropy collector. This number should be greater than
109+
/// the amount estimated with `64 / test_timer()`.
110+
/// ```sh
111+
/// python noniid_main.py -v jitter_rng_var.bin 8
112+
/// restart.py -v jitter_rng_var.bin 8 <min-entropy>
113+
/// ```
114+
/// 2. Estimate the expected amount of entropy that is available in the last 4
115+
/// bits of the timer delta after running noice sources. Note that a value of
116+
/// `3.70` is the minimum estimated entropy for true randomness.
117+
/// ```sh
118+
/// python noniid_main.py -v -u 4 jitter_rng_var.bin 4
119+
/// restart.py -v -u 4 jitter_rng_var.bin 4 <min-entropy>
120+
/// ```
121+
/// 3. Estimate the expected amount of entropy that is available to the entropy
122+
/// collector if both noice sources only run their minimal number of times.
123+
/// This measures the absolute worst-case, and gives a lower bound for the
124+
/// available entropy.
125+
/// ```sh
126+
/// python noniid_main.py -v -u 4 jitter_rng_min.bin 4
127+
/// restart.py -v -u 4 jitter_rng_min.bin 4 <min-entropy>
128+
/// ```
129+
///
53130
/// [`OsRng`]: struct.OsRng.html
131+
/// [`JitterRng::new()`]: struct.JitterRng.html#method.new
132+
/// [`new_with_timer`]: struct.JitterRng.html#method.new_with_timer
133+
/// [`timer_stats`]: struct.JitterRng.html#method.timer_stats
54134
pub struct JitterRng {
55135
data: u64, // Actual random number
56136
// Number of rounds to run the entropy collector per 64 bits
@@ -670,81 +750,19 @@ impl JitterRng {
670750
}
671751

672752
/// Statistical test: return the timer delta of one normal run of the
673-
/// `JitterEntropy` entropy collector.
753+
/// `JitterRng` entropy collector.
674754
///
675755
/// Setting `var_rounds` to `true` will execute the memory access and the
676756
/// CPU jitter noice sources a variable amount of times (just like a real
677-
/// `JitterEntropy` round).
757+
/// `JitterRng` round).
678758
///
679759
/// Setting `var_rounds` to `false` will execute the noice sources the
680760
/// minimal number of times. This can be used to measure the minimum amount
681-
/// of entropy one round of entropy collector can collect in the worst case.
682-
///
683-
/// # Example
684-
///
685-
/// Use `timer_stats` to run the [NIST SP 800-90B Entropy Estimation Suite](
686-
/// https://github.com/usnistgov/SP800-90B_EntropyAssessment).
687-
///
688-
/// This is the recommended way to test the quality of `JitterRng`. It
689-
/// should be run before using the RNG on untested hardware, after changes
690-
/// that could effect how the code is optimised, and after major compiler
691-
/// compiler changes, like a new LLVM version.
692-
///
693-
/// First generate two files `jitter_rng_var.bin` and `jitter_rng_var.min`.
694-
///
695-
/// Execute `python noniid_main.py -v jitter_rng_var.bin 8`, and validate it
696-
/// with `restart.py -v jitter_rng_var.bin 8 <min-entropy>`.
697-
/// This number is the expected amount of entropy that is at least available
698-
/// for each round of the entropy collector. This number should be greater
699-
/// than the amount estimated with `64 / test_timer()`.
700-
///
701-
/// Execute `python noniid_main.py -v -u 4 jitter_rng_var.bin 4`, and
702-
/// validate it with `restart.py -v -u 4 jitter_rng_var.bin 4 <min-entropy>`.
703-
/// This number is the expected amount of entropy that is available in the
704-
/// last 4 bits of the timer delta after running noice sources. Note that
705-
/// a value of 3.70 is the minimum estimated entropy for true randomness.
706-
///
707-
/// Execute `python noniid_main.py -v -u 4 jitter_rng_var.bin 4`, and
708-
/// validate it with `restart.py -v -u 4 jitter_rng_var.bin 4 <min-entropy>`.
709-
/// This number is the expected amount of entropy that is available to the
710-
/// entropy collecter if both noice sources only run their minimal number of
711-
/// times. This measures the absolute worst-case, and gives a lower bound
712-
/// for the available entropy.
713-
///
714-
/// ```rust,no_run
715-
/// use rand::jitter::JitterRng;
716-
/// #
717-
/// # use std::error::Error;
718-
/// # use std::fs::File;
719-
/// # use std::io::Write;
720-
/// #
721-
/// # fn try_main() -> Result<(), Box<Error>> {
722-
/// let mut rng = JitterRng::new()?;
723-
///
724-
/// // 1_000_000 results are required for the NIST SP 800-90B Entropy
725-
/// // Estimation Suite
726-
/// const ROUNDS: usize = 1_000_000;
727-
/// let mut deltas_variable: Vec<u8> = Vec::with_capacity(ROUNDS);
728-
/// let mut deltas_minimal: Vec<u8> = Vec::with_capacity(ROUNDS);
729-
///
730-
/// for _ in 0..ROUNDS {
731-
/// deltas_variable.push(rng.timer_stats(true) as u8);
732-
/// deltas_minimal.push(rng.timer_stats(false) as u8);
733-
/// }
734-
///
735-
/// // Write out after the statistics collection loop, to not disturb the
736-
/// // test results.
737-
/// File::create("jitter_rng_var.bin")?.write(&deltas_variable)?;
738-
/// File::create("jitter_rng_min.bin")?.write(&deltas_minimal)?;
739-
/// #
740-
/// # Ok(())
741-
/// # }
742-
/// #
743-
/// # fn main() {
744-
/// # try_main().unwrap();
745-
/// # }
746-
/// ```
761+
/// of entropy one round of the entropy collector can collect in the worst
762+
/// case.
747763
///
764+
/// See [Quality testing](struct.JitterRng.html#quality-testing) on how to
765+
/// use `timer_stats` to test the quality of `JitterRng`.
748766
#[cfg(feature="std")]
749767
pub fn timer_stats(&mut self, var_rounds: bool) -> i64 {
750768
let mut mem = [0; MEMORY_SIZE];

0 commit comments

Comments
 (0)