Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

diceroll

Generate a BIP39 mnemonic from physical dice rolls. No random number generator is involved anywhere: the 256 bits behind a 24-word seed phrase are exactly the bits that came off the die.

cargo run --release

The method

Throw a six-sided die and read each throw like this:

1 -> 00    2 -> 01    3 -> 10    4 -> 11    5, 6 -> discard, throw again

Faces 5 and 6 are thrown away rather than folded in. That is the whole trick. Each face has probability 1/6, so conditioned on the throw being kept, each of the four outcomes has probability (1/6) / (4/6) = 1/4 exactly — the two bits are uniform and independent by construction.

128 kept throws is 256 bits. Acceptance is 2/3, so expect around 192 physical throws to get there.

Why not base-6 and a hash

A d6 carries log2(6) ≈ 2.585 bits, which is irrational, so no fixed number of rolls lands on a whole number of bits. The common workaround treats the rolls as a base-6 integer and runs SHA-256 over it to compress to 256 bits. That works, but it moves the guarantee: you are now asserting that SHA-256 is a good randomness extractor rather than proving your bits are uniform. Rejection sampling needs no such assertion, and nothing is hashed, stretched, or whitened anywhere between the die and the entropy.

The cost is throws. That is the only thing you trade.

From entropy to words

Standard BIP39: append the first ENT/32 bits of SHA-256(entropy) as a checksum, split into 11-bit groups, index the 2048-word English list. 256 + 8 = 264 bits = 24 words. The checksum catches transcription errors — it is not a security property.

Usage

diceroll [OPTIONS]

  -w, --words <N>     12, 15, 18, 21 or 24            [default: 24]
  -e, --show-entropy  Print the raw entropy in hex
  -v, --verify        Type the mnemonic back after writing it down
  -r, --rolls <S>     Take rolls from the command line (testing only)
  -f, --rolls-file <PATH>  Read rolls from a file
  -h, --help

While entering rolls, type faces as you throw them — several at a time is fine, spacing does not matter. u undoes the last throw, q gives up.

--rolls puts your entropy in shell history. It exists for testing and prints a warning; do not use it for a real seed.

Reading rolls from a file

--rolls-file takes the same digits, from a file instead of the keyboard:

diceroll --rolls-file rolls.txt

Whitespace and newlines are ignored, so one throw per line or one long run both work. # starts a comment to the end of the line, so the file can record which die you used and when. Anything else — a stray letter, a 7 — is an error rather than a skipped character, since silently dropping it would shorten the entropy without saying so. Extra rolls past the target are dropped with a note; too few is an error and no mnemonic is produced. Piping works too — diceroll < rolls.txt — but the flag is clearer and warns about what the file now contains.

See examples/rolls.txt for the format. The words that file produces are public — it is a demonstration, not entropy.

That warning is the point: a roll file is your seed in plaintext, and unlike the words on screen it persists after the process exits. It is worth having when you want to roll away from the machine and transcribe once, or when the machine has no comfortable keyboard. Keep it on tmpfs (/dev/shm, or a container's in-memory mount), on a disk you are about to wipe, and delete it once the words are on paper. Deleting does not scrub the blocks on an SSD.

Fair-die checks

The maths above assumes a fair die. A die that is shaved, loaded, or thrown the same way every time is biased no matter what the extractor does, so the raw throw stream gets two checks:

  • a chi-square over the six faces, which catches a die favouring some faces;
  • a repeat rate, which catches a stream with the right totals but the wrong ordering — the signature of rolls that were invented rather than thrown, since people badly under-produce consecutive repeats.

Both run at p = 0.001 and are advisory. Passing them is not proof of fairness, and a fair die still trips them about once in a thousand runs.

Operational notes

  • Run this offline, on a machine you trust. Treat anything it prints as the key.
  • Rolls and entropy are zeroized on drop; the screen is cleared on exit. Neither helps if the machine is compromised or the terminal is being logged.
  • Write the words on paper, in order, and use --verify to confirm the copy before you rely on it.
  • Use a casino-grade or at least a sharp-edged die. Rounded-corner dice are the usual source of bias.

Tests

cargo test

Covers all 24 official BIP39 vectors in both directions, the uniformity of the extractor, bit-packing, the audit checks, and the end-to-end path from a fixed roll sequence to fixed words. tests/cli.rs drives the built binary over the command-line surface: roll-file parsing, comments, and the refusal paths that must never print a mnemonic — short input, junk input, unreadable files. The embedded wordlist is integrity-checked against its published SHA-256 at first use.

About

Generate a BIP39 mnemonic from physical dice rolls. Rejection sampling, no RNG, nothing hashed between the die and the entropy.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages