diff --git a/src/libstd/rand/distributions.rs b/src/libstd/rand/distributions.rs index b31e72bc697..23726490b4a 100644 --- a/src/libstd/rand/distributions.rs +++ b/src/libstd/rand/distributions.rs @@ -8,17 +8,17 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! Sampling from random distributions +/*! +Sampling from random distributions. -// Some implementations use the Ziggurat method -// https://en.wikipedia.org/wiki/Ziggurat_algorithm -// -// The version used here is ZIGNOR [Doornik 2005, "An Improved -// Ziggurat Method to Generate Normal Random Samples"] which is slower -// (about double, it generates an extra random number) than the -// canonical version [Marsaglia & Tsang 2000, "The Ziggurat Method for -// Generating Random Variables"], but more robust. If one wanted, one -// could implement VIZIGNOR the ZIGNOR paper for more speed. +This is a generalization of `Rand` to allow parameters to control the +exact properties of the generated values, e.g. the mean and standard +deviation of a normal distribution. The `Sample` trait is the most +general, and allows for generating values that change some state +internally. The `IndependentSample` trait is for generating values +that do not need to record state. + +*/ use num; use rand::{Rng,Rand}; @@ -27,16 +27,18 @@ pub use self::range::Range; pub mod range; -/// Things that can be used to create a random instance of `Support`. +/// Types that can be used to create a random instance of `Support`. pub trait Sample { /// Generate a random value of `Support`, using `rng` as the /// source of randomness. fn sample(&mut self, rng: &mut R) -> Support; } -/// `Sample`s that do not require keeping track of state, so each -/// sample is (statistically) independent of all others, assuming the -/// `Rng` used has this property. +/// `Sample`s that do not require keeping track of state. +/// +/// Since no state is recored, each sample is (statistically) +/// independent of all others, assuming the `Rng` used has this +/// property. // XXX maybe having this separate is overkill (the only reason is to // take &self rather than &mut self)? or maybe this should be the // trait called `Sample` and the other should be `DependentSample`. @@ -91,13 +93,19 @@ fn ziggurat(rng: &mut R, } } -/// A wrapper around an `f64` to generate N(0, 1) random numbers (a.k.a. a -/// standard normal, or Gaussian). Multiplying the generated values by the -/// desired standard deviation `sigma` then adding the desired mean `mu` will -/// give N(mu, sigma^2) distributed random numbers. +/// A wrapper around an `f64` to generate N(0, 1) random numbers +/// (a.k.a. a standard normal, or Gaussian). /// -/// Note that this has to be unwrapped before use as an `f64` (using either -/// `*` or `cast::transmute` is safe). +/// See `Normal` for the general normal distribution. That this has to +/// be unwrapped before use as an `f64` (using either `*` or +/// `cast::transmute` is safe). +/// +/// Implemented via the ZIGNOR variant[1] of the Ziggurat method. +/// +/// [1]: Jurgen A. Doornik (2005). [*An Improved Ziggurat Method to +/// Generate Normal Random +/// Samples*](http://www.doornik.com/research/ziggurat.pdf). Nuffield +/// College, Oxford pub struct StandardNormal(f64); impl Rand for StandardNormal { @@ -135,8 +143,10 @@ impl Rand for StandardNormal { } } -/// The `N(mean, std_dev**2)` distribution, i.e. samples from a normal -/// distribution with mean `mean` and standard deviation `std_dev`. +/// The normal distribution `N(mean, std_dev**2)`. +/// +/// This uses the ZIGNOR variant of the Ziggurat method, see +/// `StandardNormal` for more details. /// /// # Example /// @@ -175,12 +185,20 @@ impl IndependentSample for Normal { } } -/// A wrapper around an `f64` to generate Exp(1) random numbers. Dividing by -/// the desired rate `lambda` will give Exp(lambda) distributed random -/// numbers. +/// A wrapper around an `f64` to generate Exp(1) random numbers. /// -/// Note that this has to be unwrapped before use as an `f64` (using either +/// See `Exp` for the general exponential distribution.Note that this + // has to be unwrapped before use as an `f64` (using either /// `*` or `cast::transmute` is safe). +/// +/// Implemented via the ZIGNOR variant[1] of the Ziggurat method. The +/// exact description in the paper was adjusted to use tables for the +/// exponential distribution rather than normal. +/// +/// [1]: Jurgen A. Doornik (2005). [*An Improved Ziggurat Method to +/// Generate Normal Random +/// Samples*](http://www.doornik.com/research/ziggurat.pdf). Nuffield +/// College, Oxford pub struct Exp1(f64); // This could be done via `-rng.gen::().ln()` but that is slower. @@ -203,8 +221,7 @@ impl Rand for Exp1 { } } -/// The `Exp(lambda)` distribution; i.e. samples from the exponential -/// distribution with rate parameter `lambda`. +/// The exponential distribution `Exp(lambda)`. /// /// This distribution has density function: `f(x) = lambda * /// exp(-lambda * x)` for `x > 0`. diff --git a/src/libstd/rand/isaac.rs b/src/libstd/rand/isaac.rs index 0068b60cfa5..2fd58d0314e 100644 --- a/src/libstd/rand/isaac.rs +++ b/src/libstd/rand/isaac.rs @@ -18,10 +18,15 @@ use option::{None, Some}; static RAND_SIZE_LEN: u32 = 8; static RAND_SIZE: u32 = 1 << RAND_SIZE_LEN; -/// A random number generator that uses the [ISAAC -/// algorithm](http://en.wikipedia.org/wiki/ISAAC_%28cipher%29). +/// A random number generator that uses the ISAAC algorithm[1]. /// -/// The ISAAC algorithm is suitable for cryptographic purposes. +/// The ISAAC algorithm is generally accepted as suitable for +/// cryptographic purposes, but this implementation has not be +/// verified as such. Prefer a generator like `OSRng` that defers to +/// the operating system for cases that need high security. +/// +/// [1]: Bob Jenkins, [*ISAAC: A fast cryptographic random number +/// generator*](http://www.burtleburtle.net/bob/rand/isaacafa.html) pub struct IsaacRng { priv cnt: u32, priv rsl: [u32, .. RAND_SIZE], @@ -212,11 +217,16 @@ impl<'self> SeedableRng<&'self [u32]> for IsaacRng { static RAND_SIZE_64_LEN: uint = 8; static RAND_SIZE_64: uint = 1 << RAND_SIZE_64_LEN; -/// A random number generator that uses the 64-bit variant of the -/// [ISAAC -/// algorithm](http://en.wikipedia.org/wiki/ISAAC_%28cipher%29). +/// A random number generator that uses ISAAC-64[1], the 64-bit +/// variant of the ISAAC algorithm. /// -/// The ISAAC algorithm is suitable for cryptographic purposes. +/// The ISAAC algorithm is generally accepted as suitable for +/// cryptographic purposes, but this implementation has not be +/// verified as such. Prefer a generator like `OSRng` that defers to +/// the operating system for cases that need high security. +/// +/// [1]: Bob Jenkins, [*ISAAC: A fast cryptographic random number +/// generator*](http://www.burtleburtle.net/bob/rand/isaacafa.html) pub struct Isaac64Rng { priv cnt: uint, priv rsl: [u64, .. RAND_SIZE_64], diff --git a/src/libstd/rand/mod.rs b/src/libstd/rand/mod.rs index 178f5106d28..b94d8d72e37 100644 --- a/src/libstd/rand/mod.rs +++ b/src/libstd/rand/mod.rs @@ -28,6 +28,23 @@ from an operating-system source of randomness, e.g. `/dev/urandom` on Unix systems, and will automatically reseed itself from this source after generating 32 KiB of random data. +# Cryptographic security + +An application that requires random numbers for cryptographic purposes +should prefer `OSRng`, which reads randomness from one of the source +that the operating system provides (e.g. `/dev/urandom` on +Unixes). The other random number generators provided by this module +are either known to be insecure (`XorShiftRng`), or are not verified +to be secure (`IsaacRng`, `Isaac64Rng` and `StdRng`). + +*Note*: on Linux, `/dev/random` is more secure than `/dev/urandom`, +but it is a blocking RNG, and will wait until it has determined that +it has collected enough entropy to fulfill a request for random +data. It can be used with the `Rng` trait provided by this module by +opening the file and passing it to `reader::ReaderRng`. Since it +blocks, `/dev/random` should only be used to retrieve small amounts of +randomness. + # Examples ```rust @@ -516,8 +533,8 @@ pub trait SeedableRng: Rng { /// Create a random number generator with a default algorithm and seed. /// -/// It returns the cryptographically-safest `Rng` algorithm currently -/// available in Rust. If you require a specifically seeded `Rng` for +/// It returns the strongest `Rng` algorithm currently implemented in +/// pure Rust. If you require a specifically seeded `Rng` for /// consistency over time you should pick one algorithm and create the /// `Rng` yourself. /// @@ -592,12 +609,16 @@ pub fn weak_rng() -> XorShiftRng { XorShiftRng::new() } -/// An [Xorshift random number -/// generator](http://en.wikipedia.org/wiki/Xorshift). +/// An Xorshift[1] random number +/// generator. /// /// The Xorshift algorithm is not suitable for cryptographic purposes /// but is very fast. If you do not know for sure that it fits your -/// requirements, use a more secure one such as `IsaacRng`. +/// requirements, use a more secure one such as `IsaacRng` or `OSRng`. +/// +/// [1]: Marsaglia, George (July 2003). ["Xorshift +/// RNGs"](http://www.jstatsoft.org/v08/i14/paper). *Journal of +/// Statistical Software*. Vol. 8 (Issue 14). pub struct XorShiftRng { priv x: u32, priv y: u32, diff --git a/src/libstd/rand/os.rs b/src/libstd/rand/os.rs index 4c8cf06c55e..5ed8d6b10d1 100644 --- a/src/libstd/rand/os.rs +++ b/src/libstd/rand/os.rs @@ -30,8 +30,12 @@ type HCRYPTPROV = c_long; // assume they work when we call them. /// A random number generator that retrieves randomness straight from -/// the operating system. On Unix-like systems this reads from -/// `/dev/urandom`, on Windows this uses `CryptGenRandom`. +/// the operating system. Platform sources: +/// +/// - Unix-like systems (Linux, Android, Mac OSX): read directly from +/// `/dev/urandom`. +/// - Windows: calls `CryptGenRandom`, using the default cryptographic +/// service provider with the `PROV_RSA_FULL` type. /// /// This does not block. #[cfg(unix)] @@ -39,8 +43,12 @@ pub struct OSRng { priv inner: ReaderRng } /// A random number generator that retrieves randomness straight from -/// the operating system. On Unix-like systems this reads from -/// `/dev/urandom`, on Windows this uses `CryptGenRandom`. +/// the operating system. Platform sources: +/// +/// - Unix-like systems (Linux, Android, Mac OSX): read directly from +/// `/dev/urandom`. +/// - Windows: calls `CryptGenRandom`, using the default cryptographic +/// service provider with the `PROV_RSA_FULL` type. /// /// This does not block. #[cfg(windows)] diff --git a/src/rt/rust_builtin.cpp b/src/rt/rust_builtin.cpp index 17f05b59090..77020537661 100644 --- a/src/rt/rust_builtin.cpp +++ b/src/rt/rust_builtin.cpp @@ -672,6 +672,8 @@ extern "C" CDECL void rust_win32_rand_acquire(HCRYPTPROV* phProv) { win32_require (_T("CryptAcquireContext"), + // changes to the parameters here should be reflected in the docs of + // std::rand::os::OSRng CryptAcquireContext(phProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT|CRYPT_SILENT));