forked from crypdex/passport-wallet
-
Notifications
You must be signed in to change notification settings - Fork 0
/
common.py
151 lines (108 loc) · 3.27 KB
/
common.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
from subprocess import Popen, PIPE
# log
import logging
logging.basicConfig(format='%(asctime)-15s %(levelname)s %(message)s', level=logging.INFO)
logger = logging.getLogger(__name__)
# config
default_background = './images/passport-background-lines.png'
salt_length_words = 3
scrypt_N = 4096
scrypt_r = 8
scrypt_p = 1
# execute shell command
def cmd(str):
logging.debug('$ ' + ' '.join(str))
process = Popen(str, stderr=PIPE, stdout=PIPE)
outdata, errdata = process.communicate()
if len(outdata.strip()) > 0:
logging.debug('STDOUT: ' + outdata)
if len(errdata.strip()) > 0:
logging.debug('STDERR: ' + errdata)
if (process.returncode):
exit(1)
# add line breaks to a string
def break_string(string, width):
return (string[0+i:width+i] for i in range(0, len(string), width))
# validate integer type
def integer(val):
try:
return int(val)
except:
msg = '{} is not an integer'.format(val)
raise argparse.ArgumentTypeError(msg)
# validate positive integer
def positive_integer(val):
if (integer(val) and val > 0):
return val
else:
msg = '{} is not positive'.format(val)
raise argparse.ArgumentTypeError(msg)
# extract item from lists of size 1
def unwrap(obj):
if isinstance(obj, list) and len(obj) == 1:
(extracted,) = obj
return extracted
else:
return obj
# add spaces to string s until its length is a multiple of m
def pad(s, m):
pad_length = m - (len(s) % m)
spaces = ' ' * pad_length
return s + spaces
# convert byte array into 11-bit BIP39 words
def bytes2words(b):
i = 0
indexes = []
word_cursor = 0
word_value = 0
# prepend array length in first byte
if len(b) > 255:
raise ValueError('byte array too large')
b = chr(len(b)) + b
for x in b:
byte = ord(x)
for bit in range(8):
if (i-word_cursor) >= 11:
indexes.append(word_value)
word_cursor = i
word_value = 0
if byte & 2**bit:
word_value += int(2**(i-word_cursor))
i += 1
indexes.append(word_value)
# load bip39 wordlist
bip39 = []
with open('words-bip39.csv') as fp:
bip39 = fp.readlines()
bip39 = [ b.strip() for b in bip39 ]
# convert 11-bit chunks to BIP39 english word
words = [ bip39[i].strip() for i in indexes ]
return words
def words2bytes(words):
# load bip39 wordlist
bip39 = []
with open('words-bip39.csv') as fp:
bip39 = fp.readlines()
bip39 = [ b.strip() for b in bip39 ]
# map words to 11 bit integers
indexes = [bip39.index(word) for word in words]
# convert to 8-bit array
i = 0
byte_array = ''
byte_cursor = 0
byte_value = 0
for index in indexes:
for bit in range(11):
if (i - byte_cursor) >= 8:
byte_array += chr(byte_value)
byte_cursor = i
byte_value = 0
if index & 2**bit:
byte_value += int(2**(i-byte_cursor))
i += 1
byte_array += chr(byte_value)
# clip to original length
blen = ord(byte_array[0])
return byte_array[1:blen+1]
def pluralize(n):
return '' if n == 1 else 's'