Generating BIP-39 seeds with maximum verifiable assurance.
BIP-39 24-word mnemonics require 256 bits of entropy plus an 8-bit checksum (derived via SHA-256), totaling 264 bits. The d8 produces exactly 3 bits per roll because 8 = 23. Every 3-bit pattern (000–111) maps to one face with exactly equal probability.
The d8 is the only Platonic solid that simultaneously satisfies three properties:
d4 has power-of-2 faces but does not roll (it sticks or lands). d6, d12, d20 do not have power-of-2 faces and introduce modulo bias. d8 is the unique intersection of all three properties.
Roll count. Two valid approaches exist. The canonical method uses 86 rolls (258 bits: 256 entropy + 8 rolled checksum). A manual-worksheet variant uses 88 rolls (264 bits: 256 entropy + 8 discarded, checksum computed by tool). Both produce identical security. This guide uses 86 rolls.
Materials. One d8 dice. Pen and paper. A SHA-256 calculator (offline: sha256sum, Python, or a hardware wallet).
Binary conversion. Each roll maps to 3 bits:
| Roll | Binary | Roll | Binary |
|---|---|---|---|
| 1 | 000 | 5 | 100 |
| 2 | 001 | 6 | 101 |
| 3 | 010 | 7 | 110 |
| 4 | 011 | 8 | 111 |
Steps.
Python implementation:
import hashlib
ROLLS_REQUIRED = 86
rolls = []
for i in range(ROLLS_REQUIRED):
while True:
try:
roll = int(input(f"Roll {i+1:2d}: ").strip())
if 1 <= roll <= 8:
rolls.append(roll)
break
print(" Enter 1-8")
except ValueError:
print(" Enter a number")
bits = ''.join(format(r - 1, '03b') for r in rolls)
entropy_bits = bits[:256]
checksum_bits = bits[256:264]
entropy_bytes = int(entropy_bits, 2).to_bytes(32, 'big')
actual = format(int.from_bytes(hashlib.sha256(entropy_bytes).digest(), 'big'), '0256b')[:8]
if checksum_bits != actual:
print(f"Checksum mismatch. Rolled: {checksum_bits}, Computed: {actual}")
print("Using computed checksum.")
checksum_bits = actual
mnemonic_bits = entropy_bits + checksum_bits
print(f"264 bits ready for wordlist lookup.")
Before trusting any dice for seed generation, verify it empirically. Manufacturing defects, material voids, and engraving asymmetry create bias that does not average out.
Quick test: 500 rolls (5 minutes). Catches gross defects — bubbles, severe weighting, missing faces.
Pass criterion: χ² < 14.07 (p > 0.05). If the dice fails this test, stop — it is unusable for seeds.
from collections import Counter
rolls = []
print("Roll d8 500 times. Enter each (1-8).")
try:
while len(rolls) < 500:
r = int(input(f"{len(rolls)+1:3d}: ").strip())
if 1 <= r <= 8:
rolls.append(r)
except KeyboardInterrupt:
pass
n = len(rolls)
counts = Counter(rolls)
expected = n / 8
chi2 = sum((counts.get(i, 0) - expected)**2 / expected for i in range(1, 9))
print(f"n={n}, chi2={chi2:.2f}")
if chi2 < 14.07: print("PASS (p > 0.05)")
elif chi2 < 18.48: print("MARGINAL (p < 0.05)")
else: print("FAIL (p < 0.01)")
Full verification: 10,000 rolls (2 hours). Quantifies actual εrms and entropy loss for your specific dice. Gold standard for dice verification.
Pass criterion: projected loss for 86 rolls < 0.5 bits. The verification script computes χ², εrms, Shannon entropy, and min-entropy, then saves results to a JSON audit file.
Re-testing schedule: full 10k before first seed generation; quick 500 after dropping the dice on a hard surface; full 10k after every 100 seed generations (wear check).
The Dice Entropy Test tool provides a live version of these metrics for quick testing.
Before rolling, inspect the dice physically. If any check fails, do not proceed to the roll test.
| Check | Method | Pass Criteria |
|---|---|---|
| Face flatness | Optical flat + monochromatic light | < 3 fringes (~1.5 μm) |
| Edge sharpness | 10× loupe / fingernail catch | No visible rounding, crisp arris |
| Vertex symmetry | 10× loupe | All 6 vertices identical |
| Engraving depth | Visual / caliper | Uniform, < 0.1mm, balanced pattern |
| Mass balance | Spin on glass plate | No preferred stopping orientation |
| Dimensions | Digital caliper | All 12 edges equal ±0.02mm |
| Bubbles / voids | Bright backlight | None visible |
| Material homogeneity | Density (Archimedes) | Within 0.5% of theoretical |
Rolling protocol. Use casino felt or a neoprene mat (3–5mm). Throw from 20–30cm above the surface. Shake 3 seconds in cupped hands, release with spin. Vary the starting face deliberately. Take a 5-minute break every 1,000 rolls. Do not roll on glass, wood, carpet, or a bare table.
The quality of your dice determines the entropy you actually extract. The table below maps budget to expected performance. These are starting points for your own evaluation, not prescriptions.
| Budget | Material | εrms | Loss (86 rolls) | Tradeoffs |
|---|---|---|---|---|
| < $5 | Cheap plastic | ~0.03 | ~0.31 bits | Air bubbles, rounded edges common. Know what you’re accepting. |
| $5 – $15 | Good resin | ~0.01 | ~0.03 bits | Sharp edges, no visible bubbles. Acceptable for most use cases. |
| $20 – $50 | Casino-grade | ~0.003 | ~0.003 bits | GameScience, Chessex precision. Documented manufacturing. |
| $50 – $150 | CNC brass / aluminum | ~0.001 | ~0.0003 bits | 3-axis CNC, 4 setups. Face flatness <3μm, edge radius <5μm. |
The jump from cheap plastic to good resin is the most cost-effective. Beyond casino-grade, diminishing returns set in — the difference between 0.003 and 0.001 bits of loss per 86 rolls is negligible for most threat models.
What level of verification satisfies your use case is a personal question. A $10 resin dice that passes a 10,000-roll verification may serve you better than a $100 brass dice that has not been tested.
The d8 is one of the easiest Platonic solids to manufacture precisely. Its 8 equilateral triangle faces require only 4 CNC setups at 54.7° indexing angles. By comparison, a d20 requires 20+ setups or 5-axis simultaneous machining at 10–20× the cost.
Home shop feasibility: a drill press with a rotary table can produce a functional d8. Precision is limited (~0.5% face area error), but sufficient for testing and learning. A benchtop 3-axis CNC achieves ~0.05% error — indistinguishable from commercial dice for entropy purposes.
Material choice for DIY: Delrin (acetal) machines cleanly and is forgiving. Aluminum 6061 is excellent for final pieces. Brass 360 is dense (good feel) and free-machining. Cost per unit at small batch: CNC Delrin $18, CNC Aluminum $30, CNC Brass $45.
The “perfect dice” specification for maximum assurance: brass 360, 3-axis CNC, 4 setups, face flatness <3μm, edge radius <5μm, laser-engraved numbers, mirror polish (Ra < 0.1μm). Estimated cost: $75–150 each in small quantity, ~$500 one-time setup.
Why this matters: the d8 is the only Platonic solid where geometry, manufacturing, and entropy math all align. You can build a near-perfect dice in a home shop for under $50 in materials.
Record every seed generation. The audit proves you used a verified dice and followed the protocol.
{
"generation_date": "2026-08-01T14:30:00Z",
"die_id": "brass_d8_001",
"die_verification": {
"date": "2026-07-15T10:00:00Z",
"rolls": 10000,
"eps_rms": 0.0012,
"projected_loss_86": 0.0004,
"passes": true
},
"rolls": [3, 7, 1, 8, 2, 4, 6, 5, ...],
"roll_count": 86,
"entropy_bits": "010110111000...",
"checksum_verified": true,
"mnemonic": "abandon ability able ..."
}
The roll count = 86 is the proof of completion. The dice verification record proves the dice was tested. Together, they form a complete audit trail that anyone can verify in seconds.
d6 (when d8 is unavailable). Roll d6 99 times. Use rejection sampling: accept 1–4 (2 bits), reject 5–6, re-roll. Expected rolls: ~128. Bias: 0% with correct rejection, ~17% with modulo. The d6 is ubiquitous but carries 48% more rolls and requires rejection logic.
d20 (limited scenarios). Roll d20, accept 1–16 (4 bits), reject 17–20. Expected rolls: ~80, but the actual count varies (typically 75–95). Bias amplification: 2.5× that of d8. The variable roll count makes the process unauditable without a complete log. Only consider with a verified casino d20 (10,000+ test rolls, εrms < 0.001) and an automated roller with logging.
Electronic RNG (for practice, not audit). secrets.token_bytes(32) produces instant, zero-bias entropy. The limitation is trust: a third party cannot verify the process without access to the RNG. Useful for daily keys and testing.
Each alternative has properties that may suit your situation. The Dice Entropy article provides the comparative data to evaluate them.