Skip to content

Latest commit

 

History

12 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

BIP-39 wordlists

integrity

BIP-39 wordlists in several formats, plus printable backup sheets from hardware and metal-plate vendors.

pdf · decimal · index · hex · binary · diceware · plain

txt · json

Naming

Files are named bip-39-<format>-<source>.<ext>:

Format Numbering Range
plain none, words only
decimal decimal, starts at 1 1-2048
index decimal, starts at 0 0-2047
hex hexadecimal, starts at 0 000-7FF
binary 11-bit binary, starts at 0 00000000000-11111111111
diceware rolls or draws as printed

decimal and index differ only in the start value. index starts at 0 (BIP-39 / wallets). decimal starts at 1 (most plates).

binary is eleven bits as the lookup key. Coin flips, a d6 read as odd/even, or cards mapped to bits still use a binary list. diceware is when the sheet's keys are the physical results (11111 h, d8 faces, a card).

Sheets with more than one notation use the rarer one, for example binary over decimal, or a card map over binary.

The last part of the name is the vendor, or a short label if there is none. Plain lists live under wordlists/txt/lang/ and use the language name from the BIP-39 wordlists. The lists below drop the bip-39- prefix.

Formats

.txt

Upstream

From the BIP, under wordlists/txt/lang/. One word per line, 2048 lines:

Derived

From lang/english.txt:

english.txt       abandon
oneline.txt       abandon ability able about above absent …
decimal.txt          1  abandon
index.txt            0  abandon
hex.txt            000  abandon
binary.txt        00000000000  abandon
index-binary.txt     0  00000000000  abandon
diceware-d4.txt   11111 h  abandon

.json

From lang/english.txt:

Only the word is stored; the rest follows from the index:

order  = index + 1
binary = index.toString(2).padStart(11, '0')
hex    = index.toString(16).toUpperCase().padStart(3, '0')

.pdf

Decimal (1 to 2048)

Index (0 to 2047)

Hexadecimal (000 to 7FF)

  • hex-coldcard.pdf - 4 pages, US Letter - source
  • hex-moonsettler.pdf - 1 page, A4 - source
  • hex-dictionary.pdf - 3 pages, US Letter, horizontal
    • numbered 100 to 8FF, not 000 to 7FF: the leading digit is the block of 256, so subtract 100 for the index
    • printed from a spreadsheet, which turned true into TRUE at 84A and false into FALSE at 392

Binary (11 bits, 0 to 2047)

  • binary-massmux.pdf - 9 pages, A4 - source
  • binary-lookup-table.pdf - 4 pages, US Letter
  • binary-blockstream.pdf - 51 pages, A4 - print source
    • these methods first convert their results to 11 bits:
      • Coin - one coin; 11 flips per word
      • D6 - one d6; roll until you collect 11 bits per word
      • D8 - one d8; four rolls per word; keep the first 11 bits
      • Poker - one 52-card deck without Jokers; use the card map; return each card and shuffle after each draw; printable guide under Diceware
      • Piacentine - one 40-card regional deck; use the card map; return each card and shuffle after each draw
      • Tarot - one 78-card deck; use the card map; return each card and shuffle after each draw

Diceware

Plain (no numbering)

Verifying

SHA256SUMS has a SHA-256 for every file under wordlists/:

$ shasum -c SHA256SUMS        # sha256sum -c SHA256SUMS on linux
wordlists/pdf/decimal/bip-39-decimal-coinplate-1p.pdf: OK
...

To compare a vendor file to the copy here, hash theirs and match the line in SHA256SUMS:

$ curl -sL https://bitbox.swiss/bitbox02/BitBox_Diceware_LookupTable.pdf | shasum -a 256
9db3c8986b20737a3b76207a0fb325fec17fb3221aac32d2df470c2615e37535

$ grep d6-bitbox SHA256SUMS
9db3c8986b20737a3b76207a0fb325fec17fb3221aac32d2df470c2615e37535  wordlists/pdf/diceware/bip-39-diceware-d6-bitbox.pdf

A different hash is not always tampering. Vendors often re-export PDFs; a new timestamp changes the hash even when the words are the same.

sources.tsv lists each file and its direct download URL.

Upstream plain lists match the BIP byte for byte:

$ curl -sL https://raw.githubusercontent.com/bitcoin/bips/master/bip-0039/english.txt | diff - wordlists/txt/lang/bip-39-english.txt

Checks

Verifying above is for a file you downloaded. These two scripts check the repo itself. They need Python 3 and a shell, with nothing to install.

scripts/verify.py checks the wordlists are correct. Every list is compared against its pinned hash from the BIP, and every derived file is rebuilt from English and compared:

python3 scripts/verify.py
  upstream wordlists       10 ok
  english properties       3 ok
  file shape               44 ok
  derived txt              10 ok
  json                     3 ok

all checks passed

scripts/check.sh checks the bookkeeping agrees:

./scripts/check.sh
  hashes match SHA256SUMS                        ok
  SHA256SUMS covers every file                   ok
  README sources are in sources.tsv              ok
  sources.tsv paths exist                        ok
  README links are not inside code spans         ok
  README links resolve                           ok

all checks passed

GitHub Actions runs these exact two commands on every push and pull request, so the badge above means what a clean local run means. Together they guarantee that every wordlist matches the BIP byte for byte, that every derived file follows from English, that nothing is missing from SHA256SUMS, and that no link in this README is broken.

A separate weekly job re-fetches every URL in sources.tsv and reports when a vendor changes their file. It does not fail the build, because a vendor re-exporting a PDF is not a fault here.

Adding a wordlist

Two kinds of file live here and they need different things.

A sheet published by someone else. Name it bip-39-<format>-<vendor>.<ext> and put it in the folder for its numbering. The format is what the sheet prints, not what the vendor sells: decimal starts at 1, index starts at 0, and a sheet showing more than one notation uses the rarer one. Use a short label when there is no vendor.

Download their copy and compare it before recording the URL:

$ curl -sL <url> | shasum -a 256

Add the row to sources.tsv only if that matches. A source link that does not verify is worse than no link.

If the publisher supplies only a print button, save the print view and link the page from the README. Do not add the page to sources.tsv, because it does not return the stored PDF bytes.

A file built here from lang/english.txt. It gets no sources.tsv row, because nobody published it. It needs a case in scripts/verify.py describing how to rebuild it, and a line in the sample block above if it is a .txt.

Either way, finish with:

./scripts/checksums.sh
./scripts/check.sh
python3 scripts/verify.py

check.sh fails if the file is missing from SHA256SUMS or from the lists above, so a half-finished addition cannot pass quietly. What it cannot see is whether a built file is correct, only that it is listed. That is what the verify.py case is for.

License

This is a derivative work of the original BIP-39 wordlist. See BIP-39 for more information. The PDFs are the work of their respective vendors and are redistributed here for convenience. The format icons are from Material Icon Theme, MIT licensed.

About

BIP-39 wordlists in every format, for all your bitcoin needs

Topics

Resources

Stars

1 star

Watchers

1 watching

Forks

Contributors

Languages