def reverse_mnemonic(mnemonic, filepath): """ Get initial entropy from mnemonic and wordlist. :param mnemonic: mnemonic as a string :param filepath: filepath of the wordlist :return: entropy as a hex string """ if type(mnemonic) is not str: raise ValueError('mnemonic has to be a string; the given type was {}'.format(type(mnemonic))) mnemonic_list = mnemonic.split(' ') possible_ms_values = [x // 32 * 33 // 11 for x in POSSIBLE_ENT_VALUES] if len(mnemonic_list) not in possible_ms_values: raise ValueError('number of words in the mnemonic has to be in {}; the given number of words was {}'.format( possible_ms_values, len(mnemonic_list))) wordlist = get_wordlist(filepath) if len(wordlist) != 2048: raise ValueError('the wordlist has to have 2048 words; the given wordlist had {} words'.format(len(wordlist))) indices = [wordlist.index(w) for w in mnemonic_list] indices_bytes = [i.to_bytes(length=2, byteorder='big') for i in indices] indices_bits = [bytes_to_bits(b)[-11:] for b in indices_bytes] bit_string = ''.join(indices_bits) cs = len(bit_string) // 33 bit_string = bit_string[:len(bit_string) - cs] return int(bit_string, 2).to_bytes(length=len(bit_string) // 8, byteorder='big').hex()
def generate_mnemonic(ent, filepath): """ Generate a mnemonic from the given wordlist and for the given entropy length. :param ent: entropy length; type int; possible values from POSSIBLE_ENT_VALUES :param filepath: filepath of the wordlist :return: mnemonic """ if type(ent) is not int: raise ValueError('ent (entropy length) has to be int; the given type was {}'.format(type(ent))) if ent not in POSSIBLE_ENT_VALUES: raise ValueError( 'ent (entropy length) has to be in {}; the given values was {}'.format(POSSIBLE_ENT_VALUES, ent)) mnemonic = compose_mnemonic(generate_indices(ent), get_wordlist(filepath)) return mnemonic
def get_mnemonic_from_entropy_bytes(entropy_bytes, filepath): """ Get the mnemonic for the given entropy and wordlist. :param entropy_bytes: bytes encoding the entropy bytes :param filepath: filepath of the wordlist :return: mnemonic """ if type(entropy_bytes) is not bytes: raise ValueError('entropy_bytes has to be bytes object; the given type was {}'.format(type(entropy_bytes))) if len(entropy_bytes) * 8 not in POSSIBLE_ENT_VALUES: raise ValueError( 'eight multiple of entropy_bytes length has to be in {}; ' 'the eight multiple of length of the given values was {}'.format( POSSIBLE_ENT_VALUES, 8 * len(entropy_bytes))) mnemonic = compose_mnemonic(get_indices_from_entropy(entropy_bytes), get_wordlist(filepath)) return mnemonic
def generate_seed(mnemonic, passphrase='', filepath='../wordlists/english.txt'): """ Get the seed from a mnemonic :param mnemonic: mnemonic as a string :param passphrase: passphrase as a string :param filepath: path to the used wordlist :return: seed as a hex string """ wordlist = get_wordlist(filepath) split_mnemonic = mnemonic.split() for member in split_mnemonic: if member not in wordlist: raise ValueError("the given mnemonic contains illegal(s) word(s)") nfkd_mnemonic = bytes(unicodedata.normalize('NFKD', mnemonic), encoding='utf-8') concat = 'mnemonic' + passphrase nfkd_salt = bytes(unicodedata.normalize('NFKD', concat), encoding='utf-8') seed = pbkdf2_hmac('sha512', nfkd_mnemonic, nfkd_salt, 2048, 64).hex() return seed