Randstorm: the BitcoinJS wallets of 2011–2015

A combination of a weak JavaScript RNG and a popular wallet library left millions of early web wallets — worth over a billion dollars — with dangerously guessable keys.

Disclosed: Nov 2023, by Unciphered Estimated exposure: ~1.4M BTC Effective entropy: as low as ~48 bits

How the entropy collapsed

Millions of wallets from 2011–2015 (including many created on blockchain.info) were built with the BitcoinJS library. It relied on JSBN's SecureRandom(), which in the browsers of that era fell back to Math.random(). Chrome/V8 then implemented Math.random() as MWC1616, seeded with only 32 bits, and the way the entropy pool was filled and RC4-scrambled reduced real randomness further — to as little as 48 bits. That is well within reach of a determined attacker.

Unciphered demonstrated recovering live keys. Wallets generated before March 2012 are the easiest to attack; later ones added more entropy but remained weaker than intended. This mode replays the MWC1616 → pool → RC4 pipeline across all 232 seeds.

The defense

If you hold funds in a wallet created between 2011 and 2015 through a browser-based service, treat the keys as potentially exposed and migrate the funds to a freshly-generated wallet from modern, audited software.

Unciphered's Randstorm disclosure →

▶ Try the Randstorm mode in the game

← Back to all attack vectors