---
layout: post
title: "Update #12 - Taproot, Address Data, New PRNG Range, 38C3 Talk"
author: ["Christian Reitter"]
date: 2025-02-05 13:00:00 +0000
---

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.

<div id="toc-container" markdown="1">
<h2 class="no_toc">Table of Contents</h2>
* placeholder
{:toc}
</div>

<br/>


## Milk Sad Talk at 38C3

Our [Milk Sad presentation at the 38C3 conference]({% link 38c3.md %}) 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]({% link 38c3.md %}) if you're interested in watching it or reading our notes.

## Updated Research Data

In [update #11]({% link _posts/2024-12-19-research-update-11.md %}#new-research-data), we outlined our publication of known weak cryptocurrency wallet addresses for Bitcoin and Ethereum in the [data](https://git.distrust.co/milksad/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]({% link _posts/2023-12-06-research-update-2.md %}#uncompressed-public-keys-on-p2pkh)) or mismatched derivation paths / derivation standards / address types.

A fairly recent and major new standard for Bitcoin is called `Taproot`, see [Wikipedia](https://en.wikipedia.org/wiki/List_of_bitcoin_forks#Taproot). 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](https://github.com/spesmilo/electrum/issues/7544) 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]({% link _posts/2024-01-23-research-update-5.md %}) revolved around the so-called `minstd_rand0` PRNG, which is a [linear congruential generator](https://en.wikipedia.org/wiki/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](https://en.wikipedia.org/wiki/Lehmer_random_number_generator#Parameters_in_common_use) common LGC configurations.

We were curious if [a different variant](https://cplusplus.com/reference/random/minstd_rand/) 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](https://git.distrust.co/milksad/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](https://en.bitcoin.it/wiki/Vanitygen), 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.