def test_mnemonic_to_bin(self): """Given test mnemonic, derive and match entropy as bit string""" assert len(self.data) == 4 for vector in self.data: entropy_bin = vector['entropy_binary'] test_mnemonic = vector['mnemonic'] entropy_bin_calc = bip39.mnemonic2binstring(test_mnemonic) self.assertEqual(entropy_bin, entropy_bin_calc)
def test_mnemonic_to_bin_mismatch(self): """Flip a bit in the test data and verify the mnemonic doesn't match""" assert len(self.data) == 4 for vector in self.data: entropy_bin = vector['entropy_binary'] test_mnemonic = vector['mnemonic'] last = entropy_bin[-1:] assert last in ("0", "1") flipped = "0" if last == "1" else "1" entropy_bin_modified = entropy_bin[:-1] + flipped entropy_bin_calc = bip39.mnemonic2binstring(test_mnemonic) self.assertNotEqual(entropy_bin_modified, entropy_bin_calc)
def test_mnemonic2binstring_invalid(self): """Test function with invalid bip39 mnemonics""" with self.assertRaises(ValueError): bip39.mnemonic2binstring('') with self.assertRaises(bip39.InvalidWordError): bip39.mnemonic2binstring('mimble wimble') #bad checksum with self.assertRaises(bip39.FailedCheckSumError): bip39.mnemonic2binstring('town iron abandon')
def _main(): wordlist = bip39.get_wordlist() wordset = set(wordlist) assert len(wordlist) == 2048 mnemonic = str( raw_input('Enter your BIP39 mnemonic in using the ' 'canonical English dictionary: ')) print "You entered: '{0}'".format(mnemonic) words = [str(word) for word in mnemonic.split(' ')] if not _is_canonical_mnemonic(words, wordset): sys.exit(1) if len(words) not in NORMAL_MNEMONIC_LEN: print "WARNING: Length of menonic you provided ({0}) is atypical.".format( len(words)) binstring = None try: binstring = bip39.mnemonic2binstring(mnemonic) except bip39.FailedCheckSumError: print( "ERROR: Mnemonic failed checksum. It may be an invalid BIP39 " "mnemonic -- be careful!!! Stopping.") sys.exit(1) print "Mnemonic as binary string: {0}".format(binstring) print "Note: The mnemonic passes a checksum test!" buf = "Re-deriving mnemonic from binary string for sanity check... {result}" mnemonic_calc = bip39.binstring2mnemonic(binstring) if mnemonic == mnemonic_calc: print buf.format(result="PASSED!") else: print buf.format( result="FAILED! Stopping. Please report issue on GitHub.") sys.exit(1) if is_valid_entropy(binstring): print "The mnemonic appears to conform to a valid bip39 entropy format." else: print( "ERROR: The mnemonic doesn't appear to conform to bip39 entropy " "format -- be careful!!! Stopping.") sys.exit(1) urandom_rounds = int( raw_input(('Enter the number of times entropy should be mixed in from ' '/dev/urandom (0 to skip): '))) latest_entropy_binstring = binstring latest_mnemonic = mnemonic n_bits = len(binstring) for _ in repeat(None, urandom_rounds): new_entropy = entropy.get_entropy(n_bits) combined_entropy = entropy.xor(latest_entropy_binstring, new_entropy) combined_mnemonic = bip39.binstring2mnemonic(combined_entropy) print "====" print "old: {old_hex} {old_mnemonic}".format( old_hex=bip39.bin2hex(latest_entropy_binstring), old_mnemonic=latest_mnemonic) print "new: {new_hex} {new_mnemonic}".format( new_hex=bip39.bin2hex(new_entropy), new_mnemonic=bip39.binstring2mnemonic(new_entropy)) print "xor: {xor_hex} {xor_mnemonic}".format( xor_hex=bip39.bin2hex(combined_entropy), xor_mnemonic=combined_mnemonic) print( "Manually validate:\n" "\t1. Old hex and mnemonic match previous versions.\n" "\t2. Entering new and xor'd hex into alternative tool such as " "Ian Coleman bip39 tool derives to correct mnemonics.\n" "\t3. Confirm old XOR new = xor'd version hex char at a time.") latest_entropy_binstring = combined_entropy latest_mnemonic = combined_mnemonic min_estimated_rolls = int( math.ceil(entropy.die_rolls_per_bits(n_bits=n_bits) * (4.0 / 3))) entropy_gathered = False rolls_str = '' rolls = [] while True: rolls_str = str( raw_input(( 'Roll a die at least {minimum} times to provide entropy to mix ' 'in, with each roll represented by 1 to 6 and a space separating ' 'each roll: ').format(minimum=min_estimated_rolls))) rolls = [int(roll) for roll in rolls_str.split()] if len(rolls) >= min_estimated_rolls: break dice_bitstring = None while True: try: dice_bitstring = entropy.die_rolls_to_bitstring( dice_vals=rolls, bitstring_len=n_bits) print "Dice rolls as bitstring: {0}".format(dice_bitstring) break except entropy.InsufficientEntropyError: more_rolls_str = str( raw_input(( "More entropy needed. {num} rolls saved so far. Please enter " "another roll: ").format(num=len(rolls)))) rolls.extend([int(roll) for roll in more_rolls_str.split()]) combined_entropy = entropy.xor(latest_entropy_binstring, dice_bitstring) combined_mnemonic = bip39.binstring2mnemonic(combined_entropy) print "====" print "old: {old_hex} {old_mnemonic}".format( old_hex=bip39.bin2hex(latest_entropy_binstring), old_mnemonic=latest_mnemonic) print "new: {new_hex} {new_mnemonic}".format( new_hex=bip39.bin2hex(dice_bitstring), new_mnemonic=bip39.binstring2mnemonic(dice_bitstring)) print "xor: {xor_hex} {xor_mnemonic}".format( xor_hex=bip39.bin2hex(combined_entropy), xor_mnemonic=combined_mnemonic)
def test_mnemonic2binstring_valid(self): """Test function with valid bip39 mnemonics""" self.assertEqual( bip39.mnemonic2binstring('voice catch possible'), '11110101011001001000001010100010')