Weak-Entropy Key Generation

A cryptographic system that generates keys from insufficient entropy is broken at birth, and no downstream control can repair it. Weak-entropy key generation is the failure mode in which a wallet, token, or key-management system draws its root secret from a predictable or low-entropy source — a non-cryptographic PRNG, a timestamp seed, a silent software fallback — producing keys that an attacker can recompute offline. The class is defined by three properties that make it unusually vicious: the output is indistinguishable from strong keys (a 12-word mnemonic looks the same either way), the compromise is retroactive (every past and future use of the key is exposed), and the hunt requires no interaction with the victim (a public blockchain or ciphertext is oracle enough).

The mechanism

A modern wallet or key generator should produce a root secret with at least 128 bits of entropy, typically from a hardware true random number generator (TRNG), optionally stretched by a cryptographically secure PRNG (CSPRNG). The failures that define this class all break one link in that chain:

  1. Wrong algorithm. A non-cryptographic PRNG (Mersenne Twister, Yasmarang, Math.random) is used where a CSPRNG is required. These generators are fast and statistically well-behaved — which is why they pass casual testing — but their internal state is small and their outputs are reversible or enumerable.
  2. Wrong seed. Even a decent generator is fatal when seeded from a predictable value: the system clock (32 bits of wall time), a device serial number, or hardcoded public constants. The generator then “stretches” a handful of unknown bits into 256 output bits without adding information — the output space is the seed space.
  3. Wrong binding. A correct generator exists in the system but the security-critical call path silently binds to a fallback. This is the build-time/link-time variant: the guard that should have failed the build tests the wrong condition, and the linker resolves the entropy symbol to the weak implementation.

In all three, the output passes every output-side test. Entropy failures are invisible at the output; as Wizardsardine’s COLDCARD autopsy puts it, “what discriminates is the path, not the output.”1

Why the class is chain-agnostic

The bug is not a Bitcoin bug, an Ethereum bug, or a hardware-wallet bug — it is a key-generation bug. Any system whose security reduces to “the attacker cannot guess the root secret” is exposed: BIP-39 seeds (every chain that imports them), ECDSA nonces, session keys, encrypted-file passwords, vanity addresses, API tokens. Ethereum’s vanity-address niche paid its entropy tax in 2022 (Profanity/Wintermute, ~$160M); Trust Wallet’s browser extension exposed AVAX, BNB, ETH, MATIC, and SOL keys from one weak seed in 2022–23; Milk Sad drained BTC, ETH, XRP, DOGE, SOL, LTC, BCH, and ZEC from the same broken bx seed output in 2023.2 A weak BIP-39 seed stays weak when imported into any other wallet on any other chain — derivation cannot add entropy.

What varies is not vulnerability but hunting economics. Bitcoin was the most profitable hunting ground for both Milk Sad and the 2026 COLDCARD sweep because its public UTXO set makes funded-address enumeration trivially cheap and its self-custody culture concentrates long-dormant, high-value, single-key wallets. The attacker enumerates candidate seeds offline, derives addresses, and matches them against the public chain — no device contact, no phishing, no malware.3

The incident record

IncidentYearMechanismRoot spaceConfirmed loss
Android Java SecureRandom2013Broken Java RNG → colliding ECDSA nonces~55.8 BTC; mass key rotation
Profanity / Wintermute2022Vanity generator, 32-bit seed2^32~$3.3M + ~$160M
Trust Wallet extension (CVE-2023-31290)2022–23MT19937, single 32-bit seed2^32~$170K (users reimbursed)
Milk Sad / Libbitcoin bx (CVE-2023-39910)2023MT19937 seeded with 32 bits of system time2^32>$900K; >2,600 weak wallets confirmed
Randstorm (BitcoinJS/JSBN)disclosed 2023Silent fallback to Math.randomvaries~1.4M BTC potentially at risk (estimate)
“Ill Bloom” (CVE-2026-71851)2026CryptoJS weak RNG reaching BIP39 generation≥$5.69M; 431 accounts in hours
COLDCARD2026Link-time binding to Yasmarang fallback2^22 (Mk3, modelled)1,778+ BTC (~$112M+)

The Milk Sad write-up is the canonical worked example: bx seed -b 256 requested 256 bits of entropy and received 32 bits of high-precision clock time expanded by Mersenne Twister — brute-forceable in “a few days on the average gaming PC,” demonstrated by reproducing the exact milk sad wage cup reward… mnemonic under a frozen clock.4 The researchers’ disclosure dilemma is also canonical: with active exploitation underway they published in days, not months, reasoning that “time is on the side of the attackers rather than the victims.”

Design principles that fail and survive

Fails: output-side checks. COLDCARD’s generate_seed() asserted only that the 32 output bytes contained more than 4 distinct values — a test any functioning PRNG passes with probability ~1. Statistical test suites (Dieharder) run on a simulator where bytes come from the host PC certify nothing about the device path.5

Fails: single-source entropy with silent fallback. A fallback that exists will eventually be selected. Cake Wallet’s Dart Random() fell back to system time; BitcoinJS fell back to Math.random; COLDCARD fell back to Yasmarang. In each case the weak path was present in the binary and one configuration slip away from the critical path.

Survives: dissimilar redundancy by default. Mix at least two independent physical entropy sources such that the failure of either leaves the full security level. Trezor’s design — host OS entropy + STM32 TRNG + (on newer models) secure-element and TROPIC01 sources, combined — is the existing template: “a single point of failure cannot compromise your wallet’s entropy.”6 Note the COLDCARD reseed pretended to do this while passing only 4 bytes into one 32-bit state word — the form of redundancy without the substance.7

Survives: user-supplied entropy. COLDCARD users who generated seeds with ≥50 independent dice rolls contributed ≥128 bits the software could not remove, and were safe even on vulnerable firmware. Diceware’s ~12.9 bits per word works the same way: the dice provide the randomness, not the device.8 And diverse-vendor multisig lost zero satoshis in the COLDCARD sweep — the architectural answer to a single point of failure is to not have one.9

The engineering corollary: test provenance, not output. Build-time symbol checks that fail unless the board’s hardware RNG is the resolved implementation, runtime attestation that the TRNG was actually read during key generation, and end-to-end call-path verification across submodule boundaries — the bug class lives exactly where two projects each assume the other has the entropy.10

Sources

Footnotes

  1. 2026 — Generate 32 bytes of best-quality high entropy TRNG bytes.

  2. 2023 — generate 256 bits of entropy, turn it into BIP39 mnemonics

  3. 2026 — Block Predictable Rng Fallback Coldcard

  4. 2023 — generate 256 bits of entropy, turn it into BIP39 mnemonics

  5. 2026 — Generate 32 bytes of best-quality high entropy TRNG bytes.

  6. Trezor Entropy Multisource Guide

  7. 2026 — Block Predictable Rng Fallback Coldcard

  8. Trezor Entropy Multisource Guide

  9. 2026 — Galaxy Coldcard Your Keys Not Your Coins

  10. 2026 — Generate 32 bytes of best-quality high entropy TRNG bytes.