Skip to content

Commit 223de8d

Browse files
committed
Document RNG design in random.h
1 parent f2e60ca commit 223de8d

File tree

2 files changed

+51
-0
lines changed

2 files changed

+51
-0
lines changed

src/random.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,14 @@ namespace {
282282

283283
class RNGState {
284284
Mutex m_mutex;
285+
/* The RNG state consists of 256 bits of entropy, taken from the output of
286+
* one operation's SHA512 output, and fed as input to the next one.
287+
* Carrying 256 bits of entropy should be sufficient to guarantee
288+
* unpredictability as long as any entropy source was ever unpredictable
289+
* to an attacker. To protect against situations where an attacker might
290+
* observe the RNG's state, fresh entropy is always mixed when
291+
* GetStrongRandBytes is called.
292+
*/
285293
unsigned char m_state[32] GUARDED_BY(m_mutex) = {0};
286294
uint64_t m_counter GUARDED_BY(m_mutex) = 0;
287295
bool m_strongly_seeded GUARDED_BY(m_mutex) = false;

src/random.h

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,49 @@
1313
#include <stdint.h>
1414
#include <limits>
1515

16+
/**
17+
* Overall design of the RNG and entropy sources.
18+
*
19+
* We maintain a single global 256-bit RNG state for all high-quality randomness.
20+
* The following (classes of) functions interact with that state by mixing in new
21+
* entropy, and optionally extracting random output from it:
22+
*
23+
* - The GetRand*() class of functions, as well as construction of FastRandomContext objects,
24+
* perform 'fast' seeding, consisting of mixing in:
25+
* - A stack pointer (indirectly committing to calling thread and call stack)
26+
* - A high-precision timestamp (rdtsc when available, c++ high_resolution_clock otherwise)
27+
* - Hardware RNG (rdrand) when available.
28+
* These entropy sources are very fast, and only designed to protect against situations
29+
* where a VM state restore/copy results in multiple systems with the same randomness.
30+
* FastRandomContext on the other hand does not protect against this once created, but
31+
* is even faster (and acceptable to use inside tight loops).
32+
*
33+
* - The GetStrongRand*() class of function perform 'slow' seeding, including everything
34+
* that fast seeding includes, but additionally:
35+
* - OS entropy (/dev/urandom, getrandom(), ...). The application will terminate if
36+
* this entropy source fails.
37+
* - Bytes from OpenSSL's RNG (which itself may be seeded from various sources)
38+
* - Another high-precision timestamp (indirectly committing to a benchmark of all the
39+
* previous sources).
40+
* These entropy sources are slower, but designed to make sure the RNG state contains
41+
* fresh data that is unpredictable to attackers.
42+
*
43+
* - RandAddSeedSleep() seeds everything that fast seeding includes, but additionally:
44+
* - A high-precision timestamp before and after sleeping 1ms.
45+
* - (On Windows) Once every 10 minutes, performance monitoring data from the OS.
46+
* These just exploit the fact the system is idle to improve the quality of the RNG
47+
* slightly.
48+
*
49+
* On first use of the RNG (regardless of what function is called first), all entropy
50+
* sources used in the 'slow' seeder are included, but also:
51+
* - (On Windows) Performance monitoring data from the OS.
52+
* - (On Windows) Through OpenSSL, the screen contents.
53+
*
54+
* When mixing in new entropy, H = SHA512(entropy || old_rng_state) is computed, and
55+
* (up to) the first 32 bytes of H are produced as output, while the last 32 bytes
56+
* become the new RNG state.
57+
*/
58+
1659
/**
1760
* Generate random data via the internal PRNG.
1861
*

0 commit comments

Comments
 (0)