Reference · Bitcoin seed generation
Bitcoin wallets that generate seeds from dice rolls all use the same recipe. This documents it, verifies it against every implementation, and looks honestly at what imperfect dice actually cost.
Every Bitcoin wallet has to produce a seed from somewhere, and almost all of them use the device's own random number generator. You are then trusting that generator, and there is nothing in its output you can inspect to tell whether it did its job. A sound generator and a broken one produce results that look exactly alike.
Dice are for when you would rather not take that on trust. The rolls are the only input, so the seed is a pure function of something you watched happen, reproducible elsewhere to confirm the device did what it should.
A seed the device chose, you can only trust. A seed you rolled yourself, you can verify.
50 rolls makes a 12-word seed. 99 rolls makes a 24-word seed. Every implementation listed below does exactly this. A formal specification with test vectors is at the end.
Roll a die 99 times
This example follows a 24-word seed the whole way through.
Write the digits down
Hash the digits once with SHA-256
The quotation marks matter: the digits go in as text. The result is always 32 bytes, regardless of how long the input was. For a 12-word seed, only the first 16 are used.
Write those bytes out in binary
Each byte is eight bits. Nothing has changed yet, the same hash, written differently.
Collect the bits into groups of 11
Look each group up in the BIP-39 word list
01010001010→650+1651→eyebrow10011000101→1221+11222→obvious11011000011→1731+11732→such11011000111→1735+11736→suggestEach group is a number from 0 to 2047. The +1 accounts for printed word lists, which start counting at 1 rather than 0. The final group carries a checksum.
Build the final word
6d, and 23 words have used all but its last 3 bits01101101sha256(entropy) =867da839c3…1000011010110000110→1414+11415→radioThis is why the last word cannot be chosen freely.
Read off the words
Any implementation of this recipe gives the same 24 words from the same rolls.
A die has six faces, so N rolls produce 6N possible sequences. The only question is whether that is as many as there are possible seeds.
| Possible dice sequences | Possible seeds | ||
|---|---|---|---|
| 50 rolls → 12 words | 650 ≈ 8.1 × 1038 | 2128 ≈ 3.4 × 1038 | 129.2 bits, over the 128 needed |
| 99 rolls → 24 words | 699 ≈ 1.1 × 1077 | 2256 ≈ 1.2 × 1077 | 255.9 of 256 bits |
50 rolls comfortably exceeds what a 12-word seed needs. 99 rolls lands at 255.9 bits against 256, a 100th roll would push past what a 256-bit seed can hold.
Each was read from source at a pinned commit, not from documentation.
| Implementation | Language | Source |
|---|---|---|
| Signing devices and air-gapped apps, where seeds get generated | ||
| Coldcard | MicroPython | Coldcard/firmware @ 3238f6fd |
| Kern | C | odudex/Kern |
| Krux | MicroPython | selfcustody/krux |
| SeedSigner | Python | SeedSigner @ 0.8.7 |
| AirGap Vault Default mode, 24 words only | TypeScript | airgap-vault @ aa50b7f |
| Software tools, for independently checking one | ||
| Gordian seedtool-cli | C++ | BlockchainCommons/seedtool-cli, CLI |
| Gordian Seed Tool iOS app, 12 words only | Swift | GordianSeedTool-iOS @ 1.6 |
| iancoleman.io Hex or Base 10 mode | JavaScript | iancoleman/bip39, web or signed download |
| Seed Tool | JavaScript | BitcoinQnA/seedtool, web or signed download |
If the wallet you are looking for is not in this table, start with the addendum. Keystone, BlueWallet, BitBox02, Blockstream Jade and Foundation Passport all offer something for hand-rolled seeds, but not this recipe.
Coldcard is here because its construction is the one several of these projects converged on, and because it is the implementation this document checks the recipe against. That is a statement about one hashing routine, not about the device. After the entropy failure disclosed on 1 August 2026, set out in §7, this document treats Coldcard as a reference for the construction and as part of its history, not as a live option for new storage.
The same separation applies to every row. What is verified here is that a given implementation turns your rolls into the same seed as the others. Nothing about that speaks to the rest of a device, its firmware, or the parts of it a dice roll never touches.
The two browser tools ship signed standalone builds with PGP signatures: iancoleman's
bip39-standalone.html and Seed Tool's index.html. A URL is fine for a
try. For anything real: download, verify, disconnect.
One caveat, and it matters: iancoleman.io reproduces the recipe in its Hex and Base 10 modes. Its Dice mode uses a different approach and gives a different seed.
Many implementations, many languages, one recipe, with no specification, but a reference implementation several of these projects deliberately matched.
This is not blind convergence, and presenting it as such would be misleading. iancoleman.io functions as the de-facto reference: seedtool-cli's source carries the comment “Compatibility with iancoleman.io/bip39”, SeedSigner's docstring cites iancoleman and Seed Tool as its model, and Seed Tool is code-derived from iancoleman. At least three deliberately targeted it. Krux and Kern share an author, and both Gordian tools come from Blockchain Commons, so treat each of those as one lineage.
The recipe has also left Bitcoin. LumenSigner, a SeedSigner fork for Stellar, carries the function across essentially unchanged. That is worth knowing for what it says about how a convention spreads: by being copied, not by being specified.
Roll once, verify anywhere. The same rolls give the same seed on any of these, so checking your wallet against one is a real cross-implementation test, not the same code twice.
The honest measure is min-entropy, conservative, assuming an attacker knows your die's exact bias and always guesses the most likely sequences first. Every figure below already assumes that worst case.
■ 24-word (99 rolls) ■ 12-word (50 rolls)
A perfectly fair die 255.9 / 128.0 bits
One face 8% more often than it should 244.9 / 123.7 bits
20% more often, visibly odd 229.9 / 116.1 bits
50% more often, obviously defective 198.0 / 100.0 bits
110% more often, grossly loaded 149.9 / 75.7 bits
Half of all rolls, a trick die 99.0 / 50.0 bits
For a 24-word seed to fall even to 128 bits, one face would have to come up 40.8% of the time, about two and a half times its fair share. Not a slightly warped die; one you would notice in an evening of board games.
Take a die favoring one face 8% more than it should. It costs a 24-word seed 11 bits, leaving 245 of 256. To detect that bias with statistical confidence you would need roughly 6,200 rolls.
You would roll for hours to find a defect worth a rounding error. And the arithmetic runs the other way too: any bias large enough to matter is large enough to notice casually.
A common recommendation is to put ten dice of any quality in a box, shake, and read them left to right. It helps, for a reason worth understanding: after a shake, which physical die lands in which position is itself random, so each reading is drawn from the average of the pool's ten distributions, and averaging independent biases pulls that mixture toward uniform.
| Dice quality | One die, repeatedly | Pool of ten | Regained |
|---|---|---|---|
| Very good | 2.496 | 2.556 | +0.060 |
| Ordinary | 2.333 | 2.501 | +0.168 |
| Poor | 2.118 | 2.421 | +0.303 |
| Bad | 1.889 | 2.314 | +0.425 |
Averaging cancels bias only when the biases differ. Ten identical dice from one bag sharing a manufacturing defect average to exactly the same defect, simulated, and the gain is precisely zero. Use a mixed handful if you can.
The bigger win is speed: ten shakes instead of 99 rolls. Tedium is a real risk: bored people start placing dice by hand. One caveat: shake hard, or faces repeat between readings.
Advice to roll 120 or 150 times circulates, on the theory that extra rolls buy margin against an imperfect die.
With a fair die there is a ceiling. A 24-word seed is 256 bits, and 99 fair rolls already deliver 255.9 of them. Roll 150 times and you feed 388 bits into a hash that can only emit 256, the surplus is discarded.
With a biased die, extra rolls do restore what bias costs, this is worth stating plainly rather than pretending otherwise:
| If your die is | 99 rolls gives | Rolls to reach a full 256 |
|---|---|---|
| Fair | 255.9 bits | 100 |
| 8% biased | 244.9 bits | 104 |
| 20% biased | 229.9 bits | 111 |
| 50% biased, obviously defective | 198.0 bits | 128 |
So the argument against rolling more is not that it does nothing. It is that the thing it buys back is not worth buying: 245 bits against a 100-bit floor. More rolls also means more tedium, and tedium produces the rushed throws that are a far bigger risk than any manufacturing tolerance.
99 is not a floor to exceed for safety; it is the number that fills the seed.
None of the above addresses a different problem: someone who types the same digit fifty times, or an obvious pattern. Implementations differ on whether they try to catch this.
| Implementation | Guard |
|---|---|
| Krux | Live Shannon-entropy meter against the 128/256-bit threshold, arithmetic-pattern detector, distribution graph, all overridable |
| Coldcard | Rejects if any single face exceeds 30% of rolls when generating from dice. No check at all on the path that mixes rolls into an existing seed. |
| Keystone | Warns if any single face exceeds 30% of rolls, but the warning is advisory only and Confirm stays live |
| Seed Tool | Refuses fewer than the minimum roll count |
| SeedSigner, Kern | None beyond enforcing the roll count |
| AirGap Vault | None beyond the 99-roll minimum, plus an explicit refusal to hash an empty string |
| BlueWallet | None, and no minimum either; under-rolling silently tops up from the phone's RNG after a dialog |
| Gordian seedtool-cli | None, it does not enforce a roll count either, and will derive a seed from five rolls |
Where a device checks your rolls at all, it may only do so on the path that generates a seed from dice alone. Coldcard's checks do not run on the path that mixes rolls into a seed it already made, and that is the path popular third-party guides tend to point at. Mixing also costs the property dice were for, which §7 takes up.
Both common approaches, a face-frequency limit and a Shannon-entropy score, measure which faces appeared. Neither sees what order they appeared in.
| What you typed | Shannon | Top face | Coldcard 30% | Compression |
|---|---|---|---|---|
666666… | 0.000 | 100% | caught | caught |
121212… | 1.000 | 50.5% | caught | caught |
123123123… | 1.585 | 33.3% | caught | caught |
123456123456… | 2.584 | 17.2% | passes | caught |
| a real fair sequence | 2.509 | 25.3% | allowed | allowed |
Both scoring approaches share the same gap, they measure which faces appeared, not in what order.
Krux is the exception, and only partly: alongside its Shannon meter it runs a derivative-based check that flags arithmetic progressions, so it catches the row below that the scores alone do not. A face-frequency limit or an entropy score, on its own, does not.
Rolling 1-2-3-4-5-6 repeatedly gives every face its exact fair share, so it scores essentially maximum while being entirely predictable. A compression check sees it, because repetition compresses whether or not the distribution looks uniform.
With only 50 or 99 samples the estimate is far too noisy. At a threshold tuned to falsely warn 1 honest user in 1,000, at 99 rolls a Shannon score catches a die favoring one face 50% more often just 3.9% of the time. A related subtlety: a fair die does not score 2.585.
| Fair-die average | Spread to 0.1st pct | Usable threshold | |
|---|---|---|---|
| 99 rolls | 2.548 | 0.114 bits | 2.434 |
| 50 rolls | 2.511 | 0.235 bits | 2.276 |
Coldcard's fixed 30% threshold shows the same tension from the other side: it falsely warns 3.4% of honest users at 50 rolls, against 0.33% at 99.
This is the detection paradox again, and it resolves itself: these checks miss exactly the biases that don't matter. A roll-quality guard should catch patterned input, not judge your dice. Compression does that better than either approach, with fewer false alarms.
Dice very nearly remove trust from seed generation. Not entirely: no seed produced on a device somebody else built can be perfectly trustless. But what is left over is a narrow and specific residue, not the broad act of faith that “trusting your hardware wallet” usually describes. Once you have tested the device's arithmetic often enough to satisfy yourself, and checked its answer, essentially nothing about the seed itself still rests on the manufacturer's word. How many runs count as enough is a real question, and it is taken up below.
This section is about the residue, and it is deliberately unflattering about it.
When a device shows you 24 words after 99 rolls, it is asserting exactly one thing:
These words are the BIP-39 encoding of SHA-256 over the 99 digits you just entered.
That assertion is falsifiable. There is one correct answer, it does not depend on anything the device knows, and anyone holding the rolls can compute it. If the device produces anything else, it is caught.
The useful consequence is that you can check the device as often as you like, with rolls that protect nothing. Type in fifty arbitrary digits, read the words off the screen, and compute the same thing somewhere else. Then do it again with different digits. The input is throwaway, so this can be done on any computer, connected, carelessly, as many times as your patience allows.
Each pass rules out a little more. A device that returns the expected answer run after run, for inputs it had no way to anticipate, is behaving as a deterministic function of what you typed and nothing else. Enough passes and this device implements the recipe faithfully stops being something you assume about the manufacturer and becomes something you measured yourself.
After enough test runs the device is not something you trust. It is a tool you have checked, running the same arithmetic any other tool runs.
This is the part people miss about dice. The value is not only that one seed can be verified. It is that the device's behavior can be verified, repeatedly and for free, without a single real seed ever leaving the room.
Test runs cannot strictly prove the run that matters, because a device only has to tell the runs apart. The cheapest version of this is to answer honestly the first few times and then defect, which costs an attacker a counter and nothing else. Two or three passes buy you very little. This is the argument for testing more than feels necessary, and for not doing all your testing in one sitting on a fresh device.
Beyond a counter, a device would need some other trigger to pick its moment: a clock, a particular roll pattern, a state it can only be in once. Each is a narrower and stranger thing to build than a device that is simply wrong, and you can narrow it further by making the real run look like all the others.
That residue does not get closed by checking your real seed somewhere else. Doing so opens a larger hole than it fills, for reasons set out below. It is accepted knowingly, in exchange for never entering the real rolls into a second machine at all.
| Question | Why | |
|---|---|---|
| Did the device use my rolls, and only my rolls? | settled | The recipe has no free parameters. There is nowhere to mix in an extra byte without changing every word. |
| Did the device implement the recipe correctly? | settled | A truncation error, a remapped 6, a stray newline: each changes the output completely. |
| Did I enter the rolls I wrote down? | settled | A mistyped digit changes every word. Where the device lets you enter the rolls again, repeating them and comparing catches this without involving a second machine. |
| Is the device's random number generator sound? | not asked | A pure dice seed never touches it. That is the point of the exercise. |
| Are my dice fair? | open | Nothing in the output reveals the physical dice. See §4: the cost of imperfect dice is small enough to ignore. |
| Did the device keep or transmit a copy of my seed? | open | Correctness and confidentiality are unrelated. A device can compute the right answer and still copy it. |
| Will the device sign with the seed it displayed? | open | A separate question, answered by deriving an address independently and comparing. |
| Is the device running the firmware that was published? | open | A separate question, answered by signed releases and reproducible builds. |
A compromised device passes this check. Verification catches a device that lies about your seed. It cannot catch one that computes your seed correctly and also keeps a copy.
Everything protecting you there is separate: no wireless hardware, an air gap you actually maintain, signed firmware, a supply chain you have some reason to believe in, and physical control of the device. Dice make the arithmetic checkable. They do not make the machine trustworthy.
These sound alike, prove very different things, and only one of them is a good idea.
| Testing the device | Checking your real seed elsewhere | |
|---|---|---|
| Input | Throwaway rolls, or the published vectors (§9) | Your actual rolls and your actual words |
| Proves | A property of the device | A property of one event |
| How often | As often as you like | Not recommended at all |
| Cost if the checker is compromised | Nothing. The input was worthless. | Your seed, and everything it holds |
It is the obvious move, and it is a bad trade. To check the seed protecting your funds you have to type your real rolls into another computer, and that computer now knows your seed. You would be exchanging a small residual doubt about a device you have tested for a fresh and unbounded exposure to one you have not.
Working offline does not fix this. An air-gapped machine can still keep what you typed, and you have no way to know what it kept or who reads it later. The risk is not the network, it is the second copy.
This is precisely what test runs are for. They establish the device as a faithful tool using inputs worth nothing, so that the seed that matters is only ever entered once, in one place.
Comparing the device against a second implementation replaces one trusted program with another. That is only progress if the second one is independent and smaller, so it is worth being deliberate about:
Never type dice rolls into a chat prompt. Not real ones, and best not throwaway ones either, so the habit never forms. What you are asking a model for is source code, which you then run yourself on your own machine. It never needs to see a single die.
The distinction is not pedantic. A chat prompt is a network service that transmits, logs and retains. It is the worst place in this entire document to put anything touching a seed, worse than the web tools §3 tells you to download rather than visit. An AI-written checker is only independent because it runs where you are; typed into the chat, the rolls have already left.
And the seed that matters goes into neither. It is entered on the device once, and nowhere else. The checker exists to test the device, using inputs worth nothing.
A model will produce this in seconds and can be fluently, confidently wrong. The specific failure to watch for is that it applies the 6-to-0 remap unprompted, because iancoleman's Dice mode is well represented in training data and looks like the obvious reading of “dice entropy”. It may also reach for a wallet library rather than implementing the specification, which quietly reintroduces the lineage problem you were trying to escape.
So make it earn the role. Have it reproduce the official BIP-39 test vectors
before you show it a single die: a checker that cannot encode a known entropy value correctly
cannot tell you anything about your rolls. Then have it reproduce the vectors in
§9, and cross-check its output against a second implementation such as
Trezor's python-mnemonic.
Validated that way it is a strong extra witness, and a cheap one. Taken on its word it is worse than no check at all, because it will agree with you either way.
Some devices offer to blend your rolls into a seed the device generated, rather than using the rolls alone. The result is then hashed from an input the device chose, so the check described in this section no longer works: you cannot reproduce a seed whose starting value you were never shown.
This is a genuine trade rather than a mistake: mixing protects you if your dice turn out to be terrible, at the cost of the one property that made dice worth using. If you want a verifiable seed, use the dice-only mode.
Not everyone thinks the trade is worth it. Foundation, who make Passport, ship the final-word feature but advise against dice, and their then-head of strategy argued publicly in 2024 that they had heard of zero compromised seeds caused by hardware-wallet RNG failures, against repeated cases of users losing funds to botched dice procedures, one of them having used fewer than ten rolls.
The half about botched procedure stands, and it is the real objection: dice move the risk onto the human, and humans skip steps. The other half was an argument from absence of evidence, and the evidence arrived. On 1 August 2026 Wizardsardine disclosed that Coldcard had shipped a broken entropy path since 2021, across the Mk2, Mk3, Mk4, Mk5 and Q. The defect has been fully verified, wallets were drained at scale, and most of the funds that were exposed are already gone. Coinkite issued emergency firmware on 31 July, which fixes generation from that point on and repairs nothing already generated.
The disclosure draws one exception: seeds generated from 50 or more fair dice rolls were not affected. That is this document's argument, tested against the largest hardware-wallet entropy failure to date and coming through it. A seed the device chose was compromised by a defect its owner had no way to see. A seed its owner rolled was not.
The exception is narrow and worth stating exactly. It covers the seed, not the device. The disclosure is explicit that other features remain broken and that dice rolls do not protect you there.
Generating a seed on any device normally requires trusting it on two counts: that it produced a good secret, and that it kept it. Dice plus verification eliminate the first and leave the second untouched.
Verification proves the device did the right thing. It cannot prove the device did nothing else.
What is left is narrow. Not did this device make a good secret? but did it keep the one I made? That is a single, well-understood question, and it is the one an air-gapped signing device is built to answer: no wireless hardware, no persistent storage, nothing to carry a secret out on. Turning the broad question into that narrow one is the whole benefit on offer, and it is a large benefit. It is simply not the same as zero.
655152231316521321611331544441236164664431121534415633526456254462245546236542364246312613322234612Use the published example above, or rolls of your own that protect nothing. Do not enter the rolls or words of a seed holding real funds into any second tool, offline included. Every copy is another place it can leak from, and an air-gapped machine keeps what you type just as well as a networked one.
Everything worth learning here is learnable from throwaway inputs. See §7.
The goal is a checker you can run, not an answer from a chatbot. Ask it for code, run that code locally, and keep dice rolls out of the conversation entirely. Everything the model needs is in this page already.
1. Implement BIP-39 from the specification, without using any wallet's code or
library, and prove it works by reproducing the official BIP-39 test vectors. Show me
that before going further.
2. Explain how dice rolls become seed entropy in this construction, is the input hashed
as text, or converted numerically?
3. Reproduce the two test vectors in §9 with your implementation, then separately
cross-check them against Trezor's python-mnemonic.
4. Check each implementation listed in §3 against its own source. Do they agree?
5. For each one, determine specifically whether it rewrites a 6 to a 0 before hashing, and show
the line that does or does not.
6. Using min-entropy, compute what a biased die costs a 12- and 24-word seed, and how many rolls
would be needed to detect that bias.
Step 1 is not optional. An unvalidated checker is not a second opinion, it is a second guess. Requiring the official vectors first is what makes the rest of the answer worth anything, and it catches the common failure of a model applying the 6-to-0 remap on its own initiative.
Do not let it answer step 4 with a keyword search. Searching firmware for “dice” case-insensitively drowns in the word indices; searching with word boundaries misses vendors whose dice support lives in a published PDF rather than in code. Require it to read the seed-creation path, the release notes, and the vendor's own documentation, and to say which of the four categories in §3 applies.
Tell it explicitly not to evaluate the result by testing whether the output looks random. Hashing anything produces output that passes randomness tests, so such tests cannot detect a weak seed.
The backing material sits in the repository beside this document, so none of it has to be taken
on description alone. Only verify_constructions.py is standard library only; the rest
need pip install mnemonic embit==0.8.0 in a virtual environment.
| File | What it establishes |
|---|---|
evidence/verify_constructions.py | Standard library only. Reproduces five official BIP-39 vectors as a self-test before asserting anything, then recomputes both vectors in §9, the competing 6-to-0 construction, and the paper-table mapping from the addendum. Run it from evidence/; it reads the wordlist from the working directory. |
evidence/wallet-dice-survey.md | The source reading behind §3 and the addendum, with the pinned commit each classification came from, and the method any further wallet has to be surveyed by. Kern is classified from source but is not yet written up there. |
dice_bias_analysis.py | The min-entropy figures in §4. |
dice_shannon_scoring.py | Why the Shannon-scoring guard discussed in §6 does not catch a bad die. |
dice_tendice_box.py | The ten-dice-in-a-box recommendation evaluated in §4. |
There is no BIP for this. What follows is not a proposal for one. It is a description of what the implementations in §3 already do, written down so it can be checked against them.
INPUT rolls : string of ASCII digits '1'-'6'
len(rolls) == 50 -> 12-word seed
len(rolls) == 99 -> 24-word seed
STEP 1 entropy = SHA256(rolls.encode('ascii')) # 32 bytes
STEP 2 if 12-word: entropy = entropy[0:16] # 128 bits
STEP 3 mnemonic = bip39_encode(entropy) # BIP-39, English
# indices are 0-based: 'abandon' == 0
NOT no 6 -> 0 remap; the digit 6 is hashed as the character '6'
no base-6 or numeric conversion of the roll string
no bit-packing or bias-correction encoding
no separators, padding, or trailing newline in the input
| Value | |
|---|---|
| 50 rolls → 12 words | |
| rolls | 65515223131652132161133154444123616466443112153441 |
| SHA-256 | 6cb09af855050dcde6fe2adc3181c250982011e2cf17821cbed56a908ec527c3 |
| entropy (16 B) | 6cb09af855050dcde6fe2adc3181c250 |
| mnemonic | hole luggage safe present express tragic orbit shed switch metal identify path |
| 99 rolls → 24 words | |
| rolls | 655152231316521321611331544441236164664431121534415633526456254462245546236542364246312613322234612 |
| SHA-256 / entropy | 51531761ec7a738946e0b9f46bb11320a695495430e345c14f01ad8b3b898a6d |
| mnemonic | eyebrow obvious such suggest poet seven breeze blame virtual frown dynamic donor harsh pigeon express broccoli easy apology scatter force recipe shadow claim radio |
A correct implementation reproduces both. If yours does not, the most likely cause is a 6→0 remap or a numeric conversion applied before hashing.
Published analyses of these implementations that we are aware of.
3238f6fd, which is the emergency release of
31 July 2026), run on the headless simulator, logging
every write into the hash accumulator and confirming no RNG is touched. Includes a
deterministic-build proof tying that commit to Coinkite's published signed firmware.
By Portland.HODL.
This list reflects what we know of, not what exists. An implementation missing from it has not been shown to be unreviewed, only that we are unaware of a published analysis. If you know of one, or write one, it belongs here.
We reproduced the trace's figures independently before listing it.
Everything above concerns one construction. This addendum covers the rest of the landscape, for readers checking a specific wallet rather than the recipe itself.
Almost every wallet lets you type in a recovery phrase, so almost every wallet can receive a dice-derived seed you worked out somewhere else. Answering yes on that basis makes the question meaningless. The useful question is what the device itself does, and there are three answers here beyond the recipe above.
This distinction is easy to get wrong, in two specific ways. Searching firmware for dice arithmetic, finding none, and concluding “no dice support” misclassifies BitBox02, Jade and Passport, all of which ship a feature built for hand-rolled seeds while two of the three vendors publish dice instructions themselves.
The second trap is subtler. Reading the seed-generation path, finding a call to the system random number generator, and stopping there misclassifies Sparrow, whose last-word calculator sits on the seed-entry path and whose own documentation describes neither of the two features that put it here. The affordance is not always where the entropy is, and it is not always written down.
These take your rolls and do the arithmetic themselves, but not this arithmetic. Each is internally consistent and none is broken. They simply produce a different wallet from the same rolls, so they cannot be used to check each other.
The most common divergence is a single character. A competing convention rewrites every 6 to a 0 before hashing, so the six faces read as 0 to 5 rather than 1 to 6. That one substitution is not a subtle difference in the result: run the 99-roll example from §2 through both conventions and the two 24-word phrases have no words in common at all. They agree only if you roll no 6 in the entire sequence, which at 99 rolls happens about once in 69 million.
| Implementation | What it does instead | Source |
|---|---|---|
| Keystone Hardware | Rewrites every 6 to 0, then the same SHA-256 and truncation. Deliberately matches iancoleman's Dice mode. | keystone3-firmware @ 3.0.2 (the 24-word gate is gui_model.c L497) |
| BlueWallet Mobile app | No hashing at all. Packs rolls into bits, 0-indexed, and fills any shortfall from the phone's RNG. | BlueWallet @ 8.0.1 |
| iancoleman.io Dice mode only | Rewrites 6 to 0; default sub-mode does not hash at all. | iancoleman/bip39 @ de71c22 |
| AirGap Vault “Coldcard” mode | Rewrites 6 to 0. Coldcard does not do this, so the setting does not do what its name says. | airgap-vault @ aa50b7f |
A setting named after a wallet is not the same as that wallet. AirGap Vault's dice screen offers a mode labeled “Coldcard”. It applies the 6-to-0 rewrite, which Coldcard's firmware does not. Choosing it because you own a Coldcard gives you a seed your Coldcard will never reproduce. Its other mode is the standard recipe.
Matching roll counts prove nothing. The Elixir library RooSoft/bitcoinlib demands exactly 50 or 99 rolls, the recipe's own signature numbers, then reads the digits as a base-6 number and never hashes them. Everything visible from outside matches. The seed does not.
A third group does no dice arithmetic at all, and still deserves to be called dice support. The method is old and needs no firmware: roll dice, look each word up in a printed table, write it down. Anything that accepts a typed recovery phrase can then receive the result.
What makes it practical is the last word. A BIP-39 phrase ends in a checksum, so most word combinations are invalid, and finding a legal final word by hand means testing candidates one at a time. These tools compute it for you, which is the whole reason the feature exists.
A printed table is the usual way to reach the first 23 words, but it is not the only one, and the group is not only hardware. A desktop wallet can offer the same calculation against words you arrived at however you like, which is what puts Sparrow here rather than in the list below.
| Wallet | The final word | Position on dice |
|---|---|---|
| BitBox02 | Shows the 8 valid candidates; you choose | Publishes a dice guide and a 4-page lookup table |
| Blockstream Jade Two D16 and one D8, not six-sided | Shows the valid candidates; you choose | Publishes an article titled Create a recovery phrase using dice |
| Foundation Passport | Picks one itself, using the device's RNG | Documents the feature, but advises against dice |
| Sparrow Desktop software | Autosuggests every checksum-valid candidate as you type the last word, since 1.7.4 | Ships a Border Wallets grid for choosing the first 23 words. No dice screen. Its own docs describe neither feature, and mention dice only to tell you to mix rolls into a Coldcard |
BitBox02's table is the clearest published example of the method. Five dice give 10 bits: you reroll any die showing 5 or 6 until it shows 1 to 4, which makes each die worth exactly 2 bits. A coin flip supplies the eleventh. Twenty-three words later you have 253 bits, and the device supplies the last word.
Jade's published method is not a six-sided one at all. It calls for two
16-sided dice and one 8-sided die, thrown together once per word and read off a lookup table as
(D1−1)×128 + (D2−1)×8 + (D3−1). That covers
16×16×8 = 2048 exactly, so there is no rerolling and no coin flip, and each throw yields
a whole word rather than a partial one. It arrives where BitBox02's method arrives, by different
hardware and different arithmetic. The two are not variants of one scheme, and a transcript from
one means nothing to the other.
The paper-table method never hashes anything, so it does not reproduce the recipe above. A BitBox02 dice transcript does not even contain the digits 5 or 6. The phrase you end up with is ordinary BIP-39 and works in any wallet; it is the route from dice to phrase that does not transfer.
These generate seeds from their own random number generator, and offer nothing for dice beyond the ordinary ability to type in a phrase you produced elsewhere:
Trezor · Ledger · KeepKey · OneKey · Bitkey · Tangem · Cypherock · NGRAVE · Ellipal · SafePal · D’CENT · Satochip · Prokey · SecuX · Arculus · Ballet · Passport Prime · Portal · Frostsnap · Electrum · Nunchuk · Liana · Wasabi · Blockstream Green · Bitcoin Core