11import hashlib
22import os .path
3- from bisect import bisect_right ,bisect_left
4-
5- wordlist_english = list (open (os .path .join (os .path .dirpath (__file__ ),'english.txt' ),'r' ))
3+ from bisect import bisect_left
64
5+ wordlist_english = list (open (os .path .join (os .path .dirpath (os .path .realpath (__file__ )),'english.txt' ),'r' ))
6+ def _eint_to_bytes (entint ,entbits ):
7+ return binascii .unhexlify (hex (entint )[2 :].zfill (entbits // 4 ).rstrip ("L" ))
8+
79def entropy_cs (entbytes ):
810 entropy_size = 8 * len (entbytes )
911 checksum_size = entropy_size // 32
1012 hd = hashlib .sha256 (entbytes ).hexdigest ()
1113 csint = int (hd ,16 ) >> (256 - checksum_size )
1214 return csint ,checksum_size
1315
16+ def mnemonic_int_to_words (mint ,mint_num_words ,wordlist = wordlist_english ):
17+ backwords = [wordlist [(mint >> (11 * x )) & 0x7FF ].strip () for x in range (mint_num_words )]
18+ return backwords [::- 1 ]
19+
1420def entropy_to_words (entbytes ,wordlist = wordlist_english ):
21+ if (len (entbytes ) < 4 | | len (entbytes ) % 4 != 0 ):
22+ raise ValueError ("The size of the entropy must be a multiple of 4 bytes (multiple of 32 bits)" )
1523 entropy_size = 8 * len (entbytes )
1624 csint ,checksum_size = entropy_cs (entbytes )
1725
1826 mint = (entint << checksum_size ) | csint
19- mnemonic_size = (entropy_size + checksum_size )/ 11
20-
21- backwords = [wordlist [(seedint >> (11 * x )) & 0x7FF ].strip () for x in range (seedsize )]
22- return reversed (backwords )
23-
24-
25- #def words_to_seed(words,wordlist=wordlist_english):
27+ mint_num_words = (entropy_size + checksum_size )// 11
2628
29+ return mnemonic_int_to_words (mint ,mint_num_words ,wordlist )
2730
2831def words_bisect (word ,wordlist = wordlist_english ):
2932 lo = bisect_left (wordlist ,word )
30- hi = lo
31- lw = len (word )
32- while (wordlist [hi ][:lw ]== word ):
33- hi += 1
33+ hi = len (wordlist )- bisect_left (wordlist [:lo :- 1 ],word )
3434
3535 return lo ,hi
3636
3737def words_split (wordstr ,wordlist = wordlist_english ):
3838 def popword (wordstr ,wordlist ):
3939 for fwl in range (1 ,9 ):
40- w = wordstr [:fwl ]
40+ w = wordstr [:fwl ]. strip ()
4141 lo ,hi = words_bisect (w ,wordlist )
4242 if (hi - lo == 1 ):
43- return w ,wordstr [fwl :]
43+ return w ,wordstr [fwl :]. lstrip ()
4444 wordlist = wordlist [lo :hi ]
4545 raise Exception ("Wordstr %s not found in list" % (w ))
4646
@@ -51,7 +51,33 @@ def popword(wordstr,wordlist):
5151 words .append (head )
5252 return words
5353
54- def words_verify (words ):
55- pass
56- #if words in string, split them first.
54+ def words_to_mnemonic_int (words ,wordlist = wordlist_english ):
55+ if (instance (words ,str )):
56+ words = words_split (words ,wordlist )
57+ return sum ([wordlist .index (w ) << (11 * x ) for x ,w in enumerate (words [::- 1 ])])
58+
59+ def words_verify (words ,wordlist = wordlist_english ):
60+ if (isinstance (words ,str )):
61+ words = words_split (words ,wordlist )
5762
63+ mint = words_to_mnemonic_int (words ,wordlist )
64+ mint_bits = len (words )* 11
65+ cs_bits = mint_bits // 32
66+ entropy_bits = mint_bits - cs_bits
67+ eint = mint >> cs_bits
68+ csint = mint & ((1 << cs_bits )- 1 )
69+ ebytes = _eint_to_bytes (eint ,entropy_bits )
70+ return csint == entropy_cs (ebytes )
71+
72+ def mnemonic_to_seed (mnemonic_phrase ,passphrase = "" ):
73+ try :
74+ from hashlib import pbkdf2_hmac
75+ def pbkdf2_hmac_sha256 (password ,salt ,iters = 2048 ):
76+ return pbkdf2_hmac (name = 'sha512' ,password = password ,salt = salt ,iters )
77+ except :
78+ from Crypto .Protocol .KDF import PBKDF2
79+ from Crypto .Hash import SHA512 ,HMAC
80+
81+ def pbkdf2_hmac_sha256 (password ,salt ,iters = 2048 ):
82+ return PBKDF2 (password = password ,salt = salt ,dkLen = 64 ,count = iters ,prf :lambda p ,s : HMAC .new (p ,s ,SHA512 ).digest ())
83+ return pbkdf2_hmac_sha256 (password = mnemonic_phrase ,salt = "mnemonic" + passphrase )
0 commit comments