Skip to content

Seed Phrases

A seed phrase (12 or 24 ordinary English words, in a specific order) is how most Bitcoin wallets let you back up and restore access to every key they manage, without writing down raw hexadecimal. This chapter covers exactly how a phrase encodes a key, verified against the official BIP-39 test vector, and why the specific design choices (checksummed words, a fixed wordlist) matter.

Every example in this chapter uses the well-known, publicly documented BIP-39 test vector, all-zero entropy, producing the phrase "abandon abandon ... about." This specific phrase is recognized throughout the Bitcoin ecosystem as a test-only value; funds sent to any address derived from it have been swept by bots within minutes for years. Never use it, or any phrase generated the way this chapter's examples generate one, for real funds.

Entropy

A seed phrase starts with entropy (genuinely random bits, generated by a cryptographically secure random number generator, exactly the same quality of randomness a raw private key requires (see Private and Public Keys). BIP 39 specifies entropy lengths of 128, 160, 192, 224, or 256 bits, corresponding to mnemonics of 12, 15, 18, 21, or 24 words respectively) 128 bits (12 words) and 256 bits (24 words) are by far the most common in practice.

How entropy becomes words

  1. Generate the raw entropy (128 bits, for a 12-word example).
  2. Compute a checksum: the first entropy-bits / 32 bits of SHA256(entropy), for 128 bits of entropy, that's 4 checksum bits.
  3. Append the checksum to the entropy, producing a bit string whose length is now a multiple of 11.
  4. Split into 11-bit groups (11 bits gives 2^11 = 2048 possible values per group, exactly the size of the BIP-39 wordlist).
  5. Look up each 11-bit value as an index into the standardized 2048-word list, producing the mnemonic.

Example: the official test vector, reproduced

import { entropyToMnemonic, validateMnemonic, mnemonicToSeedSync } from "@scure/bip39";
import { wordlist } from "@scure/bip39/wordlists/english.js";

// 128 bits of all-zero entropy — the official BIP-39 test vector, never
// real randomness, never for real funds.
const testEntropy = new Uint8Array(16);

const mnemonic = entropyToMnemonic(testEntropy, wordlist);
console.log("mnemonic:", mnemonic);
console.log("valid:", validateMnemonic(mnemonic, wordlist));

const seed = mnemonicToSeedSync(mnemonic, ""); // "" = no additional passphrase
console.log("seed (hex):", Buffer.from(seed).toString("hex"));

Verified output from running this exact code, using @scure/bip39:

mnemonic: abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about
valid: true
seed (hex): 5eb00bbddcf069084889a8ab9155568165f5c453ccb85e70811aaed6f6da5fc19a5ac40b389cd370d086206dec8aa6c43daea6690f20ad3d8d48b2d2ce9e38e4

This matches the official BIP-39 specification's own published test vector exactly, confirming this implementation (and, by extension, any wallet correctly implementing the same standard) derives the identical seed from the identical entropy.

From mnemonic to seed: why PBKDF2

Notice the final step above uses PBKDF2 (Password-Based Key Derivation Function 2, with HMAC-SHA512, 2048 rounds, per the BIP-39 spec) to turn the mnemonic words back into a 512-bit seed, not a simple hash. This is a deliberate choice distinct from most of this book's other hashing use cases: PBKDF2 is intentionally slow (2048 rounds of repeated hashing, rather than one pass), which matters specifically because a mnemonic's actual entropy (128–256 bits) is far less than the seed's full 512-bit output size, and this derivation step is also where an optional user passphrase gets mixed in (see BIP-39 for what that passphrase actually protects against).

Why words instead of raw hex

Twelve English words are dramatically easier for a human to accurately transcribe, read aloud, and manually verify than 32 bytes of hexadecimal, and the built-in checksum (step 2 above) means a wallet can detect most transcription errors (a mistyped or misremembered word) immediately upon entry, rather than silently generating a different, wrong key. This is a genuine, practical usability improvement over raw key backup, not merely cosmetic.

Common misconceptions

A seed phrase is not a password you choose or memorize by ordinary means. Like a private key, it must be generated with cryptographically secure entropy; a phrase built from memorable words you pick (rather than derived from genuine random entropy through the process above) is catastrophically insecure, for exactly the reasons discussed in Private and Public Keys.

The specific wordlist matters, and it's standardized, not arbitrary. The 2048-word BIP-39 English list was deliberately curated (avoiding similar-sounding or similarly-spelled words, among other criteria) to minimize transcription and recognition errors; using a different word list than the one your wallet software expects will produce different, incompatible results.

Further reading


← Previous: Public Keys · Back to Wallets and Key Management · Next: BIP-39 →