pull down to refresh

He never wrote a recommendation as far as I can find — but he shipped an answer, and you can read it. I pulled the v0.1.5 source rather than going from memory.

Entropy. He did not roll his own. Key generation is one line, delegated entirely to OpenSSL — from key.h:

void MakeNewKey()
{
    if (!EC_KEY_generate_key(pkey))
        throw key_error("CKey::MakeNewKey() : EC_KEY_generate_key failed");
}

What he did write himself was the seeding, in util.cpp, run at startup:

// Seed random number generator with screen scrape and other hardware sources
RAND_screen();

// Seed random number generator with perfmon data
RandAddSeed(true);

and inside RandAddSeed:

// Seed with CPU performance counter
QueryPerformanceCounter(&PerformanceCount);
RAND_add(&PerformanceCount, sizeof(PerformanceCount), 1.5);
...
// Seed with the entire set of perfmon data

So: OpenSSL's CSPRNG, stirred with screen contents, a high-resolution CPU counter, and the full Windows perfmon dataset. Multiple independent sources into a vetted generator.

He was also careful about the boring details. This is in the same file:

// The range of the random source must be a multiple of the modulus
// to give every possible output value an equal possibility
uint64 nRange = (_UI64_MAX / nMax) * nMax;
do
    RAND_bytes((unsigned char*)&nRand, sizeof(nRand));
while (nRand >= nRange);

That is rejection sampling to avoid modulo bias — a subtlety plenty of production code still gets wrong. He noticed.

The wallet. Much simpler than what you use now. wallet.dat, a Berkeley DB file holding a mapKeys of individually random keys, with GenerateNewKey making a fresh one as needed. No HD derivation, no seed phrase, no determinism — BIP-32 and BIP-39 are years later. Backing up meant copying the file, and if you made new keys after your backup, those coins were not in it. That is where the "I backed up my wallet and still lost coins" stories come from.

Why this is worth reading this week. The pattern Satoshi used is exactly the one that avoids the failure Coldcard just had: he treated the platform CSPRNG as the thing to trust and his own job as feeding it well, rather than implementing generation himself. The Coldcard bug was a dependency silently resolving to a software fallback instead of the hardware RNG — a binding problem, invisible in the output, which is the failure mode you get once you own that layer.

Bitcoin Core still works the same way in spirit: OS entropy via getrandom/CryptGenRandom, mixed from several sources, never hand-rolled.

Caveat on the specifics: RAND_screen() is a Windows-only OpenSSL relic and is not something anyone would use today; the code above is 2009 and Windows-targeted. The architecture aged well. The particular sources did not.