
Abstract. This paper analyzes the Coinspect Ill Bloom investigation , which began in May 2026 following a series of withdrawals from wallets across various networks. The central cryptanalytic fact is that a valid BIP39 mnemonic could have been generated from a predictable source: the function CryptoJS.lib.WordArray.random() used a variant of the Multiply-With-Carry (MWC) pseudorandom generator rather than a CSPRNG, and the actual entropy of the candidate space was reduced to approximately 2^39 128 2^47or 256 bits, rather than the claimed 128 or 256 bits. This shifts the attack from the challenge of breaking ECDLP/secp256k1 to the challenge of brute-forcing a flawed secret generation process.
Keywords: BIP39, entropy, CSPRNG, CryptoJS, MWC, Math.random(), HD wallet, cryptanalysis, supply chain, vulnerability disclosure, on-chain analysis.
1. Statement of the problem
Ill Bloom’s research demonstrates a fundamental difference between the cryptographic strength of an algorithm and the strength of a key’s lifecycle. The address, signature, and mnemonic phrase may have been syntactically and cryptographically correct; the compromise occurred earlier—at the point of entropy origin.
Security(wallet) ≤ Security(entropy source)
Therefore, a 256-bit private key does not automatically gain 256 bits of practical security. Its effective security is upper-bounded by the min-entropy of the generator input: H∞(X) = -log2(max_x Pr[X=x]).
Historical analogue
A similar class of risk is known as Randstorm: older JavaScript wallets could generate key material via the insecure Math.random()/JSBN chain. In both cases, the attacker’s goal is not to solve a discrete logarithm, but to reconstruct or enumerate a small set of possible secrets generated by a weak RNG.
2. Ill Bloom’s technical mechanism
The vulnerable branch of CryptoJS was introduced in June 2014 in version 3.1.2-4. Instead of a system-wide cryptographic randomness source, it used a custom MWC generator whose state depended on Math.random(); this design does not have the required unpredictability of a CSPRNG.
| Layer | Normal design | Defective design | Cryptanalytic investigation |
|---|---|---|---|
| The source of randomness | OS CSPRNG: Web Crypto / Node crypto | MWC initialized via Math.random() | Small/predictable state space |
| BIP39 Entropy | 128 or 256 independent bits | The nominal length is preserved, the actual set is sharply compressed | Search for candidates is possible |
| Mnemonic and seed | Are deterministically derived from qualitative ENT | Deterministically derived from weak ENT | Correct format does not mean confidentiality |
| Addresses and keys | Output by HD algorithms | They are derived by the same algorithms | Candidates can be compared with blockchain |
Formal model
In BIP39, the checksum has length CS = ENT / 32, and the mnemonic length in words is MS = (ENT + CS) / 11. Therefore, a 128-bit ENT produces a 12-word phrase, and a 256-bit ENT produces a 24-word phrase. The checksum detects errors but does not add secret entropy.
ENT || CS → BIP39 word indices → mnemonic → PBKDF2-HMAC-SHA512 → seed → HD derivation → keys/addresses
For normal generation, the space size is |S| = 2^ENT. In the case described by Coinspect, it is estimated |S_vuln| ≈ 2^39 for both the nominal 128 bits and |S_vuln| ≈ 2^47 the nominal 256 bits. The loss is approximately 89 and 209 bits, respectively.
ΔH = ENT − log2(|S_vuln|); ΔH128 ≈ 128 − 39 = 89; ΔH256 ≈ 256 − 47 = 209
Illustrative secure code
// Браузер: источник для секретов — только Web Crypto API.
const entropy = new Uint8Array(32); // 256 бит
crypto.getRandomValues(entropy);
// Node.js
import { randomBytes } from 'node:crypto';
const entropyNode = randomBytes(32);
Important: This example demonstrates a valid randomness source, but is not a complete wallet implementation. A production implementation requires verified BIP39/BIP32 libraries, dependency management, testing, and a secure backup procedure.
Archival cryptanalytic example
A classic example of a weak-entropy disaster remains Debian OpenSSL (2006–2008): due to a defective patch, keys were generated from an extremely small set of options. As in Ill Bloom, the strength of RSA or ECC was not mathematically “broken”; what was destroyed was the premise of randomly selecting a secret key.
3. Why this isn’t an attack on secp256k1
For a correctly chosen private key, d the public key is calculated as Q = dG, where G is the secp256k1 base point. The inverse problem—finding d by Q —is related to ECDLP and is not practically solvable simply because the address is public.
Q = dG, d ∈ [1, n − 1]
In Ill Bloom, the attacker operates differently: they reproduce or enumerate a limited set of addresses ENT, apply standard BIP39/HD derivation, and compare the resulting addresses with observed on-chain addresses. The target key is not derived from the public key; it is recovered by repeating the erroneous generation process.
Performance evaluation
When searching the N state space completely, the average number of checks before hitting a target is approximately N/2. Even without performance monitoring, a qualitative difference is evident: 2^39 and 2^47 is a fundamentally different class of problems than a space of order 2^128 or 2^256.
E[work] ≈ |S_vuln| / 2
Historical analogue
In the PlayStation 3 attack (2010), a repeated or predictable nonce in ECDSA allowed the private key to be deduced from the signatures. The general lesson from Ill Bloom is that elliptic curves do not compensate for protocol implementation errors—whether in the signature nonce or the initial key entropy.
4. Investigation Methodology
Coinspect didn’t stop at discovering the flawed library. The investigation included reproducing the vulnerable generation, obtaining candidate mnemonics, address derivation, comparison with blockchain history, source code analysis, dependency chain analysis, and reverse engineering of archived application packages.
| Phase | Scientific and technical problem | Proof of results | A practical example |
|---|---|---|---|
| Reproduction | Confirm that RNG produces a limited set of ENTs | Reproducible candidates | In cryptanalysis, this is analogous to test vector validation. |
| Derivation | Consider BIP39, dictionary languages, networks, and paths | Candidate address sets | Different BIP44/49/84 paths yield different addresses with the same seed |
| On-chain correlation | Check addresses against transaction activity | Separating used wallets from abstract candidates | Clustering and service labels as a source of hypotheses |
| Software Attribution | Prove that the RNG code was included in the wallet generation | The “address-version-application” relationship | Analysis of lockfiles, source codes, APKs, and build artifacts |
| Response | Reduce damage without releasing operational details | Patches, migration, notifications, address checker | Coordinated vulnerability disclosure |
The key principle of attribution is that the presence of a dependency crypto-js does not prove a compromise. It is necessary to trace the data flow from the call WordArray.random() to the ENT/mnemonic, and then correlate the specific historical version of the application, its configuration, and the observed on-chain data.
A practical example of checking dependencies
# Node.js-проект: инвентаризация прямых и транзитивных зависимостей.
npm ls crypto-js
npm audit
npm explain crypto-js
# Фиксация артефакта для исследования (не доказательство уязвимости сама по себе).
sha256sum app-release.apk
Historical APKs and repository forks are especially important for defunct apps: the current version may be secure, but millions of previously created keys remain vulnerable. This “cryptographic debt” persists until funds are transferred to new key material.
5. Verified applications
At the time of Ill Bloom’s disclosure, RRWallet (RenrenBit), Bexo Wallet, NanChat, Bitcoin Libre, and Milo were confirmed. This list should not be interpreted as a complete list of affected applications: the researchers emphasize the incompleteness of the archives, the closed nature of some software, and the difficulty of accessing historical releases.
| Application | Status | Remediation | Confirmation type |
|---|---|---|---|
| RRWallet (RenrenBit) | Discontinued | Fix not available | Public source code |
| Bexo Wallet | Actively | Fixed in 20.1.0 | Dependency analysis; controlled validation |
| NanChat | Actively | Fixed in 1.3.0; migration is planned | Source code and dependencies |
| Bitcoin Libre | Actively | Fixed in version 4 | On-chain data and historical APK analysis |
| Milo | Discontinued | Fix not available | On-chain correlation and historical APK |
For example, for Milo, researchers observed a concentration of activity: 96% of wallets in a specific subset of the 256-bit search received the same token in Polygon. This illustrates a scientifically sound sequence: a statistical anomaly generates a hypothesis, and analysis of a software artifact transforms it into a technically verifiable statement.
6. Disclosure during an active attack
Disclosing such issues is a matter of risk optimization. Full disclosure of brute-force parameters and optimizations can increase the ability of third-party attackers to attack funds that haven’t yet been migrated; excessive silence, on the contrary, deprives users and developers of the opportunity to identify the risk and implement migration.
Risk_disclosure = Risk(accelerating abuse) + Risk(delaying remediation)
Coinspect employed a phased disclosure process, exchanging addresses and evidence with relevant parties, and launching a public address checker. This is consistent with the general approach of coordinated vulnerability disclosure: publishing enough information for identification and remediation, but avoiding details that directly reduce the cost of exploitation.
Historical analogue
After Heartbleed was disclosed in 2014, the public nature of the flaw meant that patching the servers wasn’t enough: potentially compromised keys and credentials had to be replaced. In Ill Bloom, the parallel is even starker: the patch prevents the creation of new weak wallets, but doesn’t change the seed, which had already been predictably generated.
7. Recommendations
For wallet owners
- If the wallet was created by an affected version or its origin cannot be reliably determined, create a new wallet using current, verified software on a device with a working operating system and transfer all assets to new addresses.
- Don’t consider updating an application as a replacement for migration: the old mnemonic and all keys deterministically derived from it remain the same.
- Verify addresses only through the official verification service and the developer’s official channels; do not enter the seed phrase into websites, support forms, or “verification” applications.
- Save evidence: app version, creation date, addresses, installer hashes, and transaction history—this helps with investigation and notification.
For developers
- Use only CSPRNG platforms:
crypto.getRandomValues()in the browser,crypto.randomBytes()in Node.js, system APIs in native clients. - Do not use
Math.random()a custom PRNG, timestamp, or custom event to generate seeds, keys, nonces, tokens, and salts if the value is sensitive. - Conduct a data-flow audit: prove the path from the system CSPRNG to BIP39 ENT; the presence of a “cryptographic” library as a dependency does not prove security.
- Maintain SBOM and lockfile, scan transitive dependencies, archive releases, and ensure reproducible builds.
- For already released vulnerable versions, prepare a migration to a new seed, user notification, and a mechanism for detecting affected addresses.
8. Limitations and Conclusions
Ill Bloom’s materials describe confirmed cases and methodology, but do not establish a comprehensive list of all vulnerable wallets. The absence of an application from the published list does not constitute proof of security; similarly, the presence of an older version of CryptoJS does not prove a vulnerability without proof of its use for mnemonic generation.
The main scientific conclusion is the following: the length of the cryptographic secret, the validity of the BIP39 phrase, and the correctness of the elliptic curve cryptography do not compensate for the lack of input entropy. Ill Bloom is an example of applied cryptanalysis of an implementation and supply chain, where a practical attack was made possible not by a breakthrough in ECDLP, but by the finite, reproducible, and enumerable state space of the generator.
Sources
Coinspect “Ill Bloom”: cryptanalytical analysis of wallet generation vulnerability: https://bitcrack.ru/coinspect-ill-bloom-cryptanalytical-analysis-of-wallet-generation-vulnerability/
- Coinspect. Ill Bloom: Investigating a Wallet Generation Vulnerability During Active Exploitation , 2026. https://www.coinspect.com/blog/ill-bloom-investigation/
- Ill Bloom. Technical Disclosure: The CryptoJS Randomness Vulnerability , 2026. https://illbloom.org/articles/cryptojs-vulnerability/
- Ill Bloom. Identifying the Wallets Behind Vulnerable Recovery Phrases , 2026. https://illbloom.org/articles/identifying-wallets-vulnerable-recovery-phrases/
- GitHub Security Advisory GHSA-rg76-677x-56q9; CVE-2026-71851.
- BIP-0039: Mnemonic code for generating deterministic keys. https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki
