Trying to convert hexadecimal string of entropy to seed sentence with the below snippet. Failing the first test with 16 zero bytes. It seems that my function came to conclusion that checksum is '1011' yet it should by '0011' (by this page for instance) therefore I do have a mistake in seed sentence where my last word is on index 13 (accuse) and correct word is on index 3 (about). What is broken in my function? Also, there is not much of an implementation details in bip39, if you know about some resources (not just core codebase) they'd be warmly welcome!
import hashlib
import requests
import unicodedata
def get_word_list():
url = "https://raw.githubusercontent.com/"
uri = "bitcoin/bips/master/bip-0039/english.txt"
return requests.get(url + uri).text.split()
def checksum_length(entropy_bits: int) -> int:
return int(entropy_bits / 32)
def mnemonic_from_entropy(entropy: str) -> str:
word_list = get_word_list()
entropy_bits = len(entropy) * 4
entropy_bytes = bytes.fromhex(entropy)
print(entropy_bytes.hex())
entropy_int = int.from_bytes(entropy_bytes, byteorder="big")
sha256_entropy_bytes = hashlib.sha256(entropy_bytes).digest()
sha256_entropy_int = int.from_bytes(sha256_entropy_bytes, "big")
checksum_bit_length = checksum_length(entropy_bits=entropy_bits)
checksum = bin(sha256_entropy_int)[2:2 + checksum_bit_length]
entropy_checksum = bin(entropy_int)[2:] + checksum
entropy_checksum = entropy_checksum.zfill(entropy_bits + checksum_bit_length)
bin_indexes = re.findall("." * 11, entropy_checksum)
indexes = [int(index, 2) for index in bin_indexes]
mnemonic_lst = [word_list[index] for index in indexes]
mnemonic_sentence = unicodedata.normalize("NFKD", " ".join(mnemonic_lst))
return mnemonic_sentence
if __name__ == "__main__":
mnemonic_from_entropy("00000000000000000000000000000000")
abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about
– skaht Mar 6 '20 at 18:58