
Subject: Insufficient entropy when generating mnemonic phrases in the Trust Wallet browser extension.
Incident period: November 2022 – April 2023.
Researchers: Trust Wallet Security Team and Ledger Donjon.
Classification: Cryptographic weakness in the pseudo-random number generator, CWE-338 / weak PRNG.
ID: CVE-2023-31290. WebAssembly WASM BIP-39 HD Wallet Mersenne Twister Cryptanalysis CVE-2023-31290.
Annotation
This article examines critical cryptographic vulnerability CVE-2023-31290, which affects the Trust Wallet browser extension. The issue stems from an insufficiently secure pseudorandom number generator initialization mechanism in the Trust Wallet Core WebAssembly module. Instead of a cryptographically secure source of randomness, the BIP-39 mnemonic generator received an initial state space of approximately 32 bits, making it possible to enumerate all potentially created wallets.
The vulnerability demonstrates a fundamental cryptanalytic fact: the strength of private keys is determined not by the mathematical complexity of the elliptic curve secp256k1 per se, but by the actual entropy of the secret material from which the keys are derived. Even with robust BIP-39, BIP-32, and ECDSA standards, an error in randomness generation can reduce the search space from a practically unachievable level to a computationally feasible one.
Introduction
Bitcoin and other cryptocurrency wallets use cryptographic secrets that determine the exclusive right to control digital assets. In a typical HD wallet architecture, the initial secret is a BIP-39 mnemonic phrase, which represents an encoded form of random entropy. The mnemonic phrase then derives a seed, a BIP-32 master key, and a hierarchy of child private keys.
In April 2023, Trust Wallet and Ledger Donjon disclosed an incident involving the Trust Wallet browser extension. The vulnerability allowed mnemonic phrases generated by vulnerable versions of the extension to be reproduced by exhaustively trying a limited set of pseudorandom number generator states. The issue was not an attack on ECDSA, SHA-256, PBKDF2, or BIP-39; it was the result of a flawed implementation of the entropy source.
The main lesson of the incident is that a cryptographic protocol can be formally correct but insecure in a real system if its secret parameters are generated predictably.
The Context of BIP-39 and HD Wallets
Mnemonics as a representation of entropy
The BIP-39 standard transforms binary entropy into a sequence of words from a fixed dictionary. For a 12-word mnemonic, the initial entropy is typically 128 bits, with an additional 4 bits serving as a checksum. For 24 words, 256-bit entropy with an 8-bit checksum is used.
ENT = 128 bits CS = ENT / 32 = 4 bits Mnemonic size = ENT + CS = 132 bits Number of words = 132 / 11 = 12
When implemented correctly, the number of possible 12-word mnemonics is determined by the space of the original entropy:
N ideal = 2 128 ≈ 3.40 × 10 38
Enumerating such a set is impossible not only with modern tools but also under realistic projections of computing technology development. It is this space of possibilities that forms the cryptographic basis for the security of the BIP-39 mnemonic.
Transition from mnemonics to keys
The mnemonic, along with the optional passphrase, is converted into a seed using PBKDF2-HMAC-SHA512. The HD wallet then receives a master private key and chain code, from which child keys are deterministically derived using derivation paths, such as m/44'/0'/0'/0/0 for a classic BIP-44 Bitcoin address.
seed = PBKDF2-HMAC-SHA512( password = mnemonic, salt = “mnemonic” || passphrase, iterations = 2048, dkLen = 64 bytes )
All subsequent addresses, public keys, and private keys depend on the initial mnemonic. Therefore, compromising a weak source of entropy is equivalent to compromising the entire wallet key hierarchy.
Technical reason for CVE-2023-31290
Vulnerable WASM circuit
The Trust Wallet browser extension used a WebAssembly build of the Trust Wallet Core library. In native mobile environments, access to cryptographically strong randomness is typically provided through operating system mechanisms: SecRandomCopyBytes on Apple platforms, SecureRandom on Android, or through the system CSPRNG interfaces on Linux and Windows.
However, the WASM target had a different configuration. The corresponding execution path used a generator std::mt19937known as the Mersenne Twister. This generator is suitable for modeling, statistical problems, and simulations, but is not intended for generating cryptographic keys.
Critical initialization error
In the vulnerable Mersenne Twister scenario, the initialization value was obtained via std::random_device. In the WebAssembly environment, this did not translate into 128 or 256 independent bits of cryptographic entropy. In fact, the available initial state space was limited to a 32-bit value.
// Упрощённая иллюстрация небезопасного паттерна.
// Не использовать для генерации ключей, мнемоник или токенов.
std::mt19937 rng(std::random_device{}());
for (size_t i = 0; i < entropy_size; ++i) {
entropy[i] = static_cast<uint8_t>(rng() & 0xFF);
}
The problem wasn’t that the Mersenne Twister generates statistically “dissimilar” numbers. The problem was the lack of cryptographic unpredictability: given a known or iterable seed, the entire stream of PRNG output values is completely reproducible.
A key cryptographic flaw. Using the MT19937’s large internal state does not make the scheme secure if the generator is started from a small, iterable initial seed. In this case, the seed’s entropy, not the size of the generator’s internal state, became the determining factor.
Cryptanalytic model
Search space compression
Formally, the entropy of a set of equally probable possible states is calculated as:
H = log 2 (N)
If mnemonic generation starts with a 32-bit seed, the number of possible sequences, regardless of the length of the resulting mnemonic, is limited:
N vulnerable = 2 32 = 4 294 967 296 H vulnerable = log 2 (2 32 ) = 32 bits
Therefore, the actual entropy loss for a 12-word BIP-39 mnemonic is:
ΔH = H ideal – H vulnerable ΔH = 128 – 32 = 96 bits
The reduction from 128 to 32 bits represents not a “minor weakening,” but a fundamental loss of cryptographic strength. The key space is reduced by:
2 128 / 2 32 = 2 96
times, that is, approximately \(7.92 × 10^{28}\) times.
Practical attack scheme
The attacker didn’t need to crack Bitcoin’s cryptography or solve the discrete logarithm problem on secp256k1. It was enough to deterministically reproduce the generation chain for each potential 32-bit seed:
- Loop through all values
seedfrom 0 to \(2^{32}-1\). - Initialize the PRNG in the same way as the WASM build did.
- Generate bytes of entropy, obtaining the BIP-39 mnemonic.
- Get BIP-39 seed via PBKDF2-HMAC-SHA512.
- Derive private and public keys using common derivation paths.
- Generate addresses and match them with addresses that have activity or balance on the blockchain.
# Псевдокод исследовательской модели.
# Не предназначен для атак или доступа к чужим активам.
for candidate_seed in range(0, 2**32):
prng = initialize_mt19937(candidate_seed)
entropy = prng_bytes(prng, 16) # 128 бит
mnemonic = bip39_encode(entropy)
master_seed = bip39_pbkdf2(mnemonic)
address = derive_bip44_address(master_seed, path="m/44'/0'/0'/0/0")
if address_in_observed_blockchain_set(address):
report_affected_wallet(address)
In cryptanalytic terms, this is a brute-force attack on a low-entropy seed secret. The public nature of the blockchain significantly aids the attacker: addresses, transactions, and balances are indexable, so a candidate can be verified without requiring the wallet owner’s consent.
Why ECDSA Hasn’t Been Broken
Bitcoin uses the elliptic curve secp256k1. The public key \(Q\) is related to the private key \(d\) by a scalar multiplication operation:
Q = dG
where \(G\) is the curve’s base point and \(d\) is the secret scalar. Given a correctly generated \(d\), recovering the private key from \(Q\) requires solving the discrete logarithm problem on an elliptic curve, which is considered computationally infeasible.
In CVE-2023-31290, the attacker did not calculate \(d\) from the public key. Instead, they could reproduce the original mnemonic, from which the owner deterministically derived \(d\). Thus, the attack bypassed the mathematical security of ECDSA by targeting an earlier stage of the key lifecycle—entropy generation.
Strong cryptography + weak entropy = weak system
Chronology of the incident
| Date / period | Event | Cryptanalytic meaning |
|---|---|---|
| November 14, 2022 | A vulnerable version of the Trust Wallet browser extension, version 0.0.172, has been released. | The period of creation of potentially vulnerable new wallets begins. |
| November 2022 | A randomness generation issue has been discovered in the Trust Wallet Core WASM module. | A connection has been established between BIP-39 entropy generation and weak PRNG seed. |
| November 17, 2022 | Ledger researcher Donjon reported the issue to the Trust Wallet team. | An example of a coordinated disclosure of a cryptographic vulnerability. |
| November 2022 | Trust Wallet has prepared a fix and an extension update. | The vulnerable generation path has been replaced with a safe source of randomness. |
| November 23, 2022 | The vulnerable period for creating new wallets has ended after the update. | The impact period was limited to specific versions of the extension. |
| April 2023 | A public disclosure has taken place, a postmortem and CVE-2023-31290 have been published. | Users were asked to transfer their assets to new, securely created wallets. |
Scale and consequences
According to Trust Wallet’s public documentation, the vulnerability affected new wallets created during a limited period using specific versions of the browser extension. Trust Wallet mobile apps were not affected by this bug, as they used different platform-specific randomness mechanisms.
The analysis revealed actual unauthorized charges. Trust Wallet reported that two known exploits resulted in losses of approximately $170,000. The company also announced a compensation program for affected users and a reward for the researcher who made responsible disclosures.
Practical risk. If an attacker had pre-built a database of addresses for all 2^{32} potential seeds, any active address in the vulnerable population could be discovered with a simple search. The appearance of a new incoming transfer to a previously empty address did not eliminate the risk: the address might already be in the pre-computed set.
Historical parallels
Debian OpenSSL, 2008
One of the most famous examples of catastrophic entropy reduction is a bug in Debian OpenSSL. Due to a poorly executed change in the PRNG initialization code, keys were generated from an extremely small set of states. This made it possible to create lists of weak SSH and TLS keys and then recognize them.
The similarity with CVE-2023-31290 is that the cryptographic primitives themselves weren’t compromised. The vulnerability was in the procedure for generating secret key material.
Android Bitcoin RNG, 2013
In 2013, some Android wallets suffered from insufficient randomness in the generation of nonce \(k\) for ECDSA signatures. If the nonce is repeated or partially predictable, the private key can be recovered from the signatures.
s = k -1 (z + rd) mod n
If the same \(k\) value is used in two signatures, the private key becomes computable. In the case of Trust Wallet, the weakness was located earlier: the source of the mnemonic was compromised, not the signature’s one-time nonce.
Milk Sad / Libbitcoin Explorer, 2023
The Milk Sad vulnerability in Libbitcoin Explorer was also related to wallet generation based on a weak and predictable source of randomness. Research showed that the actual difficulty of recovering some seed phrases could differ radically from the stated length of the mnemonic.
Both cases confirm the general principle: the BIP-39 format does not guarantee security in itself. Security depends on how the initial entropy was generated before encoding into words.
Design errors
| Error | Consequence | The correct approach |
|---|---|---|
| Using a general PRNG for a cryptographic problem. | The stream of random values becomes reproducible with a known seed. | Use a CSPRNG provided by the operating system or a secure crypto library. |
| Limited 32-bit seed. | The search space is reduced to \(2^{32}\) options. | Obtain at least 128 bits of unpredictable entropy for 12-word BIP-39 mnemonics. |
| Insufficient WASM-specific testing. | Native and browser implementations receive different levels of security. | Test cryptographic properties separately for each platform and build target. |
| Reliance on an API without formally analyzing its guarantees. | The API name gives the false impression of cryptographic randomness. | Document the entropy source, its properties, fault tolerance, and threat model. |
Safe generation in the browser
In a browser environment, the correct source of randomness is the Web Crypto API. Specifically, crypto.getRandomValues() it provides bytes derived from a cryptographically secure random number generator implemented by the browser and operating system.
// Пример безопасного получения 128 бит энтропии в браузере.
// Данный код демонстрирует принцип; для production следует применять
// проверенные реализации BIP-39 и полный аудит окружения.
function secureEntropy128() {
const entropy = new Uint8Array(16); // 16 bytes = 128 bits
if (!globalThis.crypto || !globalThis.crypto.getRandomValues) {
throw new Error("CSPRNG Web Crypto API недоступен");
}
globalThis.crypto.getRandomValues(entropy);
return entropy;
}
When creating cryptographic keys, it is prohibited to replace CSPRNGs with constructions based on time, counters, Math.random()user events without a cryptographic entropy accumulator, linear generators, or standard generators for simulation.
PRNG Audit Methodology
A cryptographic audit of key generation should evaluate not only the algorithm for converting entropy into a key, but also the origin of each bit of randomness. For WASM, browser extensions, mobile, and server-side environments, independent threat models must be considered.
- Construct a data flow graph from the system randomness source to the private key.
- Check if CSPRNG is used on all target platforms.
- Determine the actual amount of entropy, not the stated length of the resulting key.
- Check the error handling of the randomness API: failure should not result in an unsafe fallback.
- Perform reproducible tests to ensure that the seed is not repeatable across multiple runs.
- Conduct an independent audit of the WASM artifact, not just the source code of the native assembly.
- Use fuzzing and differential testing between native and WASM implementations.
Example of a uniqueness test
// Упрощённый концептуальный тест.
// Он не доказывает криптографическую стойкость,
// но способен обнаружить грубые повторения генерации.
const generated = new Set();
for (let i = 0; i < 100000; i++) {
const bytes = secureEntropy128();
const hex = Array.from(bytes)
.map(x => x.toString(16).padStart(2, "0"))
.join("");
if (generated.has(hex)) {
throw new Error("Обнаружено повторение: требуется расследование PRNG");
}
generated.add(hex);
}
Practical recommendations
For wallet developers
- Use exclusively CSPRNGs to generate entropy, secret keys, nonces, and seeds.
- Do not use Mersenne Twister, linear congruential generators, or general-purpose PRNGs in a cryptographic circuit.
- Conduct separate code audits for WASM, browser extensions, mobile, and server assemblies.
- Do not consider the size of the output key as proof of its entropy.
- Apply independent security review before releasing wallet creation features.
- Implement coordinated vulnerability disclosure and a bug bounty program.
For users
- Always update your wallet when security advisory is published by the developer.
- If you receive a notification about weak generation, create a new wallet in the corrected version and transfer assets to it.
- Do not import the vulnerable seed into the new interface as a mitigation measure: the secret remains the same.
- Use the optional BIP-39 passphrase only if you have a clear understanding of the backup storage model.
- Check the project’s official channels and do not share your seed phrase with support, websites, or third parties.
Conclusion
CVE-2023-31290 is a demonstrable vulnerability at the intersection of applied cryptography, WebAssembly compilation, and cryptocurrency wallet security. In this case, secp256k1, ECDSA, SHA-512, PBKDF2, or the BIP-39 standard were not compromised. The vulnerability arose when cryptographically strong algorithms were given predictable source material.
From a cryptanalytic perspective, the incident reduced the problem of searching for a secret from a space of \(2^{128}\) possibilities to searching a space of order \(2^{32}\). This reduction by 96 bits transforms a theoretically unachievable attack into a feasible problem of massive precomputation and searching through blockchain addresses.
For cryptographic systems, entropy should be considered the primary security asset. The strength of a key is determined not by the length of a string, the number of words, or the appearance of randomness, but by the amount of unpredictable information actually introduced into its creation.
Sources
PLEASE SELECT TWO DISTINCT LANGUAGES: https://goolg.ru/please-select-two-distinct-languages/
- Trust Wallet. Browser Extension WASM Vulnerability Postmortem , April 2023. https://community.trustwallet.com/t/browser-extension-wasm-vulnerability-postmortem/750787
- Ledger Donjon. Funds of Every Wallet Created With the Trust Wallet Browser Extension Could Have Been Stolen , 2023. https://www.ledger.com/blog/funds-of-every-wallet-created-with-the-trust-wallet-browser-extension-could-have-been-stolen
- National Vulnerability Database. CVE-2023-31290 Detail . https://nvd.nist.gov/vuln/detail/CVE-2023-31290
- Bitcoin Improvement Proposal 39. Mnemonic code for generating deterministic keys . https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki
- Bitcoin Improvement Proposal 32. Hierarchical Deterministic Wallets . https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki
- Milk Sad. Technical write-up for CVE-2023-31290 and related weak entropy issues . https://milksad.info/disclosure.html
