Skip to content

Commit 7d28a3b

Browse files
committed
release bitcoin seed security blog post
1 parent e696a2c commit 7d28a3b

13 files changed

+5344
-51
lines changed

.github/workflows/pages.yml

Lines changed: 0 additions & 39 deletions
This file was deleted.

docs/bip39/24th-word-calculator.py

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import os
2+
import sys
3+
import hashlib
4+
5+
class Bip39Check(object):
6+
def __init__(self, language):
7+
self.radix = 2048
8+
self.worddict = {}
9+
self.wordlist = []
10+
11+
counter = 0
12+
13+
with open('%s/%s.txt' % (self._get_directory(), language), 'r') as file:
14+
for w in file.readlines():
15+
word = w.strip() if sys.version < '3' else w.strip()
16+
self.worddict[word] = counter
17+
self.wordlist.append(word)
18+
counter = counter + 1
19+
20+
if(len(self.worddict) != self.radix):
21+
raise ValueError('Expecting %d words, not %d', self.radix, len(self.worddict))
22+
23+
@classmethod
24+
def _get_directory(cls):
25+
return os.path.dirname(__file__)
26+
27+
def _check_size(self, phrase):
28+
self.size = len(phrase) + 1
29+
if (self.size % 3 != 0):
30+
raise ValueError('Expecting 11 or 23 words')
31+
32+
def _compute_entropy(self, phrase):
33+
self.entropy = 0
34+
for w in phrase:
35+
idx = self.worddict[w]
36+
self.entropy = (self.entropy << 11) + idx
37+
return self.entropy
38+
39+
def _scan(self):
40+
checksum_bits = self.size // 3
41+
entropy_size = (self.size * 11 - checksum_bits) // 8 # Fixed entropy string length
42+
entropy_to_fill = 11 - checksum_bits
43+
entropy_base = self.entropy << (entropy_to_fill)
44+
45+
for i in range(0, 2 ** entropy_to_fill):
46+
entropy_candidate = entropy_base | i
47+
entropy_str = (entropy_candidate).to_bytes(entropy_size, 'big')
48+
hash = (hashlib.sha256(entropy_str).digest()[0])
49+
checksum = hash >> (8 - checksum_bits)
50+
final_word_idx = (i << checksum_bits) + checksum
51+
checkword = self.wordlist[final_word_idx]
52+
print (checkword)
53+
54+
55+
def main():
56+
m = Bip39Check('english')
57+
print("Enter the 23 words: ")
58+
phrase = sys.stdin.readline().split()
59+
m._check_size(phrase)
60+
m._compute_entropy(phrase)
61+
print("___________________________\nThese are your 8 candidate words, select any one of these for the 24th word.\n")
62+
m._scan()
63+
64+
if __name__ == '__main__':
65+
main()

0 commit comments

Comments
 (0)