Install & Compatibility
Where this runs
tested against v8.0.0 · pip install
no network on importno background threads
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
muslpy 3.10–3.95 runs
installs and imports cleanly · install 0.0s · import 0.120s · 40.4MB
glibcpy 3.10–3.95 runs
installs and imports cleanly · install 3.8s · import 0.106s · 42MB
40MB installed
● package 40MB
Code
Verified usage
Verified import paths — ran on the pinned version, not inferred.
privtopub
✓ from py_ecc.secp256k1 import privtopub
✗ from py_ecc.secp256k1 import privtopub
ecsign
✓ from py_ecc.secp256k1 import ecsign
✗ from py_ecc.secp256k1 import ecsign
ecrecover
✓ from py_ecc.secp256k1 import ecrecover
✗ from py_ecc.secp256k1 import ecrecover
This quickstart demonstrates how to generate a secp256k1 private key, derive its public key, sign a message hash, and then verify the signature by recovering the public key.
import os
from py_ecc.secp256k1 import privtopub, ecsign, ecrecover, N
# 1. Generate a private key
# In a real application, use a cryptographically secure random source (e.g., from a KDF or secure RNG)
privkey = int(os.urandom(32).hex(), 16) % N
print(f"Private Key: {hex(privkey)}")
# 2. Derive the public key
pubkey = privtopub(privkey)
print(f"Public Key (uncompressed, X, Y tuple): {pubkey}")
# 3. Create a message hash (must be 32 bytes)
msg_hash = int.from_bytes(os.urandom(32), 'big')
print(f"Message Hash: {hex(msg_hash)}")
# 4. Sign the message
v, r, s = ecsign(msg_hash, privkey)
print(f"Signature: v={v}, r={hex(r)}, s={hex(s)}")
# 5. Recover the public key from the signature
recovered_pubkey = ecrecover(msg_hash, v, r, s)
print(f"Recovered Public Key: {recovered_pubkey}")
# 6. Verify the signature
assert recovered_pubkey == pubkey, "Signature verification failed!"
print("Signature verification successful!")
Debug
Known issues
breakingBLS (Boneh-Lynn-Shacham) signature scheme implementations have undergone significant breaking changes across major versions (e.g., v3.0.0, v5.0.0). These changes reflect updates to IETF BLS drafts (e.g., v2, draft 04).fixReview the specific IETF BLS draft version implemented in your `py-ecc` version. Existing BLS keys or signatures from older versions may be incompatible. Migrate data or adapt code to the new specification, particularly for hash-to-curve functions and signature aggregation.
affects: >=3.0.0
gotchaThe `v` (recovery identifier) value returned by `py_ecc.secp256k1.ecsign` is strictly 0 or 1. This differs from Ethereum's typical `v` values (27 or 28, or Chain ID-dependent 35/36+Chain ID), which are often used in transactions.fixWhen interfacing with other libraries or blockchain protocols, be aware that you might need to convert `py-ecc`'s `v` (0 or 1) to the expected format, e.g., by adding 27, or handling chain_id logic, before broadcasting. Conversely, `ecrecover` expects `v` to be in `(0, 1)` range, not `(27, 28)`.
affects: All versions
gotchaBLS hash-to-curve functions are highly sensitive to the exact IETF draft specification. Using a function from one version with data generated by another can lead to silent failures or invalid results due to differing parameters or algorithms.fixAlways ensure consistency between the `py-ecc` BLS implementation version and the specification used by the counterparty system. Consult the `py-ecc` source or documentation for the precise BLS draft version supported by your installed library version.
affects: All BLS-enabled versions
Upgrade
Version history
8.0.0latest on PyPI · released Apr 14, 2025
Audit
Dependencies
eth-hashrequiredProvides cryptographic hashing functionalities, often including Keccak-256 which is critical for Ethereum-related operations.