BIP39

Brute Forcing Bitcoin BIP39 Seed Phrases

15 min read
MH
Written by Mohamed Habbat

I work in the crypto self-custody space. Every month someone asks whether they should worry about a brute-force attack on their seed phrase. The math says no. The behavior says yes, for reasons they did not expect.

Treat those 12 or 24 words as the Bitcoin itself. Whoever holds the phrase owns every satoshi in the wallet. Nobody can reset it for you.

Below: how BIP39 works, where it breaks, the 12 vs 24 word question, and what is, in my view, the most underused security feature in Bitcoin: the BIP39 passphrase.

TL;DR

A BIP39 seed phrase is the master key to your Bitcoin: 12 to 24 English words encoding 128 to 256 bits of entropy (BIP-39 spec). The wordlist has 2,048 words, word order matters, and PBKDF2 stretches the phrase into a 512-bit seed that derives every key in the wallet. Brute force against real entropy is out of reach. Risk lives elsewhere: weak random number generators, photos of the phrase, cloud copies, typos, and malware. Write it on metal or paper. Never digital.

What Is BIP39?

The BIP39 authors wrote that a sentence of words "is superior for human interaction compared to the handling of raw binary or hexadecimal representations of a wallet seed" (BIP-39 spec). BIP39 standardised that sentence.

How it works:

  1. A wallet generates entropy. A random value of 128 to 256 bits, in 32-bit increments.
  2. The wallet appends a checksum. The first bits of a SHA-256 hash of the entropy go on the end.
  3. The combined value splits into 11-bit segments. Each segment maps to one word from the BIP39 wordlist.
  4. You get 12, 15, 18, 21, or 24 words depending on the initial entropy.

The BIP39 wordlist contains exactly 2,048 words (2^11, by design). The spec says the English list lets you identify each word from its first four letters, which cuts typing errors (BIP-39 spec). BIP-39 ships 10 official wordlists across English, Japanese, Korean, Spanish, Chinese (Simplified), Chinese (Traditional), French, Italian, Czech, and Portuguese (BIP-39 wordlist registry). The spec itself strongly discourages non-English lists, because most wallets support only English. Marek Palatinus, Pavol Rusnak, Aaron Voisine, and Sean Bowe wrote the standard, assigned on 10 September 2013 (BIP-39 spec).

Then the PBKDF2 key stretching function runs the mnemonic through 2,048 rounds of HMAC-SHA512 to produce a 512-bit binary seed (BIP-39 spec). That seed feeds the BIP32 HD (hierarchical deterministic) wallet derivation algorithm, which generates the entire tree of private and public keys the wallet uses.

One seed phrase covers a whole tree of keys: every key in the tree can have 2^31 normal and 2^31 hardened children (BIP-32 spec). Every address the wallet has generated is recoverable from those words plus the passphrase, if you set one.

12 Words vs 24 Words

BIP39 maps 128 bits of entropy to 12 words and 256 bits to 24 words (BIP-39 spec). The entropy numbers translate like this:

Phrase LengthEntropyPossible Combinations
12 words128 bits~3.4 × 10^38 (2^128)
24 words256 bits~1.16 × 10^77 (2^256)

A worked example. Every guess costs 2,048 rounds of HMAC-SHA512. An RTX 4090 runs PBKDF2-HMAC-SHA512 at 3,120.9 thousand hashes per second at 999 iterations (hashcat benchmark), which scales to about 1.5 million seed checks per second at 2,048. At that rate one card needs about 7 × 10^24 years to try every 12-word seed, and a million cards still need about 7 × 10^18 years. The Sun has about 5 billion years left (NASA). For a full walkthrough of choosing and using a wallet, see the self-custody guide.

24 words give the seed 256 bits. The keys it derives still sit on the secp256k1 curve, which SEC 2 rates at 128-bit security (SEC 2, Table 1). So the extra 12 words protect the seed, not the signing keys.

Both are secure today. My rule of thumb: 24 words for long-term savings, because the margin costs nothing but a few minutes of writing.

How Your Wallet Derives Keys

The derivation path explains why one seed phrase is so powerful, and so dangerous to expose.

Your seed phrase, via PBKDF2, produces the master seed. The master seed, via BIP32, produces the master private key and master chain code.

From the master private key, the wallet derives child keys along a derivation path. BIP44 defines the path layout (BIP-44 spec), and BIP84 reuses it with purpose 84' for native SegWit addresses (BIP-84 spec). A BIP44 path looks like this:

m / 44' / 0' / 0' / 0 / 0

Where:

  • m = master key
  • 44' = BIP44 purpose
  • 0' = Bitcoin (coin type 0)
  • 0' = first account
  • 0 = external chain (receiving addresses)
  • 0 = first address index

Every Bitcoin address you have ever received funds on is deterministically derived from that master seed. Restore the seed phrase on a compatible wallet, with the same passphrase and derivation path, and everything comes back: addresses, balances, transaction history.

Lose the seed phrase and there is nothing to restore. No central server, no recovery path.

How To Generate BIP39 Wallets In Node.js

The fastest way to understand BIP39 entropy is to generate it yourself. The Node.js setup below spins up wallets and checks whether the generated addresses have ever held funds. Working code from Bi-Catalyst/bruteforcebitcoin. Educational only. Generating random wallets and checking on-chain activity is a brute-force exercise that confirms the math. It is not a path to anyone else's coins.

Tech Stack

  • axios for HTTP requests to blockchain APIs
  • bip39 for mnemonic generation and seed derivation
  • bitcoinjs-lib for address derivation and transaction tooling

package.json:

{
  "name": "bruteforcebitcoin",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "run": "node generate_wallet.js"
  },
  "license": "MIT",
  "dependencies": {
    "axios": "^1.4.0",
    "bip39": "^3.1.0",
    "bitcoinjs-lib": "^5.2.0"
  }
}

Imports And Constants

const axios = require("axios");
const bip39 = require("bip39");
const bitcoin = require("bitcoinjs-lib");
const fs = require("fs");

const parallelLimit = 10;
const iterations = 100;
const batchSize = 10;
const delayBetweenBatches = 5000; // 5 seconds
const apiDelay = 3000; // 3 seconds
let useBlockchainInfoAPI = true;

Generating A Wallet

async function generateWallet() {
  // Generate a new 12-word mnemonic seed phrase
  const mnemonic = bip39.generateMnemonic(128);
  console.log("Mnemonic:", mnemonic);

  // Convert the mnemonic to a seed
  const seed = await bip39.mnemonicToSeed(mnemonic);

  // Derive the wallet from the seed using BIP32
  const network = bitcoin.networks.bitcoin;
  const hdMaster = bitcoin.bip32.fromSeed(seed, network);
  const account = hdMaster.derivePath("m/44'/0'/0'/0");

  // Generate a new Bitcoin address
  const { address } = bitcoin.payments.p2pkh({
    pubkey: account.derive(0).publicKey,
    network,
  });

  console.log("Bitcoin Address:", address);
  const hasTransactions = await checkAddressActivity(address);
  await new Promise((resolve) => setTimeout(resolve, apiDelay));
  return { address, hasTransactions };
}

Checking Address Activity

Two public block explorers alternating to manage rate limits. Blockchain.com's API and BlockCypher's API:

async function checkAddressActivity(address) {
  try {
    let response;
    if (useBlockchainInfoAPI) {
      response = await axios.get(`https://blockchain.info/rawaddr/${address}`);
    } else {
      response = await axios.get(`https://api.blockcypher.com/v1/btc/main/addrs/${address}`);
    }

    useBlockchainInfoAPI = !useBlockchainInfoAPI;

    let hasTransactions = false;

    if (response.data.txs) {
      hasTransactions = response.data.txs.length > 0;
    } else if (response.data.txrefs) {
      hasTransactions = response.data.txrefs.length > 0;
    }

    if (hasTransactions) {
      console.log("This address has transactions associated with it.");
      return true;
    } else {
      console.log("This address has no transactions associated with it.");
      return false;
    }
  } catch (error) {
    console.error("Error fetching address data:", error.message);
    return false;
  }
}

Persisting Hits

function appendToFile(filename, data) {
  fs.appendFile(filename, data, (err) => {
    if (err) {
      console.error(`Error saving data to ${filename}:`, err.message);
    } else {
      console.log(`Data saved to ${filename}`);
    }
  });
}

Orchestrating The Run

async function main() {
  const walletPromises = [];

  for (let i = 0; i < iterations; i++) {
    walletPromises.push(generateWallet());

    if (walletPromises.length === parallelLimit) {
      await processBatch(walletPromises);
      walletPromises.length = 0;
    }
  }

  if (walletPromises.length > 0) {
    await processBatch(walletPromises);
  }
}

Run it overnight and you will not hit a funded wallet. The script runs 10 wallets at a time, waits 3 seconds after each API call and 5 seconds between batches (generate_wallet.js), so it checks about one wallet per second against a space of 2^128 seeds. It proves the math by failing to defeat it.

Full repo at github.com/Bi-Catalyst/bruteforcebitcoin.

The 25th Word Most Holders Never Set

BIP39 includes an optional passphrase, the "25th word". In my experience most holders never set one. That is a mistake.

When the mnemonic converts to a binary seed, PBKDF2 takes two inputs: your mnemonic and an optional passphrase. By default the passphrase is an empty string (BIP-39 spec). You can enter anything. A word, a phrase, symbols, numbers.

A different passphrase produces a different wallet: same 24 words, new master seed, new addresses, new balances. Two security implications follow.

Physical theft becomes survivable

Someone breaks in and finds your seed phrase on paper. Without the passphrase, they reach only the empty-passphrase wallet, a decoy with a small amount in it. The BIP39 spec names this property: every passphrase generates a valid wallet, which "provides plausible deniability" (BIP-39 spec).

Keep a small balance in the base wallet. Keep the real stack behind the passphrase. Make the passphrase long and random: a thief with your words can test guesses offline with BTCRecover, so a short word buys little.

The attack surface gets smaller

Most attack vectors (physical theft, shoulder surfing, a leaked photo) need only the seed words. The passphrase adds a second factor. Never write it on the same paper, never keep it in the same location, never send it digitally.

Coldcard, Jade, Trezor, and Ledger all support it. Coldcard sells the Q with a QWERTY keyboard "ideal for long BIP-39 passphrases" (COLDCARD Q). Jade has a BIP39 passphrase setting (Jade changelog). Trezor lists passphrase protection on the Safe 3 (Trezor Safe 3). Ledger puts it under Settings, then Security, on the Nano S Plus, and under Settings, then Advanced, on the Flex (Ledger support).

One warning. The passphrase is not recoverable. Forget it, and that Bitcoin is gone. Write it down separately, store it securely, and test your recovery before depositing anything significant.

The Attacks That Drain Bitcoin Wallets

Real-world seed phrase failures almost never involve brute force against good entropy. I sort them into three categories: digital, physical, mathematical.

Digital attacks come first. In my experience phishing causes the most losses: fake wallet apps, fake "wallet recovery" websites, fake support agents. Ledger says it "will never ask you for the 24 words of your recovery phrase" (Ledger), and BitBox says the same of its recovery words (BitBox02). Treat anyone who asks as a thief. Photos are next. In February 2025 Kaspersky found apps in Google Play and Apple's App Store that scanned phone galleries with text recognition to steal recovery phrases, and the infected Google Play apps had over 242,000 downloads (Securelist). Malware (keyloggers, clipboard hijackers) on internet-connected machines can capture seed phrases during entry, which is why dedicated hardware wallets exist.

Physical attacks are slower, and they still happen. Someone finds your written seed phrase in a drawer, behind a frame, on a fridge magnet. Storage location plus the BIP39 passphrase are your defences here. Shoulder surfing is the mild version. Someone watches you generate or enter your seed phrase. Set up hardware wallets in private and check for cameras before confirming anything sensitive.

Mathematical attacks (brute forcing the entropy itself) are the subject of this post's title. They have drained wallets only when the entropy was weak. Libbitcoin Explorer's bx seed produced seeds with 32 bits of real entropy, and the Milk Sad researchers estimate over $900,000 was stolen (Milk Sad disclosure). Coinkite's advisory of 30 July 2026, updated on 1 August, says a Coldcard firmware bug weakened seed generation, that Mk4, Q and Mk5 seeds carried about 72 bits instead of 128, and that attackers regenerated the weak seeds offline and stole funds (Coinkite advisory). The full story is in the Coldcard weak-entropy post. The math holds. Losses come from behavior and from broken entropy sources.

What NOT to Do With Your Seed Phrase

My hard rules:

  • No digital photos. Ever.
  • No cloud storage. Dropbox, Google Drive, iCloud, OneDrive.
  • No password managers unless you have thought through the threat model.

Beyond the above, also skip email (not to yourself, not to anyone), messaging apps (WhatsApp, Signal, iMessage), screenshots, and any website that claims to be a "seed phrase validator" or "wallet recovery tool". Those are scams.

Keep the phrase on paper or metal, in places you control.

How to Store Your Seed Phrase

Generate on a dedicated device (Coldcard, Jade, Trezor) and not a browser extension, mobile app, or any desktop wallet with internet access. A connected computer has too many attack surfaces. A device can still ship a bad random number generator, so add your own entropy where the device allows it. Coinkite's advisory says seeds made with at least 50 private dice rolls kept at least 128 bits of entropy despite the bug (Coinkite advisory).

Metal backup, not paper

Paper burns, gets wet, deteriorates. Metal backups hold your seed words in steel. Cryptosteel calls its Seed24 fireproof (Cryptosteel), and SEEDOR states its 316L stainless steel safe withstands 1,450 °C (SEEDOR). One copy in one location is a single point of failure. Keep two or three metal backups in separate physical locations. If you use a BIP39 passphrase, store it separately from the seed words.

Hardware wallet picks for 2026

Also covered in Wallets Staying Secure.

  • Coldcard Q. Bitcoin-only, airgapped, USD 319 (COLDCARD Q). In my view the most security-focused of the four.
  • Jade Plus. Fully open source, USD 169.99 (Blockstream Jade).
  • Trezor Safe 5. GPL-3.0 firmware (Trezor firmware repository) and what Trezor calls an "NDA-free EAL 6+ Secure Element" (Trezor Safe 5). The Safe 5, and the Safe 3 since June 2024, default to a 20-word SLIP-39 backup, with 12 or 24 BIP-39 words selectable (Trezor backups guide).
  • Ledger Nano S Plus and BitBox02. Ledger uses a 24-word recovery phrase (Ledger support). BitBox02 backs up to a microSD card, with recovery words as an option (BitBox02). Ledger has published two incidents of its own: a 2020 breach of customer contact data (Ledger) and the December 2023 Connect Kit compromise (Ledger incident report).

Test before you deposit. Wipe the device. Restore from your seed phrase. Verify all addresses match. Confirm the passphrase works. Only then send real Bitcoin to the wallet.

Quantum Computing and BIP39

Shor's algorithm solves discrete logarithms (Shor 1995), the problem behind the elliptic curve signatures Bitcoin uses for transactions. It does not apply to BIP39 entropy. A large enough quantum computer could derive a private key from a public key already visible on chain. Against the seed, the best known attack is Grover's search, which needs about the square root of the classical number of guesses (Grover 1996). That turns 2^128 into about 2^64 quantum steps for a 12-word seed and 2^256 into about 2^128 for a 24-word seed, each step still running 2,048 rounds of HMAC-SHA512.

NIST published its first three finalised post-quantum standards, FIPS 203, 204 and 205, on 13 August 2024 (NIST). Bitcoin does not use them yet. Taproot's Schnorr signatures (BIP-340) run on the same secp256k1 curve as ECDSA, so they face the same Shor risk. In my view any migration will be a coordinated protocol change. Full breakdown in the quantum threat analysis.

BIP39 Survives. The Human Layer Often Does Not.

The cryptography is sound. Real 128 or 256 bits of entropy produce a keyspace no adversary can brute force (BIP-39 spec).

The vulnerabilities are human, plus the occasional broken random number generator. Seed phrases get photographed, cloud-synced, typed into phishing sites, stored in a single location with no redundancy. A strong BIP39 passphrase, supported by every hardware wallet named above, defeats most of those scenarios with one extra step.

Do three things. Enable the BIP39 passphrase and store it separately from your seed words. Move to a metal backup, because paper is not a permanent solution. Test your recovery before it matters by wiping the device, restoring from seed and passphrase, and verifying it works.

BIP39 does its part. Whether your coins stay yours depends on the passphrase, the backup and the restore test you add on top.


This article draws on publicly available BIP-39 documentation and hardware-wallet vendor information as of October 2026. It is not security advice. Hardware-wallet firmware and feature sets change. Test every recovery flow on a dedicated device before depositing significant Bitcoin, verify the open-source status of any wallet firmware against the vendor's current public repository, and treat any "BIP-39 brute force" service offer as a scam. Security guidance dates fast. When in doubt, ask an independent security professional or a FINMA-supervised custodian before depositing material capital into a setup you cannot independently verify.


Sources:


New to Bitcoin? Start with Chapter 1.

Want the full picture? Read all 19 chapters free or order the physical book.

Frequently Asked Questions

What is BIP39?
BIP39 (Bitcoin Improvement Proposal 39) is the standard that turns random entropy into a human-readable mnemonic seed phrase. Each word comes from a fixed list of 2,048 words, and the BIP repository holds 10 official wordlists: English, Japanese, Korean, Spanish, Chinese Simplified, Chinese Traditional, French, Italian, Czech and Portuguese (BIP-39 wordlists). The phrase becomes a seed through PBKDF2 with HMAC-SHA512 and 2,048 iterations. Marek Palatinus, Pavol Rusnak, Aaron Voisine and Sean Bowe wrote it, and it was assigned on 10 September 2013 (BIP-39 spec).
12 versus 24 words. Does it matter for security?
12 words encode 128 bits of entropy and 24 words encode 256 bits (BIP-39 spec). Both are out of reach of brute force. One RTX 4090 runs about 1.5 million BIP39 seed checks per second (hashcat benchmark, scaled from 999 to 2,048 iterations), so a million of them would need about 7 billion billion years to try every 12-word seed. The Sun has about 5 billion years left (NASA). The keys a seed derives sit on the secp256k1 curve, rated at 128-bit security (SEC 2, Table 1), so 24 words protect the seed itself, not the signing keys. Trezor Safe 5 and Safe 3 (units since June 2024) default to a 20-word SLIP-39 backup and offer 12 or 24 BIP39 words (Trezor backups guide). Ledger devices use 24 words (Ledger support). BitBox02 backs up to a microSD card, with recovery words as an option (BitBox02).
What is the BIP39 passphrase (the 25th word) and should I use one?
The passphrase is an extra string that combines with the seed phrase to derive a different wallet (BIP-39 spec). A thief with only the seed phrase sees the empty-passphrase wallet, which can be empty or a decoy. It protects you only if the passphrase is long and hard to guess, because a thief holding the words can test passphrases offline with tools such as BTCRecover. My rule of thumb: use one for any holding above spending money. If you lose the passphrase the funds are gone. There is no recovery.
Can a BIP39 seed phrase be brute forced?
Not when the entropy is real. A 12-word phrase has 2^128 possible seeds (BIP-39 spec), and every guess costs 2,048 rounds of HMAC-SHA512. That cost holds one RTX 4090 to about 1.5 million guesses per second (hashcat benchmark, scaled from 999 to 2,048 iterations), not billions. Brute force works only when a wallet generated weak entropy. The Milk Sad researchers showed Libbitcoin Explorer seeds had 32 bits of entropy, and they estimate over $900,000 was stolen (Milk Sad disclosure). Ethical hackers test the real attack surfaces: weak random number generators, supply-chain compromise, screen capture and keylogger malware, and shoulder-surfing during setup.
How should I store a BIP39 seed phrase safely?
Write two copies by hand on the seed cards that ship with the wallet. Never a phone, never a screenshot, never the cloud. Keep the copies in separate locations, such as a home safe and a bank safe-deposit box. For long-term holding, use a steel backup. Cryptosteel calls its Seed24 fireproof (Cryptosteel), and SEEDOR states its 316L stainless steel safe withstands 1,450 °C (SEEDOR). Paper and ink burn.
Is quantum computing a threat to my BIP39 seed phrase?
Not directly. Shor's algorithm solves discrete logarithms (Shor 1995), the problem behind Bitcoin's ECDSA and Schnorr signatures, and it does not apply to BIP39 entropy. Against the seed, the best known quantum attack is Grover's search, which needs about the square root of the guesses (Grover 1996), so 2^128 becomes about 2^64 quantum steps and 2^256 becomes about 2^128. The exposed coins are unspent outputs whose public key is already on chain, covered in the quantum threat analysis.
What if I lose part of my seed phrase?
BIP39 includes a checksum: 4 bits in the last word of a 12-word phrase and 8 bits in the last word of a 24-word phrase (BIP-39 spec). If you have 23 of 24 words and know where the missing word goes, there are 2,048 candidates, and the checksum rules out most of them. BTCRecover automates this search. If you do not know the position, there are 24 places to try, so 24 times 2,048, or 49,152 candidates. That is still a small search.