Skip to main content

A Python library for 'bitcoin cryptography'

PyPI version GitHub release development status license downloads supported Python versions implementation wheel

pre-commit.ci status lint workflow status test workflow status docs workflow status documentation build vendored-vectors workflow status mutation workflow status fuzz workflow status integration-bitcoind workflow status deps-latest workflow status pypi-install workflow status deps-oldest workflow status py-arm-authority workflow status os-macos workflow status os-ubuntu workflow status os-windows workflow status links workflow status sdist-rebuild workflow status codeql workflow status

OpenSSF Scorecard OpenSSF Best Practices OpenSSF Baseline


btclib is a Python type annotated library for teaching, learning and using bitcoin, focused on elliptic curve cryptography and bitcoin's blockchain. It started as a teaching tool for Ferdinando Ametrano's Bitcoin and Blockchain Technology course, it is used in production today (still marked as beta because it is often refactored for improved clarity — CONTRIBUTING.md's Breaking a caller is not an argument says what that promises a caller and what it does not).

The test suite covers virtually the whole code base, a floor the build enforces, and it answers to vectors their authors publish: the BIPs' own and Bitcoin Core's script, transaction, sighash and key-encoding files. tests/_data/README.md pins each vendored file to the upstream commit it was copied from, and says whether the two still match — including the few vectors that are btclib's own, having no upstream. The elliptic curve schemes are answered for by btclib_ecc's suite, with the vectors RFC 6979 and the BIPs publish for them.

The library is not limited to secp256k1, and for that curve it delegates to btclib-secp256k1, FFI bindings to Bitcoin Core's optimized C library libsecp256k1, wherever a call's own guard admits them. They are the recommended install and what pip install "btclib[secp256k1]" asks for, needing one of their wheels or a C toolchain; without them, or with the delegation turned off in a process that has them, btclib still answers, on the Python arithmetic, tens of times more slowly and not in constant time — SECURITY.md publishes both. That Python arithmetic serves every other curve anyway, and the suite validates it against the bindings: libsecp256k1 says what the right answer is, being what bitcoin consensus relies on.

Included features are:

  • octets / integer / var_int / var_bytes helper functions
  • ECDSA message signatures with compact encoding: standard p2pkh and BIP137/Electrum extensions to p2wpkh and p2wpkh-p2sh
  • the x-only ECDH of BIP324, over the ElligatorSwift encoding of a public key
  • Base58 encoding/decoding
  • p2pkh/p2sh addresses and WIFs
  • Bech32 encoding/decoding
  • p2wpkh/p2wsh native segwit addresses and their legacy p2sh-wrapped versions
  • Script encoding/decoding
  • nulldata, p2pk, p2ms, p2pkh, p2sh, p2wpkh, p2wsh and p2tr ScriptPubKeys
  • a script engine: a transaction verified against the consensus rules, legacy, segwit and tapscript, with Bitcoin Core's own vectors behind it
  • OutPoint, TxIn, TxOut, and TX data classes
  • legacy, segwit_v0 and taproot transaction hash signatures
  • BlockHeader and Block data classes
  • merkle proofs verified against a header's merkle root
  • proof-of-work arithmetic: compact targets, retargeting, work, hash rate
  • fee rates carrying their unit (sat/kvB, sat/vB, and the BTC/kvB Bitcoin Core quotes one in), the fee a virtual size owes at one, what a child owes for the unconfirmed ancestors it is mined with, and the dust threshold of any output type, computed as Bitcoin Core computes it rather than tabulated

The elliptic curve arithmetic and the schemes built on it are the btclib_ecc distribution, which btclib depends on and does not re-export: import them from btclib_ecc. It provides:

  • modulo algebra functions (gcd, inverse, legendre symbol, square root)
  • the elliptic curve class
    • fast algebra implemented using Jacobian coordinates
    • double scalar multiplication (Straus's algorithm, also known as Shamir's trick)
    • multi scalar multiplication (Bos-coster's algorithm)
    • point symmetry solution: odd/even, low/high, and quadratic residue
    • SEC 1 octet encodings of points
    • elliptic curves: SEC 1 v1 and v2, NIST, Brainpool, and low cardinality test curves
  • ECDSA signature with (transaction) DER encoding
  • RFC 6979 for deterministic signature schemes
  • EC Schnorr signature (according to BIP340 bitcoin standardization)
    • batch validation
    • threshold signature (FROST)
    • MuSig2 multi-signature: key aggregation with plain and x-only tweaking, nonce aggregation, partial signatures and their aggregation, one primitive per round of the protocol
  • Borromean ring signature
  • Sign-to-contract commitment
  • Diffie-Hellman
  • the ElligatorSwift encoding of a public key (BIP324)
  • BIP374 discrete logarithm equality proofs: 64 bytes proving that an ECDH shared secret was computed from the key that signed, without revealing that key, over an arbitrary generator and an optional message
  • ECIES in the BIE1 layout, the block cipher supplied by the caller
  • Pedersen commitment

The wallet side — key derivation, mnemonics, PSBTs, output descriptors, signers and chain backends — is the btclib-wallet distribution, imported as btclib_wallet, which depends on this one.


Secrets, and where constant time ends

btclib is used to teach and to prototype as much as to build, and the two uses want different things of it. What follows is the boundary between them, before a private key is handed to any of the above.

A Python object carrying secret material cannot be reliably zeroized: it stays in the process memory until garbage collection, and the interpreter may have copied it meanwhile. The constant-time properties are libsecp256k1's, and they hold on the C side of the call — not before it, and not after.

Not every operation crosses that call, and what decides is one predicate — a process-wide dispatch switch, secp256k1 as the curve, and sha256 or no hash function at all — with whatever further conditions the call site ands onto it. Those conditions differ from one function to the next, and SECURITY.md states each of them, for dsa.sign and ssa.sign alike. Whatever that conjunction declines runs the Python arithmetic, which the suite validates against the bindings but which is not constant-time. A process that has the bindings turns that switch off with btclib_ecc.curves.set_libsecp256k1_serving(serving=False), or with BTCLIB_ECC_NO_LIBSECP256K1 in the environment, and every operation here is then the Python arithmetic. So a caller whose threat model includes timing should stay on the delegated paths, or keep the key out of the process altogether: btclib_wallet.hwi drives a hardware wallet through HWI, behind the same PsbtSigner contract a software signer answers.

Crossing that call is not the same as constant time. A mult of a point you supplied, the shared point of a key agreement among them, crosses into libsecp256k1's constant-time multiplication; double_mult_var and multi_mult_var cross into the variable-time one their suffix names, so a secret handed to them carries no timing guarantee on the delegated path either. SECURITY.md has the accounting, and which call a multiplication takes is part of it.

What that path does about it is in the names, and it is worth knowing before calling one. A function whose duration follows the value it is given ends in _var, and the plain name beside it is the one a secret may be handed: mod_inv draws a random blinding factor where mod_inv_var is the bare extended Euclid, and mult makes the same additions for every scalar where double_mult_var does not. It is libsecp256k1's own convention, and forgetting to choose gives the safer call rather than the faster one.

The suffix is not a safety label, and no name here promises constant time. It says which of two spellings to reach for, and each one was measured rather than assumed — including the ones that kept a plain name, which CONTRIBUTING lists with the figure that earned it.

SECURITY's "Limitations, not vulnerabilities" states each condition exactly — which arguments delegate, which do not, and what the Python path does hide — and is the canonical text; this section is the pointer to it.


Module layout

ARCHITECTURE is the design: which module holds what, the import edges the tests hold, and the two arithmetic paths behind secp256k1.


To install, or upgrade:

python -m pip install --upgrade btclib

In a virtual environment:

python -m venv venv_btclib
source venv_btclib/bin/activate
python -m pip install --upgrade btclib

On Windows the second line is venv_btclib\Scripts\activate in CMD and PowerShell, source venv_btclib/Scripts/activate in Git bash.

CONTRIBUTING is for development, REVIEWING for what a pull request is answered against, SECURITY for reporting a vulnerability.

How the organization decides, and who holds which role, is its GOVERNANCE.md; what it intends to do, and what it deliberately does not, is its ROADMAP.md.


The btclib organization and its projects are actively supported by DGI and CheckSig.

Metadata

Release files for btclib 2026.10.4

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for btclib 2026.10.4
File Size Uploaded
btclib-2026.10.4.tar.gz 7.4 MB Details

Built distribution (wheel)

Table of built distributions (wheels) for btclib 2026.10.4
File Interpreter ABI Platform
btclib-2026.10.4-py3-none-any.whl Python 3 none any Details

Total release size: 7.8 MB

Release files / btclib-2026.10.4.tar.gz

Download URL btclib-2026.10.4.tar.gz
Size 7.4 MB
Tags Source
SHA-256 checksum
How to use checksums
4192c57e838497830e05c1cfc30ecf55023505b76246037e525ce5477cbe7096
BLAKE2b-256 checksum
How to use checksums
73df8aa7c2a3a48fc44a478dd00d44e6aee046e8913194700bacb3fd2d243978
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 3, 2026.

Transparency log

Release files / btclib-2026.10.4-py3-none-any.whl

Download URL btclib-2026.10.4-py3-none-any.whl
Size 432.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
364e7384f351859d9c19ff12ff3c951e7cf72eee7a04c52ba4ad0429081b6aa6
BLAKE2b-256 checksum
How to use checksums
e1b9746635fd0f5da2d805be2a89fec4bc7ef943de98c6262a182d3cf36a804f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 3, 2026.

Transparency log
Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page