def sign(msg_hash: bytes, priv_key: bytes) -> bytes: ''' Sign the message hash. (not the message itself) Parameters ---------- msg_hash: bytes The message hash. priv_key: bytes The private key in bytes. Returns ------- bytes The signing result. Raises ------ ValueError If the input is malformed. ''' if not _is_valid_private_key(priv_key): raise ValueError('Private Key not valid.') sig = KeyAPI().ecdsa_sign(msg_hash, KeyAPI.PrivateKey(priv_key)) r = sig.r.to_bytes(32, byteorder='big') s = sig.s.to_bytes(32, byteorder='big') v = sig.v.to_bytes(1, byteorder='big') # public key recovery bit. return b''.join([r, s, v]) # 32 + 32 + 1 bytes
def _sign(seq, to, value, data, key): keys = KeyAPI() comb = seq.to_bytes(32, "big") + b'\x00' * 12 + to + value.to_bytes(32, "big") + data h1 = keccak(comb) h2 = keccak(b"\x19Ethereum Signed Message:\n32" + h1) sig = keys.ecdsa_sign(h2, key) return [28 if sig.v == 1 else 27, sig.r, sig.s]
def verify_msg_hash(msg_hash, signature, public_key): log.debug('message=%s type %s', msg_hash, type(msg_hash)) log.debug('public_key=%s type %s', public_key, type(public_key)) log.debug('signature=%s type %s', signature, type(signature)) signature = KeyAPI.Signature(bytes.fromhex(signature)) public_key = KeyAPI.PublicKey(bytes.fromhex(public_key)) return signature.verify_msg_hash(msg_hash, public_key)
def get_default_account_keys(quantity=None): keys = KeyAPI() quantity = quantity or 10 for i in range(1, quantity + 1): pk_bytes = int_to_big_endian(i).rjust(32, b'\x00') private_key = keys.PrivateKey(pk_bytes) yield private_key
def init_signature(sig): if isinstance(sig, str): if sig[0:2] == "0x": sig = sig[2:] sig = bytes.fromhex(sig) return IdleSignature(sig) if isinstance(sig, str): if sig[-2:] != '01' and sig[-2:] != '00': sig = hex(int(sig, 16) - 27) try: sig = KeyAPI.Signature(HexBytes(sig)) except Exception: raise TypeError(str(type(sig)) + "is not verifiable signature") elif isinstance(sig, bytes): if sig[-1] != 1 and sig[-1] != 0: sig = bytestoint(sig) sig -= 27 sig = HexBytes(hex(sig)) try: sig = KeyAPI.Signature(sig) except Exception: raise TypeError(str(type(sig)) + "is not verifiable signature") elif not isinstance(sig, KeyAPI.Signature): raise TypeError(str(type(sig)) + "is not verifiable signature") return sig
def getPublicKey(transaction, signature): s = Signature(signature_bytes=bytes.fromhex(signature)) txID = hashlib.sha256(bytes.fromhex(transaction)).digest() keys = KeyAPI('eth_keys.backends.NativeECCBackend') public_key = keys.ecdsa_recover(txID, s) logger.debug(' PublicKey: {}'.format(public_key)) return public_key
def get_default_account_keys(): keys = KeyAPI() for i in range(1, 11): pk_bytes = int_to_big_endian(i).rjust(32, b'\x00') private_key = keys.PrivateKey(pk_bytes) yield private_key
def customer_private_key(): from eth_keys import KeyAPI from eth_utils import int_to_big_endian keys = KeyAPI() pk_bytes = int_to_big_endian(2).rjust(32, b'\x00') private_key = keys.PrivateKey(pk_bytes) return private_key
def verify(msghash: bytes, signature, public_key): """Verify that data has been signed with Etheruem private key. :param signature: :return: """ key_api = KeyAPI('eth_keys.backends.NativeECCBackend') return key_api.ecdsa_verify(msghash, Signature(signature), PublicKey(public_key))
def get_account_keys_from_mnemonic(mnemonic, quantity=None): keys = KeyAPI() seed = seed_from_mnemonic(mnemonic, "") quantity = quantity or 10 for i in range(0, quantity): hd_path = HDPath(f"m/44'/60'/0'/{i}") private_key = keys.PrivateKey(hd_path.derive(seed)) yield private_key
def validate(transaction, signature, public_key): try: s = Signature(signature_bytes=signature) txID = hashlib.sha256( bytes.fromhex(transaction) if type(transaction) is str else transaction).digest() keys = KeyAPI('eth_keys.backends.NativeECCBackend') publicKey = PublicKey(bytes.fromhex(public_key)) return keys.ecdsa_verify(txID, s, publicKey), txID.hex() except: return False, ""
def set_key_backend(self, backend): """ Change the backend used by the underlying eth-keys library. *(The default is fine for most users)* :param backend: any backend that works in `eth_keys.KeyApi(backend) <https://github.com/ethereum/eth-keys/#keyapibackendnone>`_ """ self._keys = KeyAPI(backend)
def pub_bytes_to_eth_address(var): pub=var if len(pub) == 65: if pub[0] != 4: raise InvalidKey("unrecognised public key format for key: {}".format(pub)) pub=pub[1:] if len(pub) != 64: #print("Uncompressing pub: {}".format(pub)) pub = uncompress(pub) pk = KeyAPI().PublicKey(pub) return pk.to_checksum_address()
def verify_signature(signature_hex: str, message_bytes: bytes, public_key_hex: str): """Returns True for a valid signature. Args: signature (str) -- hex string message (bytes) public_key (str) -- hex string """ signature_bytes = bytes.fromhex(signature_hex) signature = KeyAPI.Signature(signature_bytes=signature_bytes) pk_bytes = bytes.fromhex(public_key_hex[2:]) pk = KeyAPI.PublicKey(pk_bytes) return signature.verify_msg(message_bytes, pk)
def recoverHash(message_hash, signature): """ :param message_hash: 32-bytes string :param signature: 130-length string without '0x' :return: """ if isinstance(signature, bytes): signature = signature.decode() signature = signature.replace('0x', '') publick_key = KeyAPI().ecdsa_recover(message_hash, Signature(binascii.a2b_hex(signature))) return checksum_encode(publick_key.to_address())
def test(): priv = KeyAPI.PrivateKey( bytes.fromhex( "208065a247edbe5df4d86fbdc0171303f23a76961be9f6013850dd2bdc759bbb") ) addr = priv.public_key.to_canonical_address() assert addr == b"\x0b\xedz\xbda$v5\xc1\x97>\xb3\x84t\xa2Qn\xd1\xd8\x84"
def verify_signature(message, signature, public_key=None): """ If public_key provided, return true or false if valid If public_key is None, return recovered public key from signature @param message bytes @param signature bytes b'abc\t0\abcd\...' @param public_key bytes b'abc\t0\abcd\...' or None """ # print('message=', message, type(message)) # print('public_key=', public_key, type(public_key)) # print('signature=', signature, type(signature)) signature = signature.decode() if isinstance(message, str): message = message.encode() log.debug('Verify_signature message %s', message) signature = KeyAPI.Signature(bytes.fromhex(signature)) recovered_pk = signature.recover_public_key_from_msg(bytes(message)) recovered_pk = recovered_pk.to_hex() log.debug('Recovered public key %s', recovered_pk) if public_key is None: return recovered_pk return public_key == recovered_pk
def verify_signature(self, public_key: KeyAPI.PublicKey): try: return public_key.verify_msg_hash( self.get_hash(), KeyAPI.Signature(signature_bytes=self.signature) ) except eth_keys.exceptions.BadSignature: return False
def from_public_key(pub: bytes, chain_code: bytes): ''' Construct an HD Node from an uncompressed public key. (starts with 0x04 as first byte) Parameters ---------- pub : bytes An uncompressed public key in bytes. chain_code : bytes 32 bytes Returns ------- HDNode A new HDNode. ''' # parts net_version = VERSION_MAINNET_PUBLIC depth = DEPTH_MASTER_NODE fprint = FINGER_PRINT_MASTER_KEY index = CHILD_NUMBER_MASTER_KEY chain = chain_code key_bytes = KeyAPI.PublicKey(strip_0x04(pub)).to_compressed_bytes() # assemble all_bytes = net_version + depth + fprint + index + chain + key_bytes # double sha-256 checksum xpub_str = Base58Encoder.CheckEncode(all_bytes) bip32_ctx = Bip32.FromExtendedKey(xpub_str) return HDNode(bip32_ctx)
def federated_address(self) -> str: signature_pubkey = self.signing_public_key uncompressed_bytes = signature_pubkey.to_bytes(is_compressed=False) without_prefix = uncompressed_bytes[1:] verifying_key_as_eth_key = EthKeyAPI.PublicKey(without_prefix) address = verifying_key_as_eth_key.to_checksum_address() return to_checksum_address(address)
def verify_sig_msg(self, message: bytes, signature: bytes, pubkey: bytes): """ Verifies that message has been signed by pubkey Args: message: bytes of message to verify signature: bytes of signature to verify pubkey: public key that signed this message Returns: Boolean (True if signature is valid) """ log.debug('from verify_sig_msg message=%s type=%s', message, type(message)) public_key = KeyAPI.PublicKey(pubkey) sig = KeyAPI.Signature(signature) return sig.verify_msg(message, public_key)
def derive_federated_address(self): if self.federated_only: verifying_key = self.public_keys(SigningPower) uncompressed_bytes = verifying_key.to_bytes(is_compressed=False) without_prefix = uncompressed_bytes[1:] verifying_key_as_eth_key = EthKeyAPI.PublicKey(without_prefix) federated_address = verifying_key_as_eth_key.to_checksum_address() else: raise RuntimeError('Federated address can only be derived for federated characters.') return federated_address
def get_publickey_from_address(web3, address): _hash = Web3.sha3(text='verify signature.') signature = split_signature(web3, web3.eth.sign(address, _hash)) signature_vrs = Signature(signature.v % 27, big_endian_to_int(signature.r), big_endian_to_int(signature.s)) prefixed_hash = prepare_prefixed_hash(_hash) pub_key = KeyAPI.PublicKey.recover_from_msg_hash( prefixed_hash, KeyAPI.Signature(vrs=signature_vrs)) assert pub_key.to_checksum_address( ) == address, 'recovered address does not match signing address.' return pub_key
def test_signature(self): header = RootBlockHeader() private_key = KeyAPI.PrivateKey(Identity.create_random_identity().get_key()) self.assertEqual(header.signature, bytes(65)) self.assertFalse(header.is_signed()) self.assertFalse(header.verify_signature(private_key.public_key)) header.sign_with_private_key(private_key) self.assertNotEqual(header.signature, bytes(65)) self.assertTrue(header.is_signed()) self.assertTrue(header.verify_signature(private_key.public_key))
def get_sender(signature, message): """ @param signature bytes @param message bytes """ if isinstance(signature, bytes): signature = KeyAPI.Signature(signature) if not isinstance(message, bytes): message = bytes(message) return signature.recover_public_key_from_msg(message)
def __init__(self, private_key): """Work with private key. Getting: PublicKey, PublicToAddress Example::: PrivateKey("4d1bc37b069b9f2e975c37770b7c87185dc3a10454e3ea024ce1fce8f3eb78bf") """ _private = unhexlify(bytes(private_key, encoding='utf8')) self._key = KeyAPI.PrivateKey(_private) # Key length must not exceed 64 length assert len(repr(self._key)) != 64
def root_signer_private_key(self) -> Optional[KeyAPI.PrivateKey]: if self._cached_root_signer_private_key: return self._cached_root_signer_private_key # cache miss ret = None if self.ROOT_SIGNER_PRIVATE_KEY: # make sure private key and public key match # noinspection PyCallByClass privkey = KeyAPI.PrivateKey( private_key_bytes=bytes.fromhex(self.ROOT_SIGNER_PRIVATE_KEY)) ret = privkey self._cached_root_signer_private_key = ret return ret
def address(self): ''' Get the checksummed address of this hd account :returns: the checksummed public address for this account. :rtype : str .. code-block:: python >>> my_account.address "0xF0109fC8DF283027b6285cc889F5aA624EaC1F55" ''' rawtuple = bip32_deserialize(self.__key) key = rawtuple[-1] if rawtuple[0] in PRIVATE: # slice the last byte, since it is the WIF-Compressed information key = KeyAPI.PrivateKey(key[:-1]).public_key else: # remove 04 prefix for KeyAPI key = KeyAPI.PublicKey(decompress(key)[1:]) return key.to_checksum_address()
def sign(self, keys): """ Sign the transaction with keys. It doesn't mean the transaction is valid in the chain since it doesn't check whether the tx_input's addresses (recipents) match the keys """ sign_list = [] for key in keys: sig = KeyAPI.PrivateKey(key).sign_msg(self.get_hash_unsigned()) sign_list.append( sig.r.to_bytes(32, byteorder="big") + sig.s.to_bytes(32, byteorder="big") + sig.v.to_bytes(1, byteorder="big")) self.sign_list = sign_list return self
def verify_signature(self, recipients): """ Verify whether the signatures are from a list of recipients. Doesn't verify if the transaction is valid on the chain """ if len(recipients) != len(self.sign_list): return False for i in range(len(recipients)): sig = KeyAPI.Signature(signature_bytes=self.sign_list[i]) pub = sig.recover_public_key_from_msg(self.get_hash_unsigned()) if pub.to_canonical_address() != recipients[i]: return False return True