Pure-Python Bitcoin key and address utilities. Zero runtime dependencies.
Every operation — secp256k1 scalar multiplication, RIPEMD-160, base58check — is implemented inside this package, so the whole codebase is auditable line by line and does not depend on any compiled extension or third-party library.
pip install git+https://github.com/cheran-senthil/bitcoin-keygen.git
Or clone and pip install -e . for a working copy. Requires Python 3.9+.
from bitcoin_keygen import PrivateKey, PublicKey, base58
# Generate a fresh random key.
k = PrivateKey.generate()
k.hex() # 64-char lowercase hex
k.wif(compressed=True) # WIF string
k.address(compressed=True) # P2PKH mainnet address
k.address(compressed=True, mainnet=False) # testnet address
k.public_key() # PublicKey instance
# Import from other formats.
PrivateKey.from_hex("0c28fc...aa1d")
PrivateKey.from_bytes(b"\\x0c...") # exactly 32 bytes
decoded = PrivateKey.from_wif("5HueCGU8rMjxEXxiPuD5BDku4MkFqeZyd4dZ1jvhTVqvbTLvyTJ")
decoded.private_key # PrivateKey
decoded.compressed # bool, taken from the WIF payload — never a caller argument
decoded.mainnet # bool, taken from the WIF version byte
# Public keys.
pub = PublicKey.from_hex("04d0de0aae...648cb0a")
pub.hex(compressed=True)
pub.address(mainnet=True)
# Base58Check codec (bytes-native).
base58.encode(b"\\x00" + b"\\x11" * 20) # → str
base58.decode(some_address) # → bytes, raises ValueError on bad checksumPrivateKey/PublicKeyvalidate at construction. There is no path to a derivation method with an invalid, out-of-range, or wrong-shape key.- WIF decoding takes compression and network from the payload itself. There is
no
compressedargument tofrom_wifthat could disagree with the string. base58.decodeverifies the double-SHA256 checksum and raisesValueErroron any tampered or mistyped string, so a single-character typo in a WIF is caught rather than silently producing a different private key.- secp256k1 scalar multiplication uses a Montgomery ladder (one add + one double per bit regardless of key bits) rather than double-and-add-only. Python's arbitrary-precision int operations are not themselves constant-time, so this is defense in depth, not a cryptographic guarantee.
- RIPEMD-160 is a pure-Python implementation of the FIPS-published algorithm, independent of OpenSSL — the library behaves identically on every Python build, including recent ones where OpenSSL's legacy provider is disabled.
pip install -e ".[test]"
pytest
Covers: base58check round-trips and error paths, secp256k1 arithmetic,
RIPEMD-160 against the spec's published vectors (including the 1M-a stress
test), the PrivateKey / PublicKey API surface, Bitcoin-wiki end-to-end
test vectors, and one regression test per pre-1.0 API bug.
GNU General Public License v3.0 (c) 2019 Cheran Senthilkumar