eth-keys: Common API for Ethereum key operations
eth-keys is a Python library providing a common API for Ethereum key operations, including private key, public key, and signature management. It is currently at version 0.7.0 and is actively maintained by the Ethereum Foundation, with development hosted on GitHub.
Warnings
- breaking The library and PyPI package were renamed from `ethereum-keys` to `eth-keys` in November 2017. Ensure you are importing from `eth_keys` and not the old package name.
- gotcha For optimal performance, `eth-keys` defaults to using the `CoinCurveECCBackend` if the `coincurve` library is installed. However, `coincurve` is not automatically installed as a dependency and must be installed separately. If not installed, it falls back to the pure Python `NativeECCBackend`, which is slower.
- gotcha The `PublicKey` class constructor expects a 64-byte `bytes` string. Common public key formats like 65-byte (with a leading `\x04` byte) or 33-byte (compressed, starting with `\x02` or `\x03`) require pre-processing (e.g., stripping the first byte for 65-byte format or using `PublicKey.from_compressed_bytes`).
- gotcha A private key consisting of all zero bytes (`b'\x00' * 32`) is mathematically invalid for generating a public key in elliptic-curve cryptography. While an address might be derived and accept funds, any transaction signed with this 'private key' will be rejected by the network as having an 'invalid sender'.
- gotcha Never hardcode, commit to version control, or expose private keys directly in source code. Private keys are critical secrets that should be handled securely, ideally loaded from environment variables or a secure key management system.
Install
-
pip install eth-keys
Imports
- PrivateKey
from eth_keys import keys; pk = keys.PrivateKey(...)
- PublicKey
from eth_keys import keys; pub_key = keys.PublicKey(...)
- Signature
from eth_keys import keys; signature = keys.Signature(...)
- KeyAPI
from eth_keys import KeyAPI
Quickstart
from eth_keys import keys
# Generate a new private key (random bytes in a real scenario)
pk_bytes = b'\x01' * 32 # Example private key bytes
pk = keys.PrivateKey(pk_bytes)
# Get the public key
pub_key = pk.public_key
# Sign a message
message = b'a message'
signature = pk.sign_msg(message)
# Verify the signature
is_valid = signature.verify_msg(message, pub_key)
print(f"Private Key: {pk.to_hex()}")
print(f"Public Key: {pub_key.to_hex()}")
print(f"Ethereum Address: {pub_key.to_checksum_address()}")
print(f"Signature: {signature.to_hex()}")
print(f"Signature Valid: {is_valid}")
# Recover public key from signature
recovered_pub_key = signature.recover_public_key_from_msg(message)
print(f"Recovered Public Key Matches: {recovered_pub_key == pub_key}")