Skip to content

Commit 628a952

Browse files
authored
Merge pull request #373 from dhardy/doc
Doc
2 parents 73ea10f + c03deb6 commit 628a952

File tree

6 files changed

+72
-68
lines changed

6 files changed

+72
-68
lines changed

rand_core/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,7 @@ pub trait BlockRngCore {
251251
/// predict the next bit with probability significantly greater than 50%.
252252
///
253253
/// Some generators may satisfy an additional property, however this is not
254-
/// required: if the CSPRNG's state is revealed, it should not be
254+
/// required by this trait: if the CSPRNG's state is revealed, it should not be
255255
/// computationally-feasible to reconstruct output prior to this. Some other
256256
/// generators allow backwards-computation and are consided *reversible*.
257257
///

src/distributions/mod.rs

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,18 @@
1010

1111
//! Sampling from random distributions.
1212
//!
13-
//! A distribution may have internal state describing the distribution of
14-
//! generated values; for example `Range` needs to know its upper and lower
15-
//! bounds. Distributions use the `Distribution` trait to yield values: call
16-
//! `distr.sample(&mut rng)` to get a random variable.
13+
//! Distributions are stateless (i.e. immutable) objects controlling the
14+
//! production of values of some type `T` from a presumed uniform randomness
15+
//! source. These objects may have internal parameters set at contruction time
16+
//! (e.g. [`Range`], which has configurable bounds) or may have no internal
17+
//! parameters (e.g. [`Standard`]).
18+
//!
19+
//! All distributions support the [`Distribution`] trait, and support usage
20+
//! via `distr.sample(&mut rng)` as well as via `rng.sample(distr)`.
21+
//!
22+
//! [`Distribution`]: trait.Distribution.html
23+
//! [`Range`]: range/struct.Range.html
24+
//! [`Standard`]: struct.Standard.html
1725
1826
use Rng;
1927

@@ -129,6 +137,10 @@ mod impls {
129137
}
130138

131139
/// Types (distributions) that can be used to create a random instance of `T`.
140+
///
141+
/// All implementations are expected to be immutable; this has the significant
142+
/// advantage of not needing to consider thread safety, and for most
143+
/// distributions efficient state-less sampling algorithms are available.
132144
pub trait Distribution<T> {
133145
/// Generate a random value of `T`, using `rng` as the source of randomness.
134146
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> T;
@@ -260,9 +272,9 @@ impl<'a, T, D: Distribution<T>> Distribution<T> for &'a D {
260272
///
261273
/// - The chance to generate a specific value, like exactly 0.0, is *tiny*. No
262274
/// (or almost no) sensible code relies on an exact floating-point value to be
263-
/// generated with a very small chance (1 in ~8 million (2^23) for `f32`, and
264-
/// 1 in 2^52 for `f64`). What is relied on is having a uniform distribution
265-
/// and a mean of `0.5`.
275+
/// generated with a very small chance (1 in 2<sup>23</sup> (approx. 8
276+
/// million) for `f32`, and 1 in 2<sup>52</sup> for `f64`). What is relied on
277+
/// is having a uniform distribution and a mean of `0.5`.
266278
/// - Several common algorithms rely on never seeing the value `0.0` generated,
267279
/// i.e. they rely on an open interval. For example when the logarithm of the
268280
/// value is taken, or used as a devisor.

src/entropy_rng.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ use rand_core::{RngCore, CryptoRng, Error, impls};
1414
use os::OsRng;
1515
use jitter::JitterRng;
1616

17-
/// A generator provided specifically for securely seeding algorithmic
18-
/// generators (PRNGs).
17+
/// An interface returning random data from external source(s), provided
18+
/// specifically for securely seeding algorithmic generators (PRNGs).
1919
///
2020
/// Where possible, `EntropyRng` retrieves random data from the operating
2121
/// system's interface for random numbers ([`OsRng`]); if that fails it will
@@ -27,8 +27,9 @@ use jitter::JitterRng;
2727
///
2828
/// This is either a little slow ([`OsRng`] requires a system call) or extremely
2929
/// slow ([`JitterRng`] must use significant CPU time to generate sufficient
30-
/// jitter). It is recommended to only use `EntropyRng` to seed a PRNG (as in
31-
/// [`thread_rng`]) or to generate a small key.
30+
/// jitter); for better performance it is common to seed a local PRNG from
31+
/// external entropy then primarily use the local PRNG ([`thread_rng`] is
32+
/// provided as a convenient, local, automatically-seeded CSPRNG).
3233
///
3334
/// [`OsRng`]: os/struct.OsRng.html
3435
/// [`JitterRng`]: jitter/struct.JitterRng.html

src/lib.rs

Lines changed: 37 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@
7676
//! use [`SeedableRng::from_seed`] or a constructor specific to the generator
7777
//! (e.g. [`IsaacRng::new_from_u64`]).
7878
//!
79-
//! # Applying / converting random data
79+
//! ## Applying / converting random data
8080
//!
8181
//! The [`RngCore`] trait allows generators to implement a common interface for
8282
//! retrieving random data, but how should you use this? Typically users should
@@ -94,56 +94,43 @@
9494
//!
9595
//! The [`seq`] module has a few tools applicable to sliceable or iterable data.
9696
//!
97-
//! # Cryptographic security
97+
//! ## Cryptographic security
98+
//!
99+
//! First, lets recap some terminology:
100+
//!
101+
//! - **PRNG:** *Pseudo-Random-Number-Generator* is another name for an
102+
//! *algorithmic generator*
103+
//! - **CSPRNG:** a *Cryptographically Secure* PRNG
98104
//!
99105
//! Security analysis requires a threat model and expert review; we can provide
100-
//! neither, but can provide some guidance. We assume that the goal is to
101-
//! obtain secret random data and that some source of secrets ("entropy") is
102-
//! available; that is, [`EntropyRng`] is functional.
103-
//!
104-
//! Potential threat: is the entropy source secure? The primary entropy source
105-
//! is [`OsRng`] which is simply a wrapper around the platform's native "secure
106-
//! entropy source"; usually this is available (outside of embedded platforms)
107-
//! and usually you can trust this (some caveats may apply; see [`OsRng`] doc).
108-
//! The fallback source used by [`EntropyRng`] is [`JitterRng`] which runs extensive
109-
//! tests on the quality of the CPU timer and is conservative in its estimates
110-
//! of the entropy harvested from each time sample; this makes it slow but very
111-
//! strong. Using [`EntropyRng`] directly should therefore be secure; the main
112-
//! reason not to is performance, which is why many applications use local
113-
//! algorithmic generators.
114-
//!
115-
//! Potential threat: are algorithmic generators predictable? Certainly some
116-
//! are; algorithmic generators fall broadly into two categories: those using a
117-
//! small amount of state (e.g. one to four 32- or 64-bit words) designed for
118-
//! non-security applications and those designed to be secure, typically with
119-
//! much larger state space and complex initialisation. The former should not be
120-
//! trusted to be secure, the latter may or may not have known weaknesses or
121-
//! may even have been proven secure under a specified adversarial model. We
122-
//! provide some notes on the security of the cryptographic algorithmic
123-
//! generators provided by this crate, [`Hc128Rng`] and [`ChaChaRng`]. Note that
124-
//! previously [`IsaacRng`] and [`Isaac64Rng`] were used as "reasonably strong
125-
//! generators"; these have no known weaknesses but also have no proofs of
126-
//! security, thus are not recommended for cryptographic uses.
127-
//!
128-
//! Potential threat: could the internal state of a cryptographic generator be
129-
//! leaked? This falls under the topic of "side channel attacks", and multiple
130-
//! variants are possible: the state of the generators being accidentally
131-
//! printed in log files or some other application output, the process's memory
132-
//! being copied somehow, the process being forked and both sub-processes
133-
//! outputting the same random sequence but such that one of those can be read;
134-
//! likely some other side-channel attacks are possible in some circumstances.
135-
//! It is typically impossible to prove immunity to all side-channel attacks,
136-
//! however some mitigation of known threats is usually possible, for example
137-
//! all generators implemented in this crate have a custom `Debug`
138-
//! implementation omitting all internal state, and [`ReseedingRng`] allows
139-
//! periodic reseeding such that a long-running process with leaked generator
140-
//! state should eventually recover to an unknown state. In the future we plan
141-
//! to add further mitigations; see issue #314.
106+
//! neither, but we can provide a few hints. We assume that the goal is to
107+
//! produce secret apparently-random data. Therefore, we need:
142108
//!
143-
//! We provide the [`CryptoRng`] marker trait as an indication of which random
144-
//! generators/sources may be used for cryptographic applications; this should
145-
//! be considered advisory only does not imply any protection against
146-
//! side-channel attacks.
109+
//! - A good source of entropy. A known algorithm given known input data is
110+
//! trivial to predict, and likewise if there's a non-negligable chance that
111+
//! the input to a PRNG is guessable then there's a chance its output is too.
112+
//! We recommend seeding CSPRNGs with [`EntropyRng`] or [`OsRng`] which
113+
//! provide fresh "random" values from an external source.
114+
//! One can also seed from another CSPRNG, e.g. `thread_rng`, which is faster,
115+
//! but adds another component which must be trusted.
116+
//! - A strong algorithmic generator. It is possible to use a good entropy
117+
//! source like `OsRng` directly, and in some cases this is the best option,
118+
//! but for better performance (or if requiring reproducible values generated
119+
//! from a fixed seed) it is common to use a local CSPRNG. The basic security
120+
//! that CSPRNGs must provide is making it infeasible to predict future output
121+
//! given a sample of past output. A further security that *some* CSPRNGs
122+
//! provide is *forward secrecy*; this ensures that in the event that the
123+
//! algorithm's state is revealed, it is infeasible to reconstruct past
124+
//! output. See the [`CryptoRng`] trait and notes on individual algorithms.
125+
//! - To be careful not to leak secrets like keys and CSPRNG's internal state
126+
//! and robust against "side channel attacks". This goes well beyond the scope
127+
//! of random number generation, but this crate takes some precautions:
128+
//! - to avoid printing CSPRNG state in log files, implementations have a
129+
//! custom `Debug` implementation which omits all internal state
130+
//! - `thread_rng` uses [`ReseedingRng`] to periodically refresh its state
131+
//! - in the future we plan to add some protection against fork attacks
132+
//! (where the process is forked and each clone generates the same "random"
133+
//! numbers); this is not yet implemented (see issues #314, #370)
147134
//!
148135
//! # Examples
149136
//!
@@ -489,9 +476,9 @@ pub trait Rng: RngCore {
489476
/// # Accuracy note
490477
///
491478
/// `gen_bool` uses 32 bits of the RNG, so if you use it to generate close
492-
/// to or more than 2^32 results, a tiny bias may become noticable.
479+
/// to or more than `2^32` results, a tiny bias may become noticable.
493480
/// A notable consequence of the method used here is that the worst case is
494-
/// `rng.gen_bool(0.0)`: it has a chance of 1 in 2^32 of being true, while
481+
/// `rng.gen_bool(0.0)`: it has a chance of 1 in `2^32` of being true, while
495482
/// it should always be false. But using `gen_bool` to consume *many* values
496483
/// from an RNG just to consistently generate `false` does not match with
497484
/// the intent of this method.

src/prng/isaac.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -162,11 +162,11 @@ impl BlockRngCore for IsaacCore {
162162
type Item = u32;
163163
type Results = IsaacArray<Self::Item>;
164164

165-
/// Refills the output buffer (`results`)
166-
/// See also the pseudocode desciption of the algorithm at the top of this
167-
/// file.
165+
/// Refills the output buffer, `results`. See also the pseudocode desciption
166+
/// of the algorithm in the [`Isaac64Rng`] documentation.
168167
///
169168
/// Optimisations used (similar to the reference implementation):
169+
///
170170
/// - The loop is unrolled 4 times, once for every constant of mix().
171171
/// - The contents of the main loop are moved to a function `rngstep`, to
172172
/// reduce code duplication.
@@ -181,6 +181,8 @@ impl BlockRngCore for IsaacCore {
181181
/// from `results` in reverse. We read them in the normal direction, to
182182
/// make `fill_bytes` a memcopy. To maintain compatibility we fill in
183183
/// reverse.
184+
///
185+
/// [`IsaacRng`]: struct.IsaacRng.html
184186
fn generate(&mut self, results: &mut IsaacArray<Self::Item>) {
185187
self.c += w(1);
186188
// abbreviations

src/prng/isaac64.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -152,11 +152,11 @@ impl BlockRngCore for Isaac64Core {
152152
type Item = u64;
153153
type Results = IsaacArray<Self::Item>;
154154

155-
/// Refills the output buffer (`results`)
156-
/// See also the pseudocode desciption of the algorithm at the top of this
157-
/// file.
155+
/// Refills the output buffer, `results`. See also the pseudocode desciption
156+
/// of the algorithm in the [`Isaac64Rng`] documentation.
158157
///
159158
/// Optimisations used (similar to the reference implementation):
159+
///
160160
/// - The loop is unrolled 4 times, once for every constant of mix().
161161
/// - The contents of the main loop are moved to a function `rngstep`, to
162162
/// reduce code duplication.
@@ -171,6 +171,8 @@ impl BlockRngCore for Isaac64Core {
171171
/// from `results` in reverse. We read them in the normal direction, to
172172
/// make `fill_bytes` a memcopy. To maintain compatibility we fill in
173173
/// reverse.
174+
///
175+
/// [`Isaac64Rng`]: struct.Isaac64Rng.html
174176
fn generate(&mut self, results: &mut IsaacArray<Self::Item>) {
175177
self.c += w(1);
176178
// abbreviations

0 commit comments

Comments
 (0)