BIP-0039: Mnemonic code for generating deterministic keys

11.09.2026

BIP-0039: Mnemonic code for generating deterministic keys

Scientific and technical article. 

BIP-0039 defines a mnemonic interface for representing cryptographic entropy and a procedure for deriving a 512-bit seed. This seed is then used in BIP-0032 hierarchical deterministic wallets and compatible derivation schemes. The standard addresses the problem of reliably recording machine-generated randomness by humans, but does not provide a mechanism for randomness generation, backup encryption, or error correction.

From a cryptanalytic perspective, BIP-0039 should be viewed as a reversible encoding of the ENT value with a short checksum and as a one-way expansion of the mnemonic via PBKDF2-HMAC-SHA512. The wallet’s strength is determined primarily by the quality of the initial entropy, the secrecy of the mnemonic, and, if it is compromised, the entropy of the additional passphrase.

Status and purpose

BIP-0039, which has a  Deployed status , is part of the Bitcoin application-layer specification and was assigned on September 10, 2013. Its authors are listed as Marek Palatinus, Pavol Rusnak, Aaron Voisine, and Sean Bowe. The document is distributed under the MIT license.

The practical motivation is simple: a binary seed or a long hexadecimal string are poorly suited for manual backup, whereas a sequence of words can be written down, verified, and transferred offline. However, a phrase is not intended to turn a user’s quotation, password, or “memorable phrase” into a secure wallet: it is a classic brainwallet model, vulnerable to dictionary attacks.

Data model

DesignationMeaningAcceptable/fixed valuesCryptanalytic meaning
ENTPrimary random entropy128, 160, 192, 224 or 256 bitsUpper bound on the search space for a valid CSPRNG
CSChecksumENT / 32 bitChecks for some random errors, but does not add any privacy
MSLength of mnemonic12, 15, 18, 21 or 24 wordsDetermines the volume of ENT being coded, not the “power of words”
seedPBKDF2 result512 bits = 64 bytesMaterial for BIP-0032; its length does not increase the initial entropy

CS = ENT / 32 MS = (ENT + CS) / 11 LaTeX: \(CS = ENT/32\), \(MS = (ENT + CS)/11\).

Each word encodes 11 bits, since the dictionary contains 2048 entries:  2048 = 2^11. Therefore, a 12-word mnemonic carries 132 bits, of which 128 bits are entropy and 4 bits are checksum.

ENT, bitCS, bitENT + CS, bitMS, words
128413212
160516515
192619818
224723121
256826424

Construction of mnemonics

The algorithm begins by obtaining the ENT bits from a cryptographically secure random number generator (CSPRNG). The SHA-256 of the ENT is then calculated, the first CS bits of the hash are taken, and appended to the ENT. The resulting string is divided into 11-bit blocks; each block is interpreted as a word index from 0 to 2047.

C = SHA256(ENT)[0:CS] B = ENT || C w_i = Wordlist[ int(B[11i : 11(i+1)]) ] LaTeX: \(C=\operatorname{prefix}_{CS}(\operatorname{SHA256}(ENT))\), \(B=ENT\parallel C\).

Illustrative test vector

For an ENT of 128 zero bits, the checksum is equal to the first four bits of the SHA-256 of that value; according to the official test vectors, the result is a 12-word English phrase beginning with eleven  abandon and ending with  about. This is a public test, not a seed for storing funds: the mnemonic, familiar to any reader, is completely compromised.

ENT (hex): 000000000000000000000000000000000
Mnemonic: abandon abandon abandon abandon abandon abandon abandon abandon abandon about
Passphrase: TREZOR

This vector is useful for auditing: the developer checks the entire pipeline—SHA-256, bit order, dictionary indexing, NFKD normalization, and PBKDF2—against the expected result. Using a null, template, or demo ENT in production code is prohibited.

Dictionaries and normalization

A high-quality BIP-0039 dictionary contains 2048 words, is lexicographically sorted, avoids dangerously similar pairs, and allows for unambiguous recognition of English words based on their first four letters. Sorting allows for searches using binary search or trie; this is an access optimization, not cryptographic protection.

UTF-8 with Unicode Normalization Form Compatibility Decomposition (NFKD) is used for strings. Normalization is critical: visually similar or canonically equivalent Unicode representations without a common rule could yield different byte strings and, therefore, different seeds.

Operational risk:  Translating the words of one mnemonic into another language is not a wallet transformation. PBKDF2 accepts the phrase text, not the hidden ENT; the modified text produces a different seed. In the current ecosystem, the English dictionary is the most compatible, and the specification strongly discourages releasing new mnemonics in non-English dictionaries unless absolutely necessary.

Transition to seed

The mnemonic and optional passphrase are normalized using NFKD. The mnemonic phrase is used as a PBKDF2 password, and the salt is formed by the string  "mnemonic", to which the passphrase is appended. BIP-0039 parameters are fixed: 2048 iterations, PRF = HMAC-SHA512, and the result length is 64 bytes.

seed = PBKDF2-HMAC-SHA512( password = NFKD(mnemonic), salt = NFKD(“mnemonic” || passphrase), iterations = 2048, dkLen = 64 ) LaTeX: \(seed=\operatorname{PBKDF2\!\text{-}\!HMAC\!\text{-}\!SHA512}(\operatorname{NFKD}(M),\operatorname{NFKD}(\text{“mnemonic”}\parallel P),2048.64)\).

The result is passed to BIP-0032 or a compatible deterministic system. BIP-0039 itself does not specify the derivation path, address type, network, or accounting model: the same seed can generate different sets of addresses with different paths and wallet agreements.

Passphrase and plausible deniability

Any passphrase, including an empty string, yields a formally valid seed and a separate deterministic wallet. This creates plausible deniability, but also makes backups fragile: loss, typos, different Unicode input, or incorrect passphrase layout won’t cause a cryptographic error—the user will simply see a different wallet.

Cryptanalytic evaluation

For a fairly generated 128-bit ENT, the mnemonic search space is on the order of  2^128; for a 256-bit ENT, it’s on the order of  2^256. Checksum doesn’t complicate the attack: it merely discards most random word strings as invalid. A mnemonic isn’t a password of words, but rather an encoding of a random secret.

N_{valid} = 2^{ENT} P_{undetected} = 2^{-CS} LaTeX: \(N_{valid}=2^{ENT}\), \(P_{undetected}=2^{-CS}\).

For 24 words, CS = 8, meaning that approximately one in 256 random errors can pass the checksum; for 12 words, CS = 4, meaning the probability of an undetected random error is approximately 1/16. The checksum does not correct errors or authenticate the origin of the phrase, and therefore should not be considered a defense against forgery or exfiltration.

PBKDF2 with 2048 iterations increases the cost of a single hypothesis check but does not increase entropy. If the attacker already knows the mnemonic and the passphrase is short, predictable, or taken from a dictionary, offline passphrase brute-force is practically the primary threat. Conversely, an unknown high-entropy mnemonic retains its strength regardless of the relatively moderate PBKDF2 parameter.

Historical lessons

Brainwallet: A Predictable Secret

Historical brainwallet compromises demonstrate why BIP-0039 explicitly requires computer-generated randomness. Services and attackers could pre-hash huge dictionaries of quotes, song lyrics, common phrases, and passwords, calculate the corresponding public keys, and automatically withdraw funds from the addresses they were deposited into. The reason isn’t the weakness of SHA-256 or the elliptic curve secp256k1, but the low entropy of the human-generated input.

Milk Sad: A weak source of ENT

The Milk Sad incident, disclosed in 2023, demonstrated a similar risk for deterministic wallets: vulnerable Libbitcoin Explorer implementations created wallets with predictable randomness based on 32-bit time. Since BIP-0039 only encodes the ENT, valid words and checksums do not save a wallet if the ENT can be recovered by brute-forcing a narrow range of time. This case is particularly important for generator auditing: compliance with the BIP-0039 format does not prove the cryptographic strength of the source material.

Backup compromise

Phishing “seed verification” forms, malicious browser extensions, cloud backup photos, and importing the passphrase into an unknown website transform the hacking task from cryptanalysis to simple secret copying. If the mnemonic is compromised, the BIP-0039 passphrase can restrict access, but it doesn’t eliminate the need to immediately generate a new independent seed on a trusted device and transfer the assets.

Specification limitations

LimitationWhy does it arise?Practical consequence
Dictionary dependencePBKDF2 is fed with the mnemonic text, not the original ENTTranslating words changes the seed; the original language/dictionary must be stored
One-sidednessThe mnemonic is hashed when the seed is received.An arbitrary BIP-0032 seed cannot be correctly represented by a BIP-0039 phrase.
Short checksumCS is only ENT/32There is only limited error detection; no correction.
No versioningThe phrase does not carry information about the path/address formatRecovery requires knowledge of the derivation path and wallet policy; descriptor wallets mitigate the problem.

The authors of BIP-0039 point to SLIP-0039 as a way to address some of the shortcomings. Unlike a single phrase, threshold-based secret sharing helps distribute storage risk, but introduces its own requirements for recovery procedures, share inventory, and interoperability between implementations.

Safe implementation methodology

  1. Obtain ENT only from a trusted operating system CSPRNG or hardware source with proper failure handling; never use time, counter,  Math.random(), custom phrase, or demo template.
  2. Strictly adhere to bit splitting, SHA-256 checksum, 11-bit indexes, official dictionary, and NFKD. An endianess or normalization error will create an incompatible wallet.
  3. Validate the implementation with official test vectors, including a passphrase vector  TREZOR and Unicode/Japanese cases; the test should compare ENT, mnemonic, and the resulting 64-byte seed.
  4. Do not send mnemonics or passphrases to web interfaces, logs, telemetry, crash reports, or cloud synchronization. Consider any online BIP-0039 check a potential exfiltration of key material.
  5. When using a passphrase, create it as an independent, high-entropy secret and back it up separately. It cannot be “hinted” by words from the phrase, date, nickname, or project name.
  6. Document the derivation path, script/address type, network, and descriptors. A single phrase isn’t always sufficient for quickly and accurately detecting all historical UTXOs.

Minimal pseudocode

function entropy_to_mnemonic(entropy_bytes, wordlist):
    ENT = bit_length(entropy_bytes)
    require ENT in {128, 160, 192, 224, 256}
    CS = ENT / 32
    bits = bits_of(entropy_bytes) || first_bits(SHA256(entropy_bytes), CS)
    return join(wordlist[integer(bits[i:i+11])] for i in range(0, ENT+CS, 11))

function mnemonic_to_seed(mnemonic, passphrase = ""):
    password = UTF8_NFKD(mnemonic)
    salt = UTF8_NFKD("mnemonic" || passphrase)
    return PBKDF2_HMAC_SHA512(password, salt, 2048, 64)

The pseudocode is intentionally not a production library. In real-world software, consistent length checking, correct Unicode handling, not keeping secrets in memory longer than necessary, compatibility tests, and independent entropy source auditing are essential.

Conclusions

BIP-0039 is a successful standard for portable representation of a random secret, not a standalone “12- or 24-word security solution.” Its cryptographic security relies on four conditions: unpredictable ENT, strict adherence to the format and Unicode normalization, preservation of the secrecy of the passphrase, and sufficient entropy of the passphrase when used.

The key fact for a cryptanalyst: the format validity of a mnemonic is not equivalent to the strength of a wallet. Checksum verification, 2048 PBKDF2 iterations, and a 512-bit seed length do not compensate for a weak ENT generator, pattern reuse, or a human-guessable passphrase.

Sources

BIP-0039: mnemonic code for generating deterministic keys: https://dynet.ru/bip-0039-mnemonic-code-for-generating-deterministic-keys/

  1. Bitcoin Improvement Proposal 39: Mnemonic code for generating deterministic keys .
  2. Trezor python-mnemonic: official BIP-39 test vectors .
  3. SLIP-0039: Shamir’s Secret-Sharing for Mnemonic Codes .
  4. Milk Sad: An Analysis of Libbitcoin Explorer’s Predictable Wallet Generation .