Skip to content

Commit 66841dc

Browse files
committed
bip39 dice wip
1 parent b568fdd commit 66841dc

File tree

4 files changed

+40
-18
lines changed

4 files changed

+40
-18
lines changed

pub/functora-hakyll/blog/2025-09-16-secure-bitcoin-seed.markdown

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ Because of how important your Bitcoin seed is, we cannot afford to take any risk
2020

2121
### Tools
2222

23-
1. A good non-digital source of randomness. Coin is acceptable, but casino-grade dice is better.
23+
1. A good non-digital source of randomness. A coin is acceptable, but casino-grade dice are better. You need a dice with an even number of sides.
2424
2. A printed BIP39 dice [calculator](/bip39/calculator.html).
2525
3. A printed BIP39 indexed [wordlist](/bip39/wordlist.html). Do not trust me. Verify the [script](https://github.com/functora/functora.github.io/blob/master/nix/bip39-wordlist.nix) and generate your own wordlist.
2626
4. A pen or pencil.
@@ -31,3 +31,13 @@ Because of how important your Bitcoin seed is, we cannot afford to take any risk
3131
### 1st-23th words
3232

3333
This is the main source of your seed entropy. When performing this step, or working with your seed at any point, it is absolutely essential to ensure there are no phones, laptops, cameras, or other devices in sight, and that no one is watching. For maximum security, choose a private room with no electronic devices present, close all doors and windows, and use only dice, paper, pen, and (optionally) a pocket calculator.
34+
35+
The BIP39 wordlist contains 2048 words. To randomly select one of them, you need exactly 11 bits of randomness, since 2<sup>11</sup> = 2048. For each of the first 23 words, repeat the following procedure:
36+
37+
1. Flip a coin 11 times or roll the dice 11 times.
38+
- Coin: heads = 0 bit, tails = 1 bit
39+
- Dice: even side = 0 bit, odd side = 1 bit
40+
2. On the printed BIP39 dice calculator, for each of the 11 bits in the word column, cross out the corresponding number if the bit value is 0, or circle the corresponding number if the bit value is 1.
41+
3. Calculate the sum of all circled numbers in the word column. Ignore the crossed-out numbers.
42+
4. Add 1 to the sum because the BIP39 wordlist is indexed starting at 1 (not 0). The resulting number is the index of the word in the BIP39 wordlist.
43+
5. Write down the corresponding BIP39 seed word, which you can find by its index in the printed BIP39 indexed wordlist.

pub/functora-hakyll/site.hs

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -85,9 +85,10 @@ main = withUtf8 . hakyllWith cfg $ do
8585
( field "idx" (pure . itemBody)
8686
<> defCtx
8787
)
88-
( mapM
89-
(makeItem . ("\8470" <>) . show)
90-
items
88+
( do
89+
xs <- mapM (makeItem . ("\8470" <>) . show) items
90+
x <- makeItem mempty
91+
pure $ x : xs
9192
)
9293
let rows top label =
9394
listField
@@ -97,19 +98,28 @@ main = withUtf8 . hakyllWith cfg $ do
9798
(field "col" (pure . itemBody))
9899
( \item -> do
99100
let (idx, raw) = itemBody item
100-
let mkItem = makeItem raw
101-
xs <- replicateM 11 mkItem
102-
x <-
103-
if top || idx > 8
104-
then mkItem
105-
else makeItem mempty
106-
pure $ xs <> [x]
101+
h <-
102+
makeItem . (\x -> "<b>" <> x <> "</b>") $
103+
if idx <= 11
104+
then "bit " <> show idx
105+
else raw
106+
xs <-
107+
replicateM 11 . makeItem $
108+
if idx <= 11
109+
then raw
110+
else mempty
111+
t <-
112+
makeItem $
113+
if (top || idx < 4) && idx <= 11
114+
then raw
115+
else mempty
116+
pure $ [h] <> xs <> [t]
107117
)
108118
)
109119
( mapM makeItem
110120
. zip [1 ..]
111-
. (<> ["\8721+1=", "W="])
112-
$ fmap (show . (2 ^)) [10, 9 .. 0]
121+
. (<> ["sum=", "sum+1=", "word="])
122+
$ fmap (show . (2 ^)) [0 .. 10]
113123
)
114124
let ctx =
115125
idxs [1 .. 12] "idxs-top"

pub/functora-hakyll/templates/bip39-dice-calculator.html

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,33 +2,34 @@
22
<thead>
33
<tr>
44
$for(idxs-top)$
5-
<th>$idx$</th>
5+
<th style="padding-right: 0.6em">$idx$</th>
66
$endfor$
77
</tr>
88
</thead>
99
<tbody>
1010
$for(rows-top)$
1111
<tr>
1212
$for(cols)$
13-
<td>$col$</td>
13+
<td style="padding-right: 0.6em">$col$</td>
1414
$endfor$
1515
</tr>
1616
$endfor$
1717
</tbody>
1818
<thead>
1919
<tr>
2020
$for(idxs-bottom)$
21-
<th>$idx$</th>
21+
<th style="padding-right: 0.6em">$idx$</th>
2222
$endfor$
2323
</tr>
2424
</thead>
2525
<tbody>
2626
$for(rows-bottom)$
2727
<tr>
2828
$for(cols)$
29-
<td>$col$</td>
29+
<td style="padding-right: 0.6em">$col$</td>
3030
$endfor$
3131
</tr>
3232
$endfor$
3333
</tbody>
3434
</table>
35+
<div style="padding-top: 55px"></div>

pub/functora-hakyll/templates/default.html

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,9 @@ <h2 class="racing-font">Fn</h2>
6565
</nav>
6666
$endif$ $if(index)$ $body$ $else$
6767
<div class="content page">
68+
$if(formal)$ $else$
6869
<h2 class="text-center">$title$</h2>
69-
$body$
70+
$endif$ $body$
7071
</div>
7172
$endif$
7273
</body>

0 commit comments

Comments
 (0)