How does the Bitcoin Core wallet generate entropy for the HD (Hierarchical Deterministic) seed and ultimately the private keys?
This post asks a related question but doesn't focus on the entropy part, more the BIP 32/39 part.
The Bitcoin Core wallet requires entropy both for generating HD seeds and for generating nonces (number used once) used in digital signatures (handled by the secp256k1 library).
raw_avocado discussed how the Bitcoin Core wallet generates entropy for a HD seed on Twitter. In summary, by mixing entropy from 4 main sources: low level processor instructions, entropy from the OS, dynamic events and static events.
(i) Processor instructions
RDSEED - access to the built-in True Random Number Generator on the processor.
RDRAND - access to the built-in Pseudo-Random Number generator that gets seeded every time it's called with RDSEED
RDTSC - returns the # of CPU cycles since reset
(ii) OS sources
Most of the Linux distributions have specific functions that call /dev/urandom, like getrandom, Where this is not the case it's called directly.
getentropy used on Open BSD & Mac sysctl kern.random on Free & Net BSD
CryptGenRandom on Windows.
(iii) Dynamic Events
Various clocks are called real-time, monotonic, and boot time.
Resource usage is constantly changing and is a great source of entropy.
On Windows, getrusage is called, and on Linux pseudofiles from /proc are used or sysctl where available.
(iv) Static Events
Anything from static details about compiler version to bitcoin client version to CPUID, hostname, network interfaces, kernel info, filesystem data.
Even though the Events Static & Dynamic are non-cryptographic data, they still increase the entropy.
The Dynamic and Static events are mixed in(mostly) by using
<<Left Shift Bits. Because it's a binary operation, every digit is a power of 2, so shifting the bit n positions ends up multiplying by
2^n. This adds further confusion when multiple numbers are used at once. The most common method used to mix in the entropy is the SHA512(its compression function more precisely). SHA512 works effectively as a pseudoRNG, as it shows uniformity, meaning each output has the same probability of occurring. In some cases, SHA256 is used.
Good hash functions have a strong avalanche effect, meaning that when even a single input bit is incremented, each output bit changes with a probability of 50%. The bit diffusion is a result of adding, rotating, and XORing chunks of the input.
In this mixing situation, the results of the processor pseudoRNG RDRAND are XORed 1024 times. (this is used as a fallback from RDSEED - the TRNG). Every call should reseed the PRNG differently and XORing is a great way to obfuscate things.
Another technique for strengthening the entropy is hashing inputs in a loop for an amount of TIME, not just a number of times. The mixing techniques are benchmarked and the benchmarks are also mixed in as sources of entropy. With each entropy source and each mix the chances of an adversary recreating the entropy decrease exponentially. Even if a few of the sources are somehow compromised, it will still result in a safe key in the end.