def create_wallet(): private_key = bytes(Random.get_random_bytes(32)) keypair = KeyPair(priv_key=private_key) return { "private_key": keypair.Export(), "address": keypair.GetAddress() }
def test_should_export_valid_wif_key(self): kp = KeyPair( binascii.unhexlify( "cbf4b9f70470856bb4f40f80b87edb90865997ffee6df315ab166d713af433a5" )) wif = kp.Export() self.assertEqual( wif, "L44B5gGEpqEDRS9vVPz7QT35jcBG2r3CZwSwQ4fCewXAhAhqGVpP")
def test_should_throw_error_on_too_short_passphrase(self): kp = KeyPair( binascii.unhexlify( "cbf4b9f70470856bb4f40f80b87edb90865997ffee6df315ab166d713af433a5" )) with self.assertRaises(ValueError) as context: kp.ExportNEP2("x") self.assertIn('Passphrase must have a minimum', str(context.exception))
def test_should_export_valid_nep2_key(self): kp = KeyPair( binascii.unhexlify( "cbf4b9f70470856bb4f40f80b87edb90865997ffee6df315ab166d713af433a5" )) nep2_key = kp.ExportNEP2("TestingOneTwoThree") self.assertEqual( nep2_key, "6PYVPVe1fQznphjbUxXP9KZJqPMVnVwCx5s5pr5axRJ8uHkMtZg97eT5kL")
def test_publickey_to_scripthash(self): expected_scripthash = binascii.unhexlify( '79ecf967a02f9bdbd147fc97b18efd7877d27f78') priv_key = KeyPair.PrivateKeyFromWIF( 'L44B5gGEpqEDRS9vVPz7QT35jcBG2r3CZwSwQ4fCewXAhAhqGVpP') kp = KeyPair(priv_key=priv_key) pub_bytes = kp.PublicKey.encode_point(True) result = Helper.pubkey_to_pubhash(pub_bytes) self.assertEqual(result, expected_scripthash)
def test_should_export_valid_nep2_key_with_emoji_pwd(self): pwd = "hellö♥️" privkey = "03eb20a711f93c04459000c62cc235f9e9da82382206b812b07fd2f81779aa42" # expected outputs target_address = "AXQUduANGZF4e7wDazVAtyRLHwMounaUMA" target_encrypted_key = "6PYWdv8bP9vbfGsNnjzDawCoXCYpk4rnWG8xTZrvdzx6FjB6jv4H9MM586" kp = KeyPair(binascii.unhexlify(privkey)) nep2_key = kp.ExportNEP2(pwd) self.assertEqual(nep2_key, target_encrypted_key) self.assertEqual(kp.GetAddress(), target_address)
def test_should_throw_error_on_invalid_password(self): nep2_key = "6PYVPVe1fQznphjbUxXP9KZJqPMVnVwCx5s5pr5axRJ8uHkMtZg97eT5kL" pwd = "invalid-pwd" with self.assertRaises(ValueError) as context: KeyPair.PrivateKeyFromNEP2(nep2_key, pwd) self.assertEqual('Wrong passphrase', str(context.exception))
def test_should_work(self): privkey = KeyPair.PrivateKeyFromWIF( "L44B5gGEpqEDRS9vVPz7QT35jcBG2r3CZwSwQ4fCewXAhAhqGVpP") self.assertEqual( binascii.hexlify(privkey), b"cbf4b9f70470856bb4f40f80b87edb90865997ffee6df315ab166d713af433a5" )
def test_long_private_key(self): # Taken from the neo-python UserWallet test priv_key = b'[\\\x8c\xdc\xb3/\x8e\'\x8e\x11\x1a\x0b\xf5\x8e\xbbF9\x88\x02K\xb4\xe2P\xaaC\x10\xb4\x02R\x03\x0b`\xdd\xc4\x99[\xac\x00)\x8b"s\x1d\xe7\xa8?\xa4\x9d\xed*\xce\xeai\xfa=\xd8r\x93p \xc8\xa9\xb6\xc6ad\xf6V\x9b#\xdfX\xc5Ltnv\x84%\x1a\x17e:K2\xf1\xb4JW\x03\xfd\xad\x94\x8eu]' kp = KeyPair(priv_key) expected_result = b'025b5c8cdcb32f8e278e111a0bf58ebb463988024bb4e250aa4310b40252030b60' self.assertEqual(expected_result, kp.PublicKey.encode_point(True))
def test_should_work(self): nep2_key = "6PYVPVe1fQznphjbUxXP9KZJqPMVnVwCx5s5pr5axRJ8uHkMtZg97eT5kL" pwd = "TestingOneTwoThree" should_equal_private_key = b"cbf4b9f70470856bb4f40f80b87edb90865997ffee6df315ab166d713af433a5" privkey = KeyPair.PrivateKeyFromNEP2(nep2_key, pwd) privkey_hex = binascii.hexlify(privkey) self.assertEqual(privkey_hex, should_equal_private_key)
def execute(self, arguments): wallet = PromptData.Wallet if len(arguments) != 1: print("Please specify the required parameter") return False nep2_key = arguments[0] passphrase = prompt("[key password] ", is_password=True) try: kp = KeyPair.PrivateKeyFromNEP2(nep2_key, passphrase) except ValueError as e: print(str(e)) return False try: key = wallet.CreateKey(kp) print(f"Imported key: {nep2_key}") pub_key = key.PublicKey.encode_point(True).decode('utf-8') print(f"Pubkey: {pub_key}") print(f"Address: {key.GetAddress()}") except Exception as e: # couldn't find an exact call that throws this but it was in the old code. Leaving it in for now. print(f"Key creation error: {str(e)}") return False
def test_fail_to_determine_plublic_key(self, patched_priv_to_pubkey): # https://github.com/vbuterin/pybitcointools/blob/aeb0a2bbb8bbfe421432d776c649650eaeb882a5/bitcoin/main.py#L291 patched_priv_to_pubkey.side_effect = Exception("Invalid privkey") with self.assertRaises(Exception) as context: KeyPair(bytes(32 * 'A', 'utf8')) self.assertEqual('Could not determine public key', str(context.exception))
def test_c(self): key = KeyPair(priv_key=self.decrypted_pk) self.assertEqual(key.PublicKey.x, self.pubkey_x) self.assertEqual(key.PublicKey.y, self.pubkey_y) self.assertEqual(key.PublicKey.encode_point(True), self.pubkey_encoded) self.assertEqual(key.PublicKey.encode_point(False), self.pubkey_not_comp) self.assertIsInstance(key.PublicKeyHash, UInt160) self.assertEqual(key.PublicKeyHash.ToBytes(), self.pubkeyhash) self.assertEqual(key.Export(), self.wif) private_key_from_wif = KeyPair.PrivateKeyFromWIF(self.wif) self.assertEqual(private_key_from_wif, self.pk)
def test_neon_sig(self): key = KeyPair(priv_key=self.nmpk) hhex = hashlib.sha256(binascii.unhexlify(self.nmsg)).hexdigest() self.assertEqual(hhex, self.hashhex) sig = Crypto.Sign(self.nmsg, key.PrivateKey) self.assertEqual(sig.hex(), self.neon_sig)
def test_sign_and_verify_str(self): privkey = KeyPair.PrivateKeyFromWIF( "L44B5gGEpqEDRS9vVPz7QT35jcBG2r3CZwSwQ4fCewXAhAhqGVpP") keypair = KeyPair(privkey) hashdata = "74657374" keypair_signature = Crypto.Sign(hashdata, bytes(keypair.PrivateKey)) keypair_signature2 = Crypto.Default().Sign(hashdata, bytes(keypair.PrivateKey)) self.assertEqual(keypair_signature, keypair_signature2) # verify without unhexing verification_result = Crypto.VerifySignature("test", keypair_signature, keypair.PublicKey, unhex=False) verification_result2 = Crypto.Default().VerifySignature( "test", keypair_signature, keypair.PublicKey, unhex=False) self.assertEqual(verification_result, verification_result2) self.assertTrue(verification_result)
def test_publickey_to_redeemscript_to_scripthash_to_address(self): # NEP 2 testvector expected_redeemscript = binascii.unhexlify( '21026241e7e26b38bb7154b8ad49458b97fb1c4797443dc921c5ca5774f511a2bbfcac' ) expected_scripthash = binascii.unhexlify( '79ecf967a02f9bdbd147fc97b18efd7877d27f78') expected_address = 'AStZHy8E6StCqYQbzMqi4poH7YNDHQKxvt' priv_key = KeyPair.PrivateKeyFromWIF( 'L44B5gGEpqEDRS9vVPz7QT35jcBG2r3CZwSwQ4fCewXAhAhqGVpP') kp = KeyPair(priv_key=priv_key) pub_bytes = kp.PublicKey.encode_point(True) redeemscript = Helper.pubkey_to_redeem(pub_bytes) scripthash = Helper.redeem_to_scripthash(redeemscript) address = Helper.scripthash_to_address(scripthash) self.assertEqual(redeemscript, expected_redeemscript) self.assertEqual(scripthash, expected_scripthash) self.assertEqual(address, expected_address)
def test_6_import_wif(self): wallet = self.GetWallet1() key_to_import = 'L3MBUkKU5kYg16KSZnqcaTj2pG5ei3fN9A4X7rxXys18GBDa3bH8' prikey = KeyPair.PrivateKeyFromWIF(key_to_import) keypair = wallet.CreateKey(prikey) key_out = keypair.PublicKey.encode_point(True).decode('utf-8') self.assertEqual(key_out, '03f3a3b5a4d873933fc7f4b53113e8eb999fb20038271fbbb10255585670c3c312')
def example2(): source_address = "AJQ6FoaSXDFzA6wLnyZ1nFN7SGSN2oNTc3" source_script_hash = address_to_scripthash(source_address) # start by creating a base InvocationTransaction # the inputs, outputs and Type do not have to be set anymore. invocation_tx = InvocationTransaction() # Since we are building a raw transaction, we will add the raw_tx flag invocation_tx.raw_tx = True # often times smart contract developers use the function ``CheckWitness`` to determine if the transaction is signed by somebody eligible of calling a certain method # in order to pass that check you want to add the corresponding script_hash as a transaction attribute (this is generally the script_hash of the public key you use for signing) # Note that for public functions like the NEP-5 'getBalance' and alike this would not be needed, but it doesn't hurt either invocation_tx.Attributes.append( TransactionAttribute(usage=TransactionAttributeUsage.Script, data=source_script_hash)) # next we need to build a 'script' that gets executed against the smart contract. # this is basically the script that calls the entry point of the contract with the necessary parameters smartcontract_scripthash = UInt160.ParseString( "31730cc9a1844891a3bafd1aa929a4142860d8d3") sb = ScriptBuilder() # call the NEP-5 `name` method on the contract (assumes contract address is a NEP-5 token) sb.EmitAppCallWithOperation(smartcontract_scripthash, 'name') invocation_tx.Script = binascii.unhexlify(sb.ToArray()) # at this point we've build our unsigned transaction and it's time to sign it before we get the raw output that we can send to the network via RPC # we need to create a Wallet instance for helping us with signing wallet = UserWallet.Create('path', to_aes_key('mypassword'), generate_default_key=False) # if you have a WIF use the following # this WIF comes from the `neo-test1-w.wallet` fixture wallet private_key = KeyPair.PrivateKeyFromWIF( "Ky94Rq8rb1z8UzTthYmy1ApbZa9xsKTvQCiuGUZJZbaDJZdkvLRV") # if you have a NEP2 encrypted key use the following instead # private_key = KeyPair.PrivateKeyFromNEP2("NEP2 key string", "password string") # we add the key to our wallet wallet.CreateKey(private_key) # and now we're ready to sign context = ContractParametersContext(invocation_tx) wallet.Sign(context) invocation_tx.scripts = context.GetScripts() raw_tx = invocation_tx.ToArray() return raw_tx
def test_sign_and_verify(self): privkey = KeyPair.PrivateKeyFromWIF( "L44B5gGEpqEDRS9vVPz7QT35jcBG2r3CZwSwQ4fCewXAhAhqGVpP") keypair = KeyPair(privkey) hashdata = b'aabbcc' keypair_signature = Crypto.Sign(hashdata, bytes(keypair.PrivateKey)) keypair_signature2 = Crypto.Default().Sign(hashdata, bytes(keypair.PrivateKey)) self.assertEqual(keypair_signature, keypair_signature2) verification_result = Crypto.VerifySignature(hashdata.decode('utf8'), keypair_signature, keypair.PublicKey) verification_result2 = Crypto.Default().VerifySignature( hashdata.decode('utf8'), keypair_signature, keypair.PublicKey) self.assertEqual(verification_result, verification_result2) self.assertTrue(verification_result) # verify with compressed key verification_result3 = Crypto.VerifySignature( hashdata.decode('utf8'), keypair_signature, binascii.unhexlify(keypair.PublicKey.encode_point(True))) self.assertTrue(verification_result3) # verify without unhexxing verification_result4 = Crypto.VerifySignature( binascii.unhexlify(hashdata), keypair_signature, binascii.unhexlify(keypair.PublicKey.encode_point(True)), unhex=False) self.assertTrue(verification_result4) # this should fail because the signature will not match the input data verification_result = Crypto.VerifySignature(b'aabb', keypair_signature, keypair.PublicKey) self.assertFalse(verification_result)
def test_normal_signing(self): # test the normal order of operations: Keypair will initialize secp256r1 Elliptic curve parameters message = binascii.hexlify(b'Hello World') key = KeyPair( bytes.fromhex( '8631cd2635c416ba5f043561e9d2ff40b79c3bb2eb245e176615298b8372d0a4' )) signature = Crypto.Sign( message, '8631cd2635c416ba5f043561e9d2ff40b79c3bb2eb245e176615298b8372d0a4') self.assertTrue( Crypto.VerifySignature(message, signature, key.PublicKey)) TestSigningWithoutCryptoInstance.sig1 = signature.hex()
def Sign(self, NEP2orPrivateKey, NEP2password=None, multisig_args=[]): """ Sign the raw transaction Args: NEP2orPrivateKey: (str) the NEP2 or PrivateKey string from the address you are sending from. NOTE: Assumes WIF if NEP2password is None. NEP2password: (str, optional) the NEP2 password associated with the NEP2 key string. Defaults to None. multisig_args: (list, optional) the arguments for importing a multsig address (e.g. [<owner pubkey>, <num required sigs>, [<signing pubkey>, ...]]) """ temp_path = "temp_wallet.wallet" temp_password = "******" wallet = UserWallet.Create(temp_path, to_aes_key(temp_password), generate_default_key=False) if NEP2password: private_key = KeyPair.PrivateKeyFromNEP2(NEP2orWIF, NEP2password) else: private_key = binascii.unhexlify(NEP2orPrivateKey) wallet.CreateKey(private_key) if multisig_args: # import a multisig address verification_contract = Contract.CreateMultiSigContract( Crypto.ToScriptHash(multisig_args[0], unhex=True), multisig_args[1], multisig_args[2]) wallet.AddContract(verification_contract) if self.Type == b'\xd1' and not self.SOURCE_SCRIPTHASH: # in case of an invocation with no funds transfer context = ContractParametersContext(self) elif not self._context: # used during transactions involving a funds transfer signer_contract = wallet.GetContract(self.SOURCE_SCRIPTHASH) context = ContractParametersContext( self, isMultiSig=signer_contract.IsMultiSigContract) else: context = self._context # used for a follow-on signature for a multi-sig transaction wallet.Sign(context) if context.Completed: self.scripts = context.GetScripts() self.Validate() # ensure the tx is ready to be relayed elif context.ContextItems: self._context = context print( "Transaction initiated, but the signature is incomplete. Sign again with another valid multi-sig keypair." ) else: raise SignatureError("Unable to sign transaction.") wallet.Close() wallet = None os.remove(temp_path)
def test_b(self): key = KeyPair(priv_key=self.pk) contract = Contract.CreateSignatureContract(key.PublicKey) self.assertEqual(binascii.unhexlify(contract.Script), self.contract_script) self.assertEqual(contract.ScriptHash.ToBytes(), self.contract_script_hash) self.assertEqual(contract.Address, self.contract_address) self.assertEqual(contract.PublicKeyHash, key.PublicKeyHash) self.assertEqual(contract.PublicKeyHash.ToBytes(), self.pubkeyhash)
def CreateKey(self, private_key=None): """ Create a KeyPair Args: private_key (iterable_of_ints): (optional) 32 byte private key Returns: KeyPair: a KeyPair instance """ if private_key is None: private_key = bytes(Random.get_random_bytes(32)) key = KeyPair(priv_key=private_key) self._keys[key.PublicKeyHash.ToBytes()] = key return key
def test_should_throw_error_on_invalid_checksum(self): # build fake wif fakewif = bytearray(34 * 'A', 'utf8') fakewif[0] = 0x80 fakewif[33] = 0x01 # fake checksum fakewif.append(0xDE) fakewif.append(0xAD) fakewif.append(0xBE) fakewif.append(0xEF) encodedFakeWIF = base58.b58encode(bytes(fakewif)) with self.assertRaises(ValueError) as context: KeyPair.PrivateKeyFromWIF(encodedFakeWIF) self.assertEqual('Invalid WIF Checksum!', str(context.exception))
def test_sign_before_KeyPair(self): # test signing prior to initializing secp256r1 Elliptic curve parameters with Keypair message = binascii.hexlify(b'Hello World') signature = Crypto.Sign( message, '8631cd2635c416ba5f043561e9d2ff40b79c3bb2eb245e176615298b8372d0a4') key = KeyPair( bytes.fromhex( '8631cd2635c416ba5f043561e9d2ff40b79c3bb2eb245e176615298b8372d0a4' )) self.assertTrue( Crypto.VerifySignature(message, signature, key.PublicKey)) TestSigningWithoutCryptoInstance.sig2 = signature.hex() # ensure the signatures are identical self.assertEqual(TestSigningWithoutCryptoInstance.sig1, TestSigningWithoutCryptoInstance.sig2)
def test_get_contains_key_should_not_be_found(self): wallet = Wallet("fakepath", to_aes_key("123"), True) wallet.CreateKey() keypair = KeyPair(priv_key=self.pk) self.assertFalse(wallet.ContainsKey(keypair.PublicKey))
def main(): parser = argparse.ArgumentParser( description= 'A utility for signing messages. Example usage: "np-sign mymessage --wallet_file path/to/my/wallet" or use an NEP2 key/passphrase like "np-sign mymessage -n"' ) parser.add_argument('message', type=str, help='The message in string format to be signed') parser.add_argument( '-w', '--wallet_file', type=str, default=None, help='If using a wallet file, the path to the wallet file') parser.add_argument( '-a', '--address', type=str, default=False, help= 'If using a wallet file with more than 1 address, the address you would like to use. Otherwise the default address will be used' ) parser.add_argument( '-n', '--nep2', action='store_true', help="Whether to use an NEP2 passhrase rather than a wallet") parser.add_argument('--wif', type=str, default=None, help='If using a wif pass in the wif') args = parser.parse_args() try: if args.wallet_file: passwd = prompt('[Wallet password]> ', is_password=True) wallet = UserWallet.Open(args.wallet_file, to_aes_key(passwd)) contract = wallet.GetDefaultContract() if args.address: addr = args.address script_hash = Helper.AddrStrToScriptHash(addr) contract = wallet.GetContract(script_hash) if contract is None: raise Exception('Address %s not found in wallet %s ' % (addr, args.wallet_file)) print("Signing With Address %s " % contract.Address) signature, pubkey = wallet.SignMessage(args.message, contract.ScriptHash) pubkey = pubkey.encode_point().decode('utf-8') signature = signature.hex() print("pubkey, sig: %s %s " % (pubkey, signature)) elif args.nep2: nep2_key = prompt('[nep2 key]> ', is_password=True) nep2_passwd = prompt("[nep2 key password]> ", is_password=True) prikey = KeyPair.PrivateKeyFromNEP2(nep2_key, nep2_passwd) keypair = KeyPair(priv_key=prikey) contract = Contract.CreateSignatureContract(keypair.PublicKey) print("Signing With Address %s " % contract.Address) signature = Crypto.Sign(args.message, prikey) pubkey = keypair.PublicKey.encode_point().decode('utf-8') signature = signature.hex() print("pubkey, sig: %s %s " % (pubkey, signature)) elif args.wif: prikey = KeyPair.PrivateKeyFromWIF(args.wif) keypair = KeyPair(priv_key=prikey) contract = Contract.CreateSignatureContract(keypair.PublicKey) print("Signing With Address %s " % contract.Address) signature = Crypto.Sign(args.message, prikey) pubkey = keypair.PublicKey.encode_point().decode('utf-8') signature = signature.hex() print("pubkey, sig: %s %s " % (pubkey, signature)) except Exception as e: print("Could not sign: %s " % e)
def test_should_throw_error_on_too_short_nep2_key(self): with self.assertRaises(ValueError) as context: KeyPair.PrivateKeyFromNEP2('invalid', 'pwd') self.assertIn('Please provide a nep2_key with a length of 58 bytes', str(context.exception))
def test_wrong_private_key_length(self): priv_key = b'\xDE\xAD\xBE\xEF' with self.assertRaises(ValueError) as context: KeyPair(priv_key) self.assertEqual('Invalid private key', str(context.exception))
def test_should_throw_error_on_invalid_nep2_key(self): with self.assertRaises(ValueError) as context: KeyPair.PrivateKeyFromNEP2(58 * 'A', 'pwd') self.assertEqual('Invalid nep2_key', str(context.exception))