26
26
27
27
from unicodedata import normalize
28
28
import hashlib
29
- import binascii
29
+ from typing import Tuple
30
30
31
31
from . import bitcoin , ecc , constants , bip32
32
32
from .bitcoin import (deserialize_privkey , serialize_privkey ,
@@ -601,14 +601,15 @@ def bip39_to_seed(mnemonic, passphrase):
601
601
return hashlib .pbkdf2_hmac ('sha512' , mnemonic .encode ('utf-8' ),
602
602
b'mnemonic' + passphrase .encode ('utf-8' ), iterations = PBKDF2_ROUNDS )
603
603
604
- # returns tuple (is_checksum_valid, is_wordlist_valid)
605
- def bip39_is_checksum_valid (mnemonic ):
604
+
605
+ def bip39_is_checksum_valid (mnemonic : str ) -> Tuple [bool , bool ]:
606
+ """Test checksum of bip39 mnemonic assuming English wordlist.
607
+ Returns tuple (is_checksum_valid, is_wordlist_valid)
608
+ """
606
609
words = [ normalize ('NFKD' , word ) for word in mnemonic .split () ]
607
610
words_len = len (words )
608
611
wordlist = load_wordlist ("english.txt" )
609
612
n = len (wordlist )
610
- checksum_length = 11 * words_len // 33
611
- entropy_length = 32 * checksum_length
612
613
i = 0
613
614
words .reverse ()
614
615
while words :
@@ -620,13 +621,12 @@ def bip39_is_checksum_valid(mnemonic):
620
621
i = i * n + k
621
622
if words_len not in [12 , 15 , 18 , 21 , 24 ]:
622
623
return False , True
624
+ checksum_length = 11 * words_len // 33 # num bits
625
+ entropy_length = 32 * checksum_length # num bits
623
626
entropy = i >> checksum_length
624
627
checksum = i % 2 ** checksum_length
625
- h = '{:x}' .format (entropy )
626
- while len (h ) < entropy_length / 4 :
627
- h = '0' + h
628
- b = bytearray .fromhex (h )
629
- hashed = int (binascii .hexlify (sha256 (b )), 16 )
628
+ entropy_bytes = int .to_bytes (entropy , length = entropy_length // 8 , byteorder = "big" )
629
+ hashed = int .from_bytes (sha256 (entropy_bytes ), byteorder = "big" )
630
630
calculated_checksum = hashed >> (256 - checksum_length )
631
631
return checksum == calculated_checksum , True
632
632
0 commit comments