Skip to main content

std/
random.rs

1//! Random value generation.
2//!
3//! This module provides two low-level interfaces for random number generation:
4//! * The [`Rng`] trait abstracts over all random number generators (RNGs) and
5//!   is intended to be used in all cases where the choice of RNG is left to the
6//!   user. It provides the [`fill_bytes`](Rng::fill_bytes) method that fills a
7//!   buffer of [`u8`]s with freshly-generated random data.
8//! * The [`SystemRng`] implements the [`Rng`] trait by asking the operating
9//!   system for cryptographically-secure random data on every call to
10//!   `fill_bytes`.
11//!
12//! In the future, higher-level interfaces for features like sampling distributions
13//! may be added to this module. Until that time, users of `fill_bytes` should
14//! take care to avoid sampling bias when using the filled byte buffer to create
15//! an instance of another type. In particular, the modulo operation is **not**
16//! suitable for constraining the range of an unconstrained number:
17//! ```compile_fail
18//! let mut buf = [0; 2];
19//! rng.fill_bytes(&mut buf);
20//! // 💀 **DO NOT DO THIS** 💀
21//! // Numbers below ca. 22000 will be twice as likely.
22//! let very_bad_random_number = u16::from_ne_bytes(buf) % 45000;
23//! ```
24//!
25//! # Examples
26//!
27//! Generating a [version 4/variant 1 UUID] represented as text:
28//! ```
29//! #![feature(random)]
30//!
31//! use std::random::{Rng, SystemRng};
32//!
33//! fn uuid(rng: &mut impl Rng) -> String {
34//!     let mut buf = [0; 16];
35//!     rng.fill_bytes(&mut buf);
36//!     // Use little-endian to make the result reproducible across architectures.
37//!     let bits = u128::from_le_bytes(buf);
38//!     let g1 = (bits >> 96) as u32;
39//!     let g2 = (bits >> 80) as u16;
40//!     let g3 = (0x4000 | (bits >> 64) & 0x0fff) as u16;
41//!     let g4 = (0x8000 | (bits >> 48) & 0x3fff) as u16;
42//!     let g5 = (bits & 0xffffffffffff) as u64;
43//!     format!("{g1:08x}-{g2:04x}-{g3:04x}-{g4:04x}-{g5:012x}")
44//! }
45//!
46//! println!("{}", uuid(&mut SystemRng));
47//! ```
48//!
49//! [version 4/variant 1 UUID]: https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random)
50
51#[unstable(feature = "random", issue = "130703")]
52pub use core::random::*;
53
54use crate::sys::random as sys;
55
56/// The system random number generator.
57///
58/// This asks the system for random data suitable for cryptographic purposes
59/// such as key generation. If security is a concern, consult the platform
60/// documentation below for the specific guarantees your target provides.
61///
62/// The high quality of randomness provided by this source means it can be quite
63/// slow on some targets. If you need a large quantity of random numbers and
64/// security is not a concern, you might want to consider using an alternative
65/// random number generator. That said, `std` attempts to use the fastest source
66/// available on the system that still provides strong security. A custom random
67/// number generator will in nearly all cases have weaker security attributes
68/// than `SystemRng`.
69///
70/// # Blocking
71///
72/// The underlying syscalls might block the calling thread until there is
73/// sufficient [entropy] in the system to seed a procedural random number
74/// generator. This is usually only a concern if the program runs immediately
75/// after the system boots.
76///
77/// # Panicking
78///
79/// Calling `fill_bytes` will panic if the system cannot provide the required
80/// random data. Due to the blocking behaviour described above, this is a
81/// permanent condition in nearly all cases and implies that the system lacks
82/// the facilities (hardware or software) necessary for collecting entropy.
83/// Non-embedded systems usually do not suffer from this limitation.
84///
85/// [entropy]: https://en.wikipedia.org/wiki/Entropy_(information_theory)
86///
87/// # Underlying sources
88///
89/// Platform               | Source
90/// -----------------------|---------------------------------------------------------------
91/// Linux                  | [`getrandom`] or [`/dev/urandom`] after polling `/dev/random`
92/// Windows                | [`ProcessPrng`](https://learn.microsoft.com/en-us/windows/win32/seccng/processprng)
93/// Apple                  | `CCRandomGenerateBytes`
94/// DragonFly              | [`arc4random_buf`](https://man.dragonflybsd.org/?command=arc4random)
95/// ESP-IDF                | [`esp_fill_random`](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/random.html#_CPPv415esp_fill_randomPv6size_t)
96/// FreeBSD                | [`arc4random_buf`](https://man.freebsd.org/cgi/man.cgi?query=arc4random)
97/// Fuchsia                | [`cprng_draw`](https://fuchsia.dev/reference/syscalls/cprng_draw)
98/// Haiku                  | `arc4random_buf`
99/// Illumos                | [`arc4random_buf`](https://www.illumos.org/man/3C/arc4random)
100/// NetBSD                 | [`arc4random_buf`](https://man.netbsd.org/arc4random.3)
101/// OpenBSD                | [`arc4random_buf`](https://man.openbsd.org/arc4random.3)
102/// Solaris                | [`arc4random_buf`](https://docs.oracle.com/cd/E88353_01/html/E37843/arc4random-3c.html)
103/// Vita                   | `arc4random_buf`
104/// Hermit                 | `read_entropy`
105/// Horizon, Cygwin        | `getrandom`
106/// AIX, Hurd, QNX         | `/dev/urandom`
107/// Redox                  | `/scheme/rand`
108/// RTEMS                  | [`arc4random_buf`](https://docs.rtems.org/branches/main/bsp-howto/getentropy.html)
109/// SGX                    | [`rdrand`](https://en.wikipedia.org/wiki/RDRAND)
110/// SOLID                  | `SOLID_RNG_SampleRandomBytes`
111/// TEEOS                  | `TEE_GenerateRandom`
112/// UEFI                   | [`EFI_RNG_PROTOCOL`](https://uefi.org/specs/UEFI/2.10/37_Secure_Technologies.html#random-number-generator-protocol)
113/// VxWorks                | `randABytes` after waiting for `randSecure` to become ready
114/// WASIp1                 | [`random_get`](https://github.com/WebAssembly/WASI/blob/wasi-0.1/preview1/docs.md#-random_getbuf-pointeru8-buf_len-size---result-errno)
115/// WASIp2                 | [`get-random-bytes`]
116/// WASIp3                 | [`get-random-bytes`]
117/// ZKVM                   | `sys_rand`
118///
119/// Note that the sources used might change over time.
120///
121/// Consult the documentation for the underlying operations on your supported
122/// targets to determine whether they provide any particular desired properties,
123/// such as support for reseeding on VM fork operations.
124///
125/// [`getrandom`]: https://www.man7.org/linux/man-pages/man2/getrandom.2.html
126/// [`/dev/urandom`]: https://www.man7.org/linux/man-pages/man4/random.4.html
127/// [`get-random-bytes`]: https://github.com/WebAssembly/WASI/blob/main/proposals/random/imports.md#get-random-bytes-func
128///
129/// # Examples
130///
131/// Filling a buffer with random bytes
132/// ```
133/// #![feature(random)]
134///
135/// use std::random::{Rng, SystemRng};
136///
137/// let mut buf = [0; 16];
138/// SystemRng.fill_bytes(&mut buf);
139/// dbg!(buf);
140/// ```
141#[doc(alias = "getrandom", alias = "getentropy", alias = "arc4random")]
142#[derive(Default, Debug, Clone, Copy)]
143#[unstable(feature = "random", issue = "130703")]
144pub struct SystemRng;
145
146#[unstable(feature = "random", issue = "130703")]
147impl Rng for SystemRng {
148    fn fill_bytes(&mut self, bytes: &mut [u8]) {
149        sys::fill_bytes(bytes)
150    }
151}
152
153/// Generates a random value from a distribution, using the default random source.
154///
155/// This is a convenience function for `dist.sample(&mut SystemRng)` and will sample according to
156/// the same distribution as the underlying [`Distribution`] trait implementation. See [`SystemRng`]
157/// for more information about how randomness is sourced.
158///
159/// # Examples
160///
161/// Generating a [version 4/variant 1 UUID] represented as text:
162/// ```
163/// #![feature(random)]
164///
165/// use std::random::random;
166///
167/// let bits: u128 = random(..);
168/// let g1 = (bits >> 96) as u32;
169/// let g2 = (bits >> 80) as u16;
170/// let g3 = (0x4000 | (bits >> 64) & 0x0fff) as u16;
171/// let g4 = (0x8000 | (bits >> 48) & 0x3fff) as u16;
172/// let g5 = (bits & 0xffffffffffff) as u64;
173/// let uuid = format!("{g1:08x}-{g2:04x}-{g3:04x}-{g4:04x}-{g5:012x}");
174/// println!("{uuid}");
175/// ```
176///
177/// [version 4/variant 1 UUID]: https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random)
178#[unstable(feature = "random", issue = "130703")]
179pub fn random<T>(dist: impl Distribution<T>) -> T {
180    dist.sample(&mut SystemRng)
181}