Skip to content

Commit

Permalink
Revise rngs module doc
Browse files Browse the repository at this point in the history
  • Loading branch information
dhardy committed May 11, 2018
1 parent bbb33f4 commit 7f5b951
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 78 deletions.
8 changes: 7 additions & 1 deletion src/rngs/adaptor/read.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,14 @@ use std::io::Read;
use rand_core::{RngCore, Error, ErrorKind, impls};


/// An RNG that reads random bytes straight from a `Read`.
/// An RNG that reads random bytes straight from any type supporting
/// `std::io::Read`, for example files.
///
/// This will work best with an infinite reader, but that is not required.
///
/// This can be used with `/dev/urandom` on Unix but it is recommended to use
/// [`OsRng`] instead.
///
/// # Panics
///
/// `ReadRng` uses `std::io::read_exact`, which retries on interrupts. All other
Expand All @@ -35,6 +39,8 @@ use rand_core::{RngCore, Error, ErrorKind, impls};
/// let mut rng = read::ReadRng::new(&data[..]);
/// println!("{:x}", rng.gen::<u32>());
/// ```
///
/// [`OsRng`]: ../struct.OsRng.html
#[derive(Debug)]
pub struct ReadRng<R> {
reader: R
Expand Down
150 changes: 74 additions & 76 deletions src/rngs/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,101 +8,95 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Various RNGs and adapters.
//!
//! This module provides two standard RNGs exposed by Rand (besides
//! specific PRNG algorithms in the [`prng` module]): [`StdRng`] and
//! [`SmallRng`]. Also there is [`ThreadRng`], an implementation of [`StdRng`]
//! put in thread-local storage.
//!
//! When to prefer [`StdRng`] over [`SmallRng`]? Whenever there might be an
//! adversary who can effect the working of an algorithm by tweaking input.
//! Examples include picking random filenames, hashmap seeding, or QuickSort
//! using Random Pivoting.
//!
//! To get a seed for those PRNGs at runtime, [`EntropyRng`], [`OsRng`] and
//! [`JitterRng`] are sources of external randomness. There might be situations
//! where may want to use one of them directly, but generally they are used to
//! just get a seed. Prefer to use the [`FromEntropy`] trait when seeding a PRNG
//! instead, which takes care of error handling and has a fallback mechanism.
//! Random number generators and adapters for common usage:
//!
//! - [`ThreadRng`], a fast, secure, auto-seeded thread-local generator
//! - [`StdRng`] and [`SmallRng`], algorithms to cover typical usage
//! - [`EntropyRng`], [`OsRng`] and [`JitterRng`] as entropy sources
//! - [`mock::StepRng`] as a simple counter for tests
//! - [`adapter::ReadRng`] to read from a file/stream
//!
//! # Background — Random number generators (RNGs)
//!
//! Pulling random numbers out of 'thin air' is very hard for a computer. Not
//! impossible, but hard and slow. Generally the operating systems collects some
//! of them, by measuring different kinds of noice/jitter in the hardware.
//!
//! What is always used instead is a psuedo-random number generator (PRNG). This
//! is a clever algorithm that can produce an infinite stream of psuedo-random
//! numbers from a small seed. There exist algorithms that produce random
//! numbers that appear in no pratical situation to be any less random than
//! pulling values 'out of thin air'. Except that the random number stream can
//! be reproduced if you know the seed.
//!
//! There are two very different groups interested in developing PRNGs: one
//! interested in simulations and statistics, another in cryptography (sometimes
//! PRNGs from the latter are more specifically called a CSPRNG). From both
//! groups Rand picks one good algorithm. They are exposed as:
//!
//! - [`SmallRng`]. Uses little memory, and is very fast.
//! The best way to make sure a PRNG is suitable for many kinds of different
//! uses is by measuring how well it performs on the RNG test suites designed
//! to measure their quality (TestU01 and PractRand).
//! The currently picked algorithm (plain Xorshift) performs very bad on them,
//! and is planned to be replaced in the next major release.
//! - [`StdRng`]. It is a requirement for a CSPRNG that the output is basically
//! indiscernible from true randomness, as otherwise information could be
//! leaked. In addition this PRNG is unpredictable, even if you know the
//! implementation. This is an important property for any situation where
//! there might be an adversary, like cryptography, but certainly not limited
//! to that. This requirement makes it slower and/or use more memory however.
//!
//! One of the problems with PRNGs is that they need a seed (which is what the
//! [`SeedableRng`] trait is for). Where do you get such a seed? Two options:
//!
//! - Just use a constant. This is good when you need reproducible results, for
//! example to procedurally generate a game world). See the
//! [`SeedableRng::from_seed`] documentation. You may want to combine this
//! with a named PRNG from the [`prng` module] or from other crates, because
//! the algorithm of [`StdRng`] and [`SmallRng`] can change per release and/or
//! platform.
//! - Get a random value from somewhere at runtime. The
//! [`FromEntropy::from_entropy`] method helps here. It will usually get the
//! seed from the operating system's PRNG (using [`EntropyRng`]).
//!
//! Another problem is that the internal state of a PRNG must change after every
//! generated number. So an PRNG always has to be mutable. For APIs this means
//! they always need to somehow preserve the state between function calls, and
//! that there can always be only one mutable reference to the PRNG.
//!
//! [`ThreadRng`] abstracts away most of these issues. It uses [`StdRng`], which
//! is always a safe choice. Seeding happens automatically on first use. The
//! PRNG's state is stored in thread local storage, so no need to plumb the
//! state through an API. You can easily get a mutable reference to it with the
//! [`thread_rng`] function.
//! Computers are inherently deterministic, so to get *random* numbers one
//! either has to use a hardware generator or collect small bits of *entropy*
//! from various sources (e.g. event timestamps, or jitter). Generally the
//! operating system will collect entropy, remove bias and provide random
//! values on demand; [`OsRng`] uses this. [`JitterRng`] is a local
//! implementation of an entropy collector using high-resolution timers. Both
//! methods have some overhead (the latter especially).
//!
//! Usually, therefore, random values are generated using a deterministic
//! algorithm seeded with random data; a so-called Pseudo-Random Number
//! Generator (PRNG). The numbers produced are not "true" random numbers but
//! can be statistically of very high quality and can be impossible to predict.
//! (They can also have obvious correlations and be trivial to predict; quality
//! varies.)
//!
//! There are two different types of PRNGs: those developed for simulations
//! and statistics, and those developed for use in cryptography; the latter are
//! called Cryptographically Secure PRNGs (CSPRNG or CPRNG). Both types can
//! have good statistical quality but the latter should also be impossible to
//! predict, even after seeing many previous output values. We choose a good
//! default algorithm for each class:
//!
//! - [`SmallRng`] is a PRNG chosen for low memory usage, high performance and
//! good statistical quality.
//! The current algorithm (plain Xorshift) unfortunately performs
//! poorly in statistical quality test suites (TestU01 and PractRand) and will
//! be replaced in the next major release.
//! - [`StdRng`] is a CSPRNG chosen for good performance and trust of security
//! (based on reviews, maturity and usage). The current algorithm is HC-128,
//! which is recommended by ECRYPT's eSTREAM project. Amortised performance
//! is (on modern x86_64 CPUs) roughly similar to [`SmallRng`], but memory
//! usage is much higher.
//!
//! The above PRNGs do not cover all use-cases; more algorithms can be found in
//! the [`prng` module], as well as in several other crates. For example, you
//! may wish a CSPRNG with significantly lower memory usage than [`StdRng`]
//! while being less concerned about performance, in which case [`ChaChaRng`]
//! is a good choice.
//!
//! As mentioned above, PRNGs require random seed data in order to produce
//! random output. This is especially important for CSPRNGs, which are still
//! deterministic algorithms, thus can only be secure if their seed value is
//! also secure. To seed a PRNG, use one of:
//!
//! - [`FromEntropy::from_entropy`]; this is the most convenient way to seed
//! with fresh, secure random data
//! - [`SeedableRng::from_rng`]; this allows seeding from another PRNG or
//! from an entropy source such as [`EntropyRng`]
//! - [`SeedableRng::from_seed`]; this is mostly useful if you wish to be able
//! to reproduce the output sequence by using a fixed seed. (Don't use
//! [`StdRng`] or [`SmallRng`] in this case since different algorithms may be
//! used by future versions of Rand; use an algorithm from the [`prng` module].)
//!
//! Finally, if you "just" want a convient, secure, fast random number source,
//! use [`ThreadRng`]. This is a thread-local CSPRNG with automatic seeding on
//! first use and periodic reseeding. Use via the [`thread_rng`] function, which
//! gets a reference to the current thread's local instance.
//!
//! ## Conclusion
//!
//! - [`thread_rng`] is what you often want to use.
//! - If you want more control, flexibility, or better performance, use
//! [`StdRng`], [`SmallRng`] or choose a specific PRNG algorithm.
//! - If you do not use [`thread_rng`], use [`FromEntropy::from_entropy`] for
//! seeding.
//! [`StdRng`], [`SmallRng`] or an algorithm from the [`prng` module].
//! - Use [`FromEntropy::from_entropy`] to seed new PRNGs.
//! - If you need reproducibility, use [`SeedableRng::from_seed`] combined with
//! a named PRNG.
//!
//! For more information, and notes on cryptographic security, see the
//! documentation in the [`prng` module].
//! More information and notes on cryptographic security can be found
//! in the [`prng` module].
//!
//! ## Examples
//!
//! Examples of seeding PRNGs:
//!
//! ```
//! # use rand::Error;
//! // StdRng with a seed obtained at runtime:
//! use rand::prelude::*;
//! # use rand::Error;
//!
//! // StdRng seeded securely by the OS or local entropy collector:
//! let mut rng = StdRng::from_entropy();
//! # let v: u32 = rng.gen();
//!
Expand Down Expand Up @@ -149,8 +143,12 @@
//! [`RngCore`]: ../trait.RngCore.html
//! [`Rng`]: ../trait.Rng.html
//! [`SeedableRng`]: ../trait.SeedableRng.html
//! [`SeedableRng::from_rng`]: ../trait.SeedableRng.html#tymethod.from_rng
//! [`SeedableRng::from_seed`]: ../trait.SeedableRng.html#tymethod.from_seed
//! [`thread_rng`]: ../fn.thread_rng.html
//! [`mock::StepRng`]: mock/struct.StepRng.html
//! [`adapter::ReadRng`]: adaptor/struct.ReadRng.html
//! [`ChaChaRng`]: ../prng/chacha/struct.ChaChaRng.html

pub mod adaptor;

Expand Down
2 changes: 1 addition & 1 deletion src/rngs/os.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use rand_core::{CryptoRng, RngCore, Error, impls};
/// Commonly it is used to initialize a user-space RNG, which can then be used
/// to generate random values with much less overhead than `OsRng`.
///
/// You may prefer to use [`EntropyRng`] instead of `OsRng`. Is is unlikely, but
/// You may prefer to use [`EntropyRng`] instead of `OsRng`. It is unlikely, but
/// not entirely theoretical, for `OsRng` to fail. In such cases [`EntropyRng`]
/// falls back on a good alternative entropy source.
///
Expand Down

0 comments on commit 7f5b951

Please sign in to comment.