-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.py
158 lines (122 loc) · 5.29 KB
/
main.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
from hashlib import sha256
import binascii
import itertools
def get_bip39_words_list():
lines = None
# downloaded from https://github.com/raw/bitcoin/bips/master/bip-0039/english.txt
with open('./english.txt') as file:
lines = [line.rstrip() for line in file]
assert(len(lines) == 2048)
return lines
def checksum_chars_to_add(seed_len):
chars_for_checksum = None
if seed_len == 12:
chars_for_checksum = 1
elif seed_len == 24:
chars_for_checksum = 2
return chars_for_checksum
def bits_to_add(seed_len):
chars_for_checksum = None
if seed_len == 12:
chars_for_checksum = 7
elif seed_len == 24:
chars_for_checksum = 3
return chars_for_checksum
def handle_one_pad(bip39_words_list, num_added_pads):
while True:
try:
msg = '\nYou added already {} pads. Insert all the words of another pad or 0 to stop: '
f_msg = msg.format(num_added_pads)
seed_string = input(f_msg).lower()
except KeyboardInterrupt:
quit()
if seed_string == '0':
return False
# convert string to list
seed_list = seed_string.split(' ')
# remove eventual whitespaces in list
seed_list = [word for word in seed_list if word]
# check if all words are in bip39 list
all_words_in_bip39_list = True
for word in seed_list:
if word not in bip39_words_list:
all_words_in_bip39_list = False
print('\n!! ERROR: word {} not in bip39 words list'.format(word))
# prevent going ahead if not all words in bip39 list
if not all_words_in_bip39_list:
continue
# check that words inserted must be 12 or 24
if len(seed_list) != 12 and len(seed_list) != 24:
print('\n!! ERROR: {} words inserted'.format(len(seed_list)))
continue
break
whole_mnemonic = seed_list.copy()
last_word = seed_list.pop()
bits_string = ''
for word in seed_list:
decimal_index = bip39_words_list.index(word)
binary_index = bin(decimal_index)[2:].zfill(11)
bits_string += binary_index
combos = itertools.product(['0', '1'], repeat=bits_to_add(len(whole_mnemonic)))
combos = [ ''.join(list(i)) for i in combos]
combos = sorted(combos, key=lambda x: int(x, 2))
last_word_bits = None
for combo in combos:
entropy = '{}{}'.format(bits_string, combo)
hexstr = "{0:0>4X}".format(int(entropy,2)).zfill(int(len(entropy)/4))
data = binascii.a2b_hex(hexstr)
hs = sha256(data).hexdigest()
last_bits = ''.join([ str(bin(int(hs[i], 16))[2:].zfill(4)) for i in range(0, checksum_chars_to_add(len(whole_mnemonic))) ])
last_word_bin = '{}{}'.format(combo, last_bits)
word = bip39_words_list[int(last_word_bin, 2)]
if (word == last_word):
last_word_bits = combo
return {
'mnemonic': whole_mnemonic,
'bits_string': bits_string+last_word_bits
}
def main():
print('\n\nSEED XOR CALCULATOR\n\n')
bip39_words_list = get_bip39_words_list()
added_pads = []
while True:
pad = handle_one_pad(bip39_words_list, len(added_pads))
# he stopped adding pads
if pad is False:
# at least 2 pads are required
if len(added_pads) < 2:
print('\n!! ERROR: At least 2 pads are required. You added {} pads'.format(len(added_pads)))
continue
print('\nPads completed! I will calculate the XOR seed...')
break
else:
# following pads should have the same amount of words of the first one
if len(added_pads) > 0 and len(pad['mnemonic']) != len(added_pads[0]['mnemonic']):
msg = '\n!! ERROR: first pad added has {} words. All the following ones should have the same amount of words'
f_msg = msg.format(len(added_pads[0]['mnemonic']))
print(f_msg)
continue
added_pads.append(pad)
print('\nCalculating... You inserted these pads:')
for idx, pad in enumerate(added_pads):
print('\n{}) {}'.format(idx+1, ' '.join(pad['mnemonic'])))
xor = None
for i in range(0, len(added_pads)-1):
if i == 0:
xor = added_pads[0]['bits_string']
str1 = xor
str2 = added_pads[i+1]['bits_string']
xor = ''.join([str(ord(a) ^ ord(b)) for a,b in zip(str1, str2)])
entropy = xor
hexstr = "{0:0>4X}".format(int(entropy,2)).zfill(int(len(entropy)/4))
data = binascii.a2b_hex(hexstr)
hs = sha256(data).hexdigest()
chars_for_checksum = checksum_chars_to_add(len(added_pads[0]['mnemonic']))
last_bits = ''.join([ str(bin(int(hs[i], 16))[2:].zfill(4)) for i in range(0, chars_for_checksum) ])
entropy += last_bits
bits_per_word = 11
splitted = [entropy[i:i+bits_per_word] for i in range(0, len(entropy), bits_per_word)]
words = [ bip39_words_list[int(i, 2)] for i in splitted ]
print('\nXOR SEED CALCULATED:\n\n{}\n'.format(' '.join(words)))
if __name__ == "__main__":
main()