Skip to content

Commit

Permalink
Merge pull request #373 from dhardy/doc
Browse files Browse the repository at this point in the history
Doc
  • Loading branch information
dhardy committed Apr 5, 2018
2 parents 73ea10f + c03deb6 commit 628a952
Show file tree
Hide file tree
Showing 6 changed files with 72 additions and 68 deletions.
2 changes: 1 addition & 1 deletion rand_core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ pub trait BlockRngCore {
/// predict the next bit with probability significantly greater than 50%.
///
/// Some generators may satisfy an additional property, however this is not
/// required: if the CSPRNG's state is revealed, it should not be
/// required by this trait: if the CSPRNG's state is revealed, it should not be
/// computationally-feasible to reconstruct output prior to this. Some other
/// generators allow backwards-computation and are consided *reversible*.
///
Expand Down
26 changes: 19 additions & 7 deletions src/distributions/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,18 @@

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

use Rng;

Expand Down Expand Up @@ -129,6 +137,10 @@ mod impls {
}

/// Types (distributions) that can be used to create a random instance of `T`.
///
/// All implementations are expected to be immutable; this has the significant
/// advantage of not needing to consider thread safety, and for most
/// distributions efficient state-less sampling algorithms are available.
pub trait Distribution<T> {
/// Generate a random value of `T`, using `rng` as the source of randomness.
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> T;
Expand Down Expand Up @@ -260,9 +272,9 @@ impl<'a, T, D: Distribution<T>> Distribution<T> for &'a D {
///
/// - The chance to generate a specific value, like exactly 0.0, is *tiny*. No
/// (or almost no) sensible code relies on an exact floating-point value to be
/// generated with a very small chance (1 in ~8 million (2^23) for `f32`, and
/// 1 in 2^52 for `f64`). What is relied on is having a uniform distribution
/// and a mean of `0.5`.
/// generated with a very small chance (1 in 2<sup>23</sup> (approx. 8
/// million) for `f32`, and 1 in 2<sup>52</sup> for `f64`). What is relied on
/// is having a uniform distribution and a mean of `0.5`.
/// - Several common algorithms rely on never seeing the value `0.0` generated,
/// i.e. they rely on an open interval. For example when the logarithm of the
/// value is taken, or used as a devisor.
Expand Down
9 changes: 5 additions & 4 deletions src/entropy_rng.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ use rand_core::{RngCore, CryptoRng, Error, impls};
use os::OsRng;
use jitter::JitterRng;

/// A generator provided specifically for securely seeding algorithmic
/// generators (PRNGs).
/// An interface returning random data from external source(s), provided
/// specifically for securely seeding algorithmic generators (PRNGs).
///
/// Where possible, `EntropyRng` retrieves random data from the operating
/// system's interface for random numbers ([`OsRng`]); if that fails it will
Expand All @@ -27,8 +27,9 @@ use jitter::JitterRng;
///
/// This is either a little slow ([`OsRng`] requires a system call) or extremely
/// slow ([`JitterRng`] must use significant CPU time to generate sufficient
/// jitter). It is recommended to only use `EntropyRng` to seed a PRNG (as in
/// [`thread_rng`]) or to generate a small key.
/// jitter); for better performance it is common to seed a local PRNG from
/// external entropy then primarily use the local PRNG ([`thread_rng`] is
/// provided as a convenient, local, automatically-seeded CSPRNG).
///
/// [`OsRng`]: os/struct.OsRng.html
/// [`JitterRng`]: jitter/struct.JitterRng.html
Expand Down
87 changes: 37 additions & 50 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@
//! use [`SeedableRng::from_seed`] or a constructor specific to the generator
//! (e.g. [`IsaacRng::new_from_u64`]).
//!
//! # Applying / converting random data
//! ## Applying / converting random data
//!
//! The [`RngCore`] trait allows generators to implement a common interface for
//! retrieving random data, but how should you use this? Typically users should
Expand All @@ -94,56 +94,43 @@
//!
//! The [`seq`] module has a few tools applicable to sliceable or iterable data.
//!
//! # Cryptographic security
//! ## Cryptographic security
//!
//! First, lets recap some terminology:
//!
//! - **PRNG:** *Pseudo-Random-Number-Generator* is another name for an
//! *algorithmic generator*
//! - **CSPRNG:** a *Cryptographically Secure* PRNG
//!
//! Security analysis requires a threat model and expert review; we can provide
//! neither, but can provide some guidance. We assume that the goal is to
//! obtain secret random data and that some source of secrets ("entropy") is
//! available; that is, [`EntropyRng`] is functional.
//!
//! Potential threat: is the entropy source secure? The primary entropy source
//! is [`OsRng`] which is simply a wrapper around the platform's native "secure
//! entropy source"; usually this is available (outside of embedded platforms)
//! and usually you can trust this (some caveats may apply; see [`OsRng`] doc).
//! The fallback source used by [`EntropyRng`] is [`JitterRng`] which runs extensive
//! tests on the quality of the CPU timer and is conservative in its estimates
//! of the entropy harvested from each time sample; this makes it slow but very
//! strong. Using [`EntropyRng`] directly should therefore be secure; the main
//! reason not to is performance, which is why many applications use local
//! algorithmic generators.
//!
//! Potential threat: are algorithmic generators predictable? Certainly some
//! are; algorithmic generators fall broadly into two categories: those using a
//! small amount of state (e.g. one to four 32- or 64-bit words) designed for
//! non-security applications and those designed to be secure, typically with
//! much larger state space and complex initialisation. The former should not be
//! trusted to be secure, the latter may or may not have known weaknesses or
//! may even have been proven secure under a specified adversarial model. We
//! provide some notes on the security of the cryptographic algorithmic
//! generators provided by this crate, [`Hc128Rng`] and [`ChaChaRng`]. Note that
//! previously [`IsaacRng`] and [`Isaac64Rng`] were used as "reasonably strong
//! generators"; these have no known weaknesses but also have no proofs of
//! security, thus are not recommended for cryptographic uses.
//!
//! Potential threat: could the internal state of a cryptographic generator be
//! leaked? This falls under the topic of "side channel attacks", and multiple
//! variants are possible: the state of the generators being accidentally
//! printed in log files or some other application output, the process's memory
//! being copied somehow, the process being forked and both sub-processes
//! outputting the same random sequence but such that one of those can be read;
//! likely some other side-channel attacks are possible in some circumstances.
//! It is typically impossible to prove immunity to all side-channel attacks,
//! however some mitigation of known threats is usually possible, for example
//! all generators implemented in this crate have a custom `Debug`
//! implementation omitting all internal state, and [`ReseedingRng`] allows
//! periodic reseeding such that a long-running process with leaked generator
//! state should eventually recover to an unknown state. In the future we plan
//! to add further mitigations; see issue #314.
//! neither, but we can provide a few hints. We assume that the goal is to
//! produce secret apparently-random data. Therefore, we need:
//!
//! We provide the [`CryptoRng`] marker trait as an indication of which random
//! generators/sources may be used for cryptographic applications; this should
//! be considered advisory only does not imply any protection against
//! side-channel attacks.
//! - A good source of entropy. A known algorithm given known input data is
//! trivial to predict, and likewise if there's a non-negligable chance that
//! the input to a PRNG is guessable then there's a chance its output is too.
//! We recommend seeding CSPRNGs with [`EntropyRng`] or [`OsRng`] which
//! provide fresh "random" values from an external source.
//! One can also seed from another CSPRNG, e.g. `thread_rng`, which is faster,
//! but adds another component which must be trusted.
//! - A strong algorithmic generator. It is possible to use a good entropy
//! source like `OsRng` directly, and in some cases this is the best option,
//! but for better performance (or if requiring reproducible values generated
//! from a fixed seed) it is common to use a local CSPRNG. The basic security
//! that CSPRNGs must provide is making it infeasible to predict future output
//! given a sample of past output. A further security that *some* CSPRNGs
//! provide is *forward secrecy*; this ensures that in the event that the
//! algorithm's state is revealed, it is infeasible to reconstruct past
//! output. See the [`CryptoRng`] trait and notes on individual algorithms.
//! - To be careful not to leak secrets like keys and CSPRNG's internal state
//! and robust against "side channel attacks". This goes well beyond the scope
//! of random number generation, but this crate takes some precautions:
//! - to avoid printing CSPRNG state in log files, implementations have a
//! custom `Debug` implementation which omits all internal state
//! - `thread_rng` uses [`ReseedingRng`] to periodically refresh its state
//! - in the future we plan to add some protection against fork attacks
//! (where the process is forked and each clone generates the same "random"
//! numbers); this is not yet implemented (see issues #314, #370)
//!
//! # Examples
//!
Expand Down Expand Up @@ -489,9 +476,9 @@ pub trait Rng: RngCore {
/// # Accuracy note
///
/// `gen_bool` uses 32 bits of the RNG, so if you use it to generate close
/// to or more than 2^32 results, a tiny bias may become noticable.
/// to or more than `2^32` results, a tiny bias may become noticable.
/// A notable consequence of the method used here is that the worst case is
/// `rng.gen_bool(0.0)`: it has a chance of 1 in 2^32 of being true, while
/// `rng.gen_bool(0.0)`: it has a chance of 1 in `2^32` of being true, while
/// it should always be false. But using `gen_bool` to consume *many* values
/// from an RNG just to consistently generate `false` does not match with
/// the intent of this method.
Expand Down
8 changes: 5 additions & 3 deletions src/prng/isaac.rs
Original file line number Diff line number Diff line change
Expand Up @@ -162,11 +162,11 @@ impl BlockRngCore for IsaacCore {
type Item = u32;
type Results = IsaacArray<Self::Item>;

/// Refills the output buffer (`results`)
/// See also the pseudocode desciption of the algorithm at the top of this
/// file.
/// Refills the output buffer, `results`. See also the pseudocode desciption
/// of the algorithm in the [`Isaac64Rng`] documentation.
///
/// Optimisations used (similar to the reference implementation):
///
/// - The loop is unrolled 4 times, once for every constant of mix().
/// - The contents of the main loop are moved to a function `rngstep`, to
/// reduce code duplication.
Expand All @@ -181,6 +181,8 @@ impl BlockRngCore for IsaacCore {
/// from `results` in reverse. We read them in the normal direction, to
/// make `fill_bytes` a memcopy. To maintain compatibility we fill in
/// reverse.
///
/// [`IsaacRng`]: struct.IsaacRng.html
fn generate(&mut self, results: &mut IsaacArray<Self::Item>) {
self.c += w(1);
// abbreviations
Expand Down
8 changes: 5 additions & 3 deletions src/prng/isaac64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -152,11 +152,11 @@ impl BlockRngCore for Isaac64Core {
type Item = u64;
type Results = IsaacArray<Self::Item>;

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

0 comments on commit 628a952

Please sign in to comment.