def test_from_invalid_words_num(self): for test_words_num in Bip39WordsNum: self.assertRaises(ValueError, Bip39MnemonicGenerator().FromWordsNumber, test_words_num - 1) self.assertRaises(ValueError, Bip39MnemonicGenerator().FromWordsNumber, test_words_num + 1)
def test_vector(self): for test in TEST_VECT: lang = test["lang"] if "lang" in test else Bip39Languages.ENGLISH # Test mnemonic generator mnemonic = Bip39MnemonicGenerator(lang).FromEntropy( binascii.unhexlify(test["entropy"])) self.assertEqual(test["mnemonic"], mnemonic) # Test mnemonic validator using string (language specified) bip39_mnemonic_validator = Bip39MnemonicValidator(mnemonic, lang) entropy = bip39_mnemonic_validator.GetEntropy() self.assertEqual(test["entropy"], binascii.hexlify(entropy)) self.assertTrue(bip39_mnemonic_validator.IsValid()) # Test mnemonic validator using list (automatic language detection) bip39_mnemonic_validator = Bip39MnemonicValidator( mnemonic.split(" ")) entropy = bip39_mnemonic_validator.GetEntropy() self.assertEqual(test["entropy"], binascii.hexlify(entropy)) self.assertTrue(bip39_mnemonic_validator.IsValid()) # Test seed generator seed = Bip39SeedGenerator(mnemonic, lang).Generate(TEST_PASSPHRASE) self.assertEqual(test["seed"], binascii.hexlify(seed))
def test_vector(self): for test in TEST_VECT: # Test mnemonic generator mnemonic = Bip39MnemonicGenerator.FromEntropy( binascii.unhexlify(test["entropy"])) self.assertEqual(test["mnemonic"], mnemonic) # Test mnemonic validator using string bip39_mnemonic_validator = Bip39MnemonicValidator(mnemonic) entropy = bip39_mnemonic_validator.GetEntropy() self.assertEqual(test["entropy"], binascii.hexlify(entropy)) self.assertTrue(bip39_mnemonic_validator.Validate()) # Test mnemonic validator using list bip39_mnemonic_validator = Bip39MnemonicValidator( mnemonic.split(" ")) entropy = bip39_mnemonic_validator.GetEntropy() self.assertEqual(test["entropy"], binascii.hexlify(entropy)) self.assertTrue(bip39_mnemonic_validator.Validate()) # Test seed generator seed = Bip39SeedGenerator(mnemonic).Generate(TEST_PASSPHRASE) self.assertEqual(test["seed"], binascii.hexlify(seed))
def test_from_words_num(self): for test in TEST_WORDS_NUM_MAIN: if test["is_valid"]: mnemonic = Bip39MnemonicGenerator.FromWordsNumber(test["words_num"]) self.assertEqual(len(mnemonic.split(" ")), test["words_num"]) else: self.assertRaises(ValueError, Bip39MnemonicGenerator.FromWordsNumber, test["words_num"])
def test_entropy_invalid_bitlen(self): for test_bit_len in TEST_VECT_ENTROPY_BITLEN_INVALID: self.assertRaises(ValueError, Bip39EntropyGenerator, test_bit_len) # Build a dummy entropy with that bit length # Subtract 8 because, otherwise, dividing by 8 could result in a correct byte length dummy_ent = b"\x00" * ((test_bit_len - 8) // 8) # Construct from it self.assertRaises(ValueError, Bip39MnemonicGenerator().FromEntropy, dummy_ent)
def test_entropy_valid_bitlen(self): for test_bit_len in TEST_VECT_ENTROPY_BITLEN_VALID: # Test generator entropy = Bip39EntropyGenerator(test_bit_len).Generate() self.assertEqual(len(entropy), test_bit_len // 8) # Generate mnemonic mnemonic = Bip39MnemonicGenerator().FromEntropy(entropy) # Compute the expected mnemonic length mnemonic_len = (test_bit_len + (test_bit_len // 32)) // 11 # Test generated mnemonic length self.assertEqual(len(mnemonic.split(" ")), mnemonic_len)
def test_entropy_invalid_bitlen(self): for test_bit_len in Bip39EntropyBitLen: self.assertRaises(ValueError, Bip39EntropyGenerator, test_bit_len - 1) self.assertRaises(ValueError, Bip39EntropyGenerator, test_bit_len + 1) # Build a dummy entropy with invalid bit length dummy_ent = b"\x00" * ((test_bit_len - 8) // 8) self.assertRaises(ValueError, Bip39MnemonicGenerator().FromEntropy, dummy_ent)
def test_entropy_valid_bitlen(self): for test_bit_len in Bip39EntropyBitLen: # Test generator entropy = Bip39EntropyGenerator(test_bit_len).Generate() self.assertEqual(len(entropy), test_bit_len // 8) # Generate mnemonic mnemonic = Bip39MnemonicGenerator().FromEntropy(entropy) # Compute the expected mnemonic length mnemonic_len = (test_bit_len + (test_bit_len // 32)) // 11 # Test generated mnemonic length self.assertEqual(mnemonic.WordsCount(), mnemonic_len)
def getMnemonic( password: str = "" ) -> str: while True: res: str = Bip39MnemonicGenerator.FromWordsNumber(Bip39WordsNum.WORDS_NUM_24) seed: bytes = sha256(Bip39SeedGenerator(res).Generate(password)).digest() try: BIP32.derive(seed, [44 + (1 << 31), 5132 + (1 << 31), 0 + (1 << 31), 0]) BIP32.derive(seed, [44 + (1 << 31), 5132 + (1 << 31), 0 + (1 << 31), 1]) except Exception: continue return res
def generate(self): # Generate random mnemonic mnemonic = Bip39MnemonicGenerator.FromWordsNumber(12) # Generate seed from mnemonic seed_bytes = Bip39SeedGenerator(mnemonic).Generate() # Generate BIP44 master keys bip_obj_mst = Bip44.FromSeed(seed_bytes, Bip44Coins.DASH) address = bip_obj_mst.PublicKey().ToAddress() wif = bip_obj_mst.PrivateKey().ToWif() seed = mnemonic return CryptoCoin(address, wif, seed)
def find_it(search_for: list): found = 0 while True: entropy = urandom(32) mnemonic = Bip39MnemonicGenerator().FromEntropy(entropy) # pk = token_hex(32) # +50% time, but supposed to be cryptographically secure addresses = get_addresses_from(mnemonic) for string in search_for: for index, address in enumerate(addresses): if not options.case: address = address.lower() if string in address: print(address, index, mnemonic) found += 1 if found > options.max: return
def test_entropy(self): for test in TEST_ENTROPY_BITS_MAIN: if test["is_valid"]: # Test generator entropy = EntropyGenerator(test["bit_len"]).Generate() self.assertEqual(len(entropy), test["bit_len"] // 8) # Generate mnemonic mnemonic = Bip39MnemonicGenerator.FromEntropy(entropy) # Compute the expected mnemonic length mnemonic_len = (test["bit_len"] + (test["bit_len"] // 32)) // 11 # Test generated mnemonic length self.assertEqual(len(mnemonic.split(" ")), mnemonic_len) else: self.assertRaises(ValueError, EntropyGenerator, test["bit_len"]) # Build a dummy entropy with that bit length dummy_ent = b"\x00" * (test["bit_len"] // 8) # Construct from it self.assertRaises(ValueError, Bip39MnemonicGenerator.FromEntropy, dummy_ent)
def CreateRandom(self, wallet_name, words_num): """ Create wallet randomly. Args: wallet_name (str) : Wallet name words_num (HdWalletWordsNum): Words number, must be a HdWalletWordsNum enum Returns: HdWallet object: HdWallet object Raises: TypeError: If words number is not of HdWalletWordsNum enum """ if not isinstance(words_num, HdWalletWordsNum): raise TypeError("Words number is not an enumerative of HdWalletWordsNum") mnemonic = Bip39MnemonicGenerator.FromWordsNumber(words_num) return self.CreateFromMnemonic(wallet_name, mnemonic)
def test_vector(self): for test in TEST_VECT: lang = test["lang"] if "lang" in test else Bip39Languages.ENGLISH # Test mnemonic generator mnemonic = Bip39MnemonicGenerator(lang).FromEntropy( binascii.unhexlify(test["entropy"])) self.assertEqual(test["mnemonic"], mnemonic.ToStr()) self.assertEqual(test["mnemonic"], str(mnemonic)) self.assertEqual(test["mnemonic"].split(" "), mnemonic.ToList()) self.assertEqual(len(test["mnemonic"].split(" ")), mnemonic.WordsCount()) # Test mnemonic validator (language specified) mnemonic_validator = Bip39MnemonicValidator(lang) self.assertTrue(mnemonic_validator.IsValid(mnemonic)) # Test mnemonic validator (automatic language detection) mnemonic_validator = Bip39MnemonicValidator() self.assertTrue(mnemonic_validator.IsValid(mnemonic)) # Test decoder (language specified) entropy = Bip39MnemonicDecoder(lang).Decode(mnemonic) self.assertEqual(test["entropy"], binascii.hexlify(entropy)) # Test decoder (automatic language detection) entropy = Bip39MnemonicDecoder().Decode(mnemonic) self.assertEqual(test["entropy"], binascii.hexlify(entropy)) # Test decoder with checksum if "entropy_chksum" in test: entropy = Bip39MnemonicDecoder(lang).DecodeWithChecksum( mnemonic) self.assertEqual(test["entropy_chksum"], binascii.hexlify(entropy)) entropy = Bip39MnemonicDecoder().DecodeWithChecksum(mnemonic) self.assertEqual(test["entropy_chksum"], binascii.hexlify(entropy)) # Test seed generator seed = Bip39SeedGenerator(mnemonic, lang).Generate(TEST_PASSPHRASE) self.assertEqual(test["seed"], binascii.hexlify(seed))
def generate(self): # Generate random mnemonic mnemonic = Bip39MnemonicGenerator.FromWordsNumber(12) # Generate seed from mnemonic seed_bytes = Bip39SeedGenerator(mnemonic).Generate() # Generate BIP44 master keys bip_obj_mst = Bip44.FromSeed(seed_bytes, Bip44Coins.BITCOIN) wif = WifEncoder.Encode(bip_obj_mst.PrivateKey().Raw().ToBytes(), True, POTE_WIF_NET_VER.Main()) pub_key_bytes = bip_obj_mst.PublicKey().RawCompressed().ToBytes() address = Base58Encoder.CheckEncode(POTE_P2PKH_NET_VER.Main() + CryptoUtils.Hash160(pub_key_bytes)) seed = mnemonic return CryptoCoin(address, wif, seed)
def cli( mnemonic: str, passphrase: str, limit: int, prompt_mnemonic: bool, prompt_passphrase: bool, hide_mnemonic: bool, hide_private: bool, ): if prompt_passphrase: passphrase = click.prompt("passphrase", hide_input=True) if prompt_mnemonic: mnemonic = click.prompt("mnemonic", hide_input=True) if not mnemonic: mnemonic = Bip39MnemonicGenerator.FromWordsNumber( Bip39WordsNum.WORDS_NUM_24) if not Bip39MnemonicValidator(mnemonic).Validate(): return fatal("Invalid mnemonic") seed_bytes = Bip39SeedGenerator(mnemonic).Generate(passphrase) if not hide_mnemonic: click.echo(mnemonic + "\n") bip_obj_mst = Bip44.FromSeed(seed_bytes, Bip44Coins.BITCOIN) bip_obj_acc = bip_obj_mst.Purpose().Coin().Account(0) bip_obj_chain = bip_obj_acc.Change(Bip44Changes.CHAIN_EXT) # m/44'/0'/0'/0/i for i in range(limit): bip_obj_addr = bip_obj_chain.AddressIndex(i) address = bip_obj_addr.PublicKey().ToAddress() private = bip_obj_addr.PrivateKey().ToWif() acc = address if hide_private else f"{address} / {private}" click.echo(acc)
def test_from_invalid_words_num(self): for test_words_num in TEST_VECT_WORDS_NUM_INVALID: self.assertRaises(ValueError, Bip39MnemonicGenerator().FromWordsNumber, test_words_num)
def test_from_valid_words_num(self): for test_words_num in Bip39WordsNum: mnemonic = Bip39MnemonicGenerator().FromWordsNumber(test_words_num) self.assertEqual(mnemonic.WordsCount(), test_words_num)
def generate(): # Tells the library what network we are using setup() if not mnemonic_phrase: # Generate mnemonic from random 192-bit entropy entropy_bytes = Bip39EntropyGenerator( Bip39EntropyBitLen.BIT_LEN_192).Generate() mnemonic = Bip39MnemonicGenerator.FromEntropy(entropy_bytes) print("Generated random mnemonic:\n" + mnemonic) else: print("Using included mnemonic.") mnemonic = mnemonic_phrase # Get seed bytes from mnemonic seed_bytes = Bip39SeedGenerator(mnemonic).Generate() bip44_mst = Bip44.FromSeed( seed_bytes, Bip44Coins.BITCOIN) # Could add in multi currency support # Derive account 0 for Bitcoin: m/44'/0'/0' bip44_acc = bip44_mst.Purpose() \ .Coin() \ .Account(0) # Derive the external chain: m/44'/0'/0'/0 bip44_change = bip44_acc.Change(Bip44Changes.CHAIN_EXT) with open(output_dest, 'w') as output_file: # Open the output file output_file.write("address, public_key" + (", private_key" if privates else "") + "\n") # Go through each address for i in range(number): bip44_addr = bip44_change.AddressIndex(i) # create segwit address addr3 = PrivateKey.from_wif(bip44_addr.PrivateKey().ToWif( )).get_public_key().get_segwit_address() # wrap in P2SH address addr4 = P2shAddress.from_script(addr3.to_script_pub_key()) if addr4.to_string() == compare: print("Found it!") print("Path: m/44'/0'/0'/0/" + str(i)) break #print("P2SH(P2WPKH):", addr4.to_string()) if (i % int(number / 10)) == 0: print('Finished {}'.format(i)) out = "{0}, {1}".format(addr4.to_string(), bip44_addr.PublicKey().ToExtended() ) # Public addresses not including private if (privates): # Include the private keys out = "{0}, {1}, {2}".format( addr4.to_string(), bip44_addr.PublicKey().RawCompressed().ToHex(), bip44_addr.PrivateKey().ToWif()) #bip44_addr.PublicKey().ToAddress() # This is the regular address (not P2SH(P2WPKH)) # Print extended keys and address if (verbose): print(out) output_file.write(out + "\n")
def test_from_valid_words_num(self): for test_words_num in TEST_VECT_WORDS_NUM_VALID: mnemonic = Bip39MnemonicGenerator().FromWordsNumber(test_words_num) self.assertEqual(len(mnemonic.split(" ")), test_words_num)
"""Example of key derivation using Substrate (same addresses of PolkadotJS).""" from bip_utils import (Bip39WordsNum, Bip39MnemonicGenerator, SubstrateBip39SeedGenerator, SubstrateCoins, Substrate) # Generate random mnemonic mnemonic = Bip39MnemonicGenerator().FromWordsNumber(Bip39WordsNum.WORDS_NUM_24) print(f"Mnemonic string: {mnemonic}") # Generate seed from mnemonic seed_bytes = SubstrateBip39SeedGenerator(mnemonic).Generate() # Construct from seed substrate_ctx = Substrate.FromSeed(seed_bytes, SubstrateCoins.POLKADOT) # Print master keys and address print( f"Master private key (bytes): {substrate_ctx.PrivateKey().Raw().ToHex()}") print( f"Master public key (bytes): {substrate_ctx.PublicKey().RawCompressed().ToHex()}" ) print(f"Address: {substrate_ctx.PublicKey().ToAddress()}") # Derive a child key substrate_ctx = substrate_ctx.ChildKey("//hard") # Print derived keys and address print( f"Derived private key (bytes): {substrate_ctx.PrivateKey().Raw().ToHex()}") print( f"Derived public key (bytes): {substrate_ctx.PublicKey().RawCompressed().ToHex()}" ) print(f"Derived address: {substrate_ctx.PublicKey().ToAddress()}") # Print path
def DerivationTest(rpc: RPC) -> None: #Start by testing BIP 32, 39, and 44 functionality in general. for _ in range(10): rpc.call("personal", "setWallet") verifyMnemonicAndAccount(rpc) #Set specific Mnemonics and ensure they're handled properly. for _ in range(10): mnemonic: str = getMnemonic() rpc.call("personal", "setWallet", {"mnemonic": mnemonic}) verifyMnemonicAndAccount(rpc, mnemonic) #Create Mnemonics with passwords and ensure they're handled properly. for _ in range(10): password: str = os.urandom(32).hex() rpc.call("personal", "setWallet", {"password": password}) verifyMnemonicAndAccount(rpc, password=password) #Set specific Mnemonics with passwords and ensure they're handled properly. for i in range(10): password: str = os.urandom(32).hex() #Non-hex string. if i == 0: password = "******" mnemonic: str = getMnemonic(password) rpc.call("personal", "setWallet", { "mnemonic": mnemonic, "password": password }) verifyMnemonicAndAccount(rpc, mnemonic, password) #setWallet, getMnemonic, getMeritHolderKey, getMeritHolderNick's non-existent case, and getAccount have now been tested. #This leaves getAddress with specific indexes. #Clear the Wallet. rpc.call("personal", "setWallet") #Start by testing specific derivation. password: str = "password since it shouldn't be relevant" for _ in range(10): mnemonic: str = getMnemonic(password) index: int = 100 key: bytes while True: try: key = BIP32.derive( sha256(Bip39SeedGenerator(mnemonic).Generate( password)).digest(), [ 44 + (1 << 31), 5132 + (1 << 31), 0 + (1 << 31), 0, index ]) break except Exception: index += 1 rpc.call("personal", "setWallet", { "mnemonic": mnemonic, "password": password }) addr: str = bech32_encode( "mr", convertbits( bytes([0]) + RistrettoScalar(key[:32]).toPoint().serialize(), 8, 5)) if rpc.call("personal", "getAddress", {"index": index}) != addr: raise TestError("Didn't get the correct address for this index.") #Test if a specific address is requested, it won't come up naturally. #This isn't explicitly required by the RPC spec, which has been worded carefully to leave this open ended. #The only requirement is the address was never funded and the index is sequential (no moving backwards). #The node offers this feature to try to make mixing implicit/explicit addresses safer, along with some internal benefits. #That said, said internal benefits are minimal or questionable, hence why the RPC docs are open ended. #This way we can decide differently in the future. rpc.call("personal", "setWallet") firstAddr: str = rpc.call("personal", "getAddress") #Explicitly get the first address. for i in range(256): try: rpc.call("personal", "getAddress", {"index": i}) break except TestError: if i == 255: raise Exception( "The first 256 address were invalid; this should be practically impossible." ) if firstAddr == rpc.call("personal", "getAddress"): raise TestError("Explicitly grabbed address was naturally returned.") #Test error cases. #Mnemonic with an improper amount of entropy. #Runs multiple times in case the below error pops up for the sole reason the Mnemonic didn't have viable keys. #This should error earlier than that though. for _ in range(16): try: rpc.call( "personal", "setWallet", { "mnemonic": Bip39MnemonicGenerator.FromWordsNumber( Bip39WordsNum.WORDS_NUM_12) }) raise Exception() except Exception as e: if str(e) != "-3 Invalid mnemonic or password.": raise TestError( "Could set a Mnemonic with too little entropy.") #Mnemonic with additional spaces. rpc.call("personal", "setWallet") mnemonic: str = rpc.call("personal", "getMnemonic") rpc.call("personal", "setWallet", {"mnemonic": " " + (" " * 2).join(mnemonic.split(" ")) + " "}) if rpc.call("personal", "getMnemonic") != mnemonic: raise TestError( "Meros didn't handle a mnemonic with extra whitespace.") #Negative index to getAddress. try: rpc.call("personal", "getAddress", {"index": -1}) raise Exception() except Exception as e: if str(e) != "-32602 Invalid params.": raise TestError("Could call getAddress with a negative index.")