From 223de8d94d6522f795ec3c2e7db27469f24aa68c Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Sun, 13 Jan 2019 10:51:17 -0800 Subject: Document RNG design in random.h --- src/random.h | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) (limited to 'src/random.h') diff --git a/src/random.h b/src/random.h index 038e3ecd78..4c73f3822a 100644 --- a/src/random.h +++ b/src/random.h @@ -13,6 +13,49 @@ #include #include +/** + * Overall design of the RNG and entropy sources. + * + * We maintain a single global 256-bit RNG state for all high-quality randomness. + * The following (classes of) functions interact with that state by mixing in new + * entropy, and optionally extracting random output from it: + * + * - The GetRand*() class of functions, as well as construction of FastRandomContext objects, + * perform 'fast' seeding, consisting of mixing in: + * - A stack pointer (indirectly committing to calling thread and call stack) + * - A high-precision timestamp (rdtsc when available, c++ high_resolution_clock otherwise) + * - Hardware RNG (rdrand) when available. + * These entropy sources are very fast, and only designed to protect against situations + * where a VM state restore/copy results in multiple systems with the same randomness. + * FastRandomContext on the other hand does not protect against this once created, but + * is even faster (and acceptable to use inside tight loops). + * + * - The GetStrongRand*() class of function perform 'slow' seeding, including everything + * that fast seeding includes, but additionally: + * - OS entropy (/dev/urandom, getrandom(), ...). The application will terminate if + * this entropy source fails. + * - Bytes from OpenSSL's RNG (which itself may be seeded from various sources) + * - Another high-precision timestamp (indirectly committing to a benchmark of all the + * previous sources). + * These entropy sources are slower, but designed to make sure the RNG state contains + * fresh data that is unpredictable to attackers. + * + * - RandAddSeedSleep() seeds everything that fast seeding includes, but additionally: + * - A high-precision timestamp before and after sleeping 1ms. + * - (On Windows) Once every 10 minutes, performance monitoring data from the OS. + * These just exploit the fact the system is idle to improve the quality of the RNG + * slightly. + * + * On first use of the RNG (regardless of what function is called first), all entropy + * sources used in the 'slow' seeder are included, but also: + * - (On Windows) Performance monitoring data from the OS. + * - (On Windows) Through OpenSSL, the screen contents. + * + * When mixing in new entropy, H = SHA512(entropy || old_rng_state) is computed, and + * (up to) the first 32 bytes of H are produced as output, while the last 32 bytes + * become the new RNG state. +*/ + /** * Generate random data via the internal PRNG. * -- cgit v1.2.3