We looked into a modern Bitcoin address format, released more weak addresses, investigated a new PRNG range, and found what looks like results of a weak vanity address generator.


Milk Sad Talk at 38C3

Our Milk Sad presentation at the 38C3 conference was a success, and we also had an interesting discussion session in the workshop room afterwards! Thanks to the great VOC video team at CCC, the talk recording is available online on their video archive as well as Youtube. Head over to our dedicated talk page if you’re interested in watching it or reading our notes.

Updated Research Data

In update #11, we outlined our publication of known weak cryptocurrency wallet addresses for Bitcoin and Ethereum in the data repository. We’ve now significantly extended this collection, primarily for the Bitcoin addresses, by including addresses of used sub-accounts and change accounts. We’ve also done newer scans over some of the ranges and added more documentation, showing a more recent view and highlighting potential changes between the different scans.

Current statistics:

  • Number of unique weak Bitcoin wallet addresses: 40219
    • Prefix 1: 4315
    • Prefix 3: 20516
    • Prefix bc1q: 15387
    • Prefix bc1p: 1
  • Number of unique weak Ethereum wallet addresses: 8932

Taproot

Bitcoin has several different formats for addresses and transactions. During our research so far, we focused on the older and more popular address calculations (P2PKH, P2WPKH, P2SH-P2WPKH), and there were already some surprises such as the use of uncompressed public keys (see update #2) or mismatched derivation paths / derivation standards / address types.

A fairly recent and major new standard for Bitcoin is called Taproot, see Wikipedia. It was introduced on-chain in November 2021, but is still optional and not supported by all actively developed cryptocurrency wallet implementations. For example, the Electrum software wallet doesn’t fully support it yet. For us, the late introduction compared to the timeframe of many of the weak wallet issues meant that Taproot wasn’t available at all for most victims, and we suspected that it would only make up a small portion of vulnerable funds even now due to the limited software support.

So far, our partial analysis of known weak wallet ranges confirms our assumptions. When searching for the “plain” P2TR Taproot usage for normal wallets without more advanced configurations (scripts, multiple signatures, …), we only found usage with a known test key. This may change in the future if a Taproot-enabled wallet software uses bad PRNGs. It may already be relevant for other PRNG ranges or usage scenarios that we didn’t look into. Still, for our prior work, Taproot doesn’t seem to reveal more weak wallets - which is an interesting result.

New PRNG Type

Many PRNG implementations are very similar to each other in terms of their mathematical construction, but their designers pick different parameters with the goal of obtaining better properties. Our Trust Wallet research in update #5 revolved around the so-called minstd_rand0 PRNG, which is a linear congruential generator or LGC for short. That particular minstd_rand0 configuration used in the Apple standard library environment by the affected iOS wallet app with m = 2^31 - 1 and a = 16807 seems to be one of the oldest common LGC configurations.

We were curious if a different variant of this LGC PRNG called minstd_rand (notice the missing 0 in the name) with m = 2^31 - 1 and a = 48271 had also generated some weak wallets. That variant is available in some C++ environments, as far as we understand.

As it turns out, yes, there are weak wallets! Looking through the direct usage of some PRNG output pattern into secp256k1 private keys, we found a handful of used P2PKH addresses, as you can see in the data repository.

Bad Vanity Address Generator

Additionally, we also searched through some other direct PRNG-to-private-key usages for 256 bit outputs and found a few, which are now in the data repository as well. Curiously, someone seems to have used the minstd_rand0 PRNG as a vanity address generator, generating and using addresses with the 1Love[...] and 1Shao[...] prefixes:

1Loveu9He9wDnLUBzio9XM47EbwKqoCyEX
1LovEUjnQQF1yiYNGr2MJtpNu1UHwSCL1h
1LovezS8pFiKWKfPZTJPmj7ZR7AUfvufGq
1Shao1YrYoLdrgjjLgLTycQwVYyNRxKWL
1ShaoJtnZc9ZyK4yXQqVDHnHRUntrpG72

Given that there are only 2^31 potential PRNG starting configurations, this was a very poor choice not just for security reasons, but also for functional reasons, since the PRNG is very limited in the random address prefixes it can find. Based on the few used addresses, we expect that this was either an experiment or a custom tool setup, since it would have more users (victims) otherwise.