From f5cb0bb89a2e00b56fe743043c919eb83205bb66 Mon Sep 17 00:00:00 2001 From: Alexey Karyabkin Date: Mon, 4 Jun 2018 16:03:58 +0400 Subject: [PATCH] move functions bip0039 to hdwallet.py --- pybtc/hdwallet.py | 78 +++++++++++++++++++++++++++++++++++++++++++++++ pybtc/tools.py | 67 ---------------------------------------- 2 files changed, 78 insertions(+), 67 deletions(-) create mode 100644 pybtc/hdwallet.py diff --git a/pybtc/hdwallet.py b/pybtc/hdwallet.py new file mode 100644 index 0000000..54d0383 --- /dev/null +++ b/pybtc/hdwallet.py @@ -0,0 +1,78 @@ +import os +import hashlib + +from binascii import hexlify, unhexlify +from .constants import * + + +# BIP39 +# +# +# + +def create_passphrase(bits=256, language='english'): + entropy = os.urandom(bits // 8) + mnemonic = create_mnemonic(entropy, language) + return ' '.join(mnemonic[::-1]) + + +def create_mnemonic(entropy, language='english'): + mnemonic = [] + wordlist = create_wordlist(language) + entropy_int = int.from_bytes(entropy, byteorder="big") + entropy_bit_len = len(entropy) * 8 + chk_sum_bit_len = entropy_bit_len // 32 + entropy_hash = hashlib.sha256(entropy).hexdigest() + fbyte_hash = unhexlify(entropy_hash)[0] + entropy_int = add_checksum(entropy) + while entropy_int: + mnemonic.append(wordlist[entropy_int & 0b11111111111]) + entropy_int = entropy_int >> 11 + return mnemonic[::-1] + + +def create_wordlist(language, wordlist_dir=BIP0039_DIR): + f = None + path = os.path.join(wordlist_dir, '.'.join((language, 'txt'))) + assert os.path.exists(path) + f = open(path) + content = f.read().rstrip('\n') + assert content + f.close() + return content.split('\n') + + +def add_checksum(data): + mask = 0b10000000 + data_int = int.from_bytes(data, byteorder="big") + data_bit_len = len(data) * 8 // 32 + data_hash = hashlib.sha256(data).hexdigest() + fbyte_hash = unhexlify(data_hash)[0] + while data_bit_len: + data_bit_len -= 1 + data_int = (data_int << 1) | 1 if fbyte_hash & mask else data_int << 1 + mask = mask >> 1 + return data_int + + +def mnemonic2bytes(passphrase, language): + mnemonic = passphrase.split() + wordlist = create_wordlist(language) + codes = dict() + for code, word in enumerate(wordlist): + codes[word] = code + word_count = len(mnemonic) + entropy_int = None + bit_size = word_count * 11 + chk_sum_bit_len = word_count * 11 % 32 + for word in mnemonic: + entropy_int = (entropy_int << 11) | codes[word] if entropy_int else codes[word] + chk_sum = entropy_int & (2 ** chk_sum_bit_len - 1) + entropy_int = entropy_int >> chk_sum_bit_len + entropy = entropy_int.to_bytes((bit_size - chk_sum_bit_len) // 8, byteorder="big") + ent_hash = hashlib.sha256(entropy).hexdigest() + fb = unhexlify(ent_hash)[0] + assert (fb >> (8 - chk_sum_bit_len)) & chk_sum + return entropy + + diff --git a/pybtc/tools.py b/pybtc/tools.py index 5a8e4b2..143228b 100644 --- a/pybtc/tools.py +++ b/pybtc/tools.py @@ -704,70 +704,3 @@ def b2i(b): return vch2bn(b) - -# BIP39 -# -# -# - -def create_mnemonic(bits=256, language='english'): - passphrase = [] - wordlist = create_wordlist(language) - entropy = os.urandom(bits // 8) - entropy_int = int.from_bytes(entropy, byteorder="big") - entropy_bit_len = len(entropy) * 8 - chk_sum_bit_len = entropy_bit_len // 32 - entropy_hash = hashlib.sha256(entropy).hexdigest() - fbyte_hash = unhexlify(entropy_hash)[0] - entropy_int = add_checksum(entropy) - while entropy_int: - passphrase.append(wordlist[entropy_int & 0b11111111111]) - entropy_int = entropy_int >> 11 - return ' '.join(passphrase[::-1]) - - -def create_wordlist(language, wordlist_dir=BIP0039_DIR): - f = None - path = os.path.join(wordlist_dir, '.'.join((language, 'txt'))) - assert os.path.exists(path) - f = open(path) - content = f.read().rstrip('\n') - assert content - f.close() - return content.split('\n') - - -def add_checksum(data): - mask = 0b10000000 - data_int = int.from_bytes(data, byteorder="big") - data_bit_len = len(data) * 8 // 32 - data_hash = hashlib.sha256(data).hexdigest() - fbyte_hash = unhexlify(data_hash)[0] - while data_bit_len: - data_bit_len -= 1 - data_int = (data_int << 1) | 1 if fbyte_hash & mask else data_int << 1 - mask = mask >> 1 - return data_int - - -def mnemonic2bytes(mnemonic, language): - wordlist = create_wordlist(language) - codes = dict() - for code, word in enumerate(wordlist): - codes[word] = code - word_count = len(mnemonic) - entropy_int = None - bit_size = word_count * 11 - chk_sum_bit_len = word_count * 11 % 32 - for word in mnemonic: - entropy_int = (entropy_int << 11) | codes[word] if entropy_int else codes[word] - - chk_sum = entropy_int & (2 ** chk_sum_bit_len - 1) - entropy_int = entropy_int >> chk_sum_bit_len - entropy = entropy_int.to_bytes((bit_size - chk_sum_bit_len) // 8, byteorder="big") - ent_hash = hashlib.sha256(entropy).hexdigest() - fb = unhexlify(ent_hash)[0] - assert (fb >> (8 - chk_sum_bit_len)) & chk_sum - return entropy - -