Library / SDK
bitcoin-core/secp256k1 avatar
bitcoin-core/secp256k1

bitcoin-core/secp256k1: the C library behind Bitcoin's signatures

Optimized C library for EC operations on curve secp256k1

2,484 stars1,173 forksCMIT

At a glance

What is it?
A build-and-adoption guide to libsecp256k1, the MIT-licensed C library for ECDSA, Schnorr, MuSig2, ECDH and Silent Payments on the secp256k1 curve, including how to install it, its optional modules and where its interface stops being a good fit.
Who is it for?
Adopt libsecp256k1 when you need secp256k1 primitives at C speed with no runtime dependencies, and you are prepared to build it yourself and call its C API directly. Do not adopt it as a general-purpose crypto toolkit: it is not a TLS stack, it is not a Bitcoin wallet, and the README warns that usage unlike Bitcoin's may be less well tested.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 1 day ago.
What is it written in?
Mainly C, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 29, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What libsecp256k1 is, and who it is for

The README describes the project in one line: a high-performance high-assurance C library for digital signatures and other cryptographic primitives on the secp256k1 elliptic curve. The curve is the one Bitcoin uses, and the README is explicit that the primary focus of development has been usage in the Bitcoin system. That sentence is also the project's own warning: usage unlike Bitcoin's may be less well tested, verified, or suffer from a less well thought out interface.

So the audience is narrow and technical. You are writing a C or C++ application that needs ECDSA signing and verification, key generation, key tweaking, ECDH, BIP-340 Schnorr signatures, BIP-327 MuSig2 multi-signatures, BIP-324 ElligatorSwift key exchange, or BIP-352 Silent Payments, and you want those primitives implemented on the secp256k1 curve without pulling in a runtime dependency. The library states it exposes only higher level interfaces to minimize the API surface, with the stated goal of being difficult to use insecurely. It is not a wallet, not a node, not a transport protocol. It is the arithmetic and the signature schemes underneath them.

How the implementation is put together

The README's implementation details section is unusually concrete, and it is the best evidence of what the code actually does. Field arithmetic is implemented two ways: 5 52-bit limbs, and 10 26-bit limbs with hand-optimized assembly for 32-bit ARM. The README calls the 26-bit path experimental and says it has not received enough scrutiny to satisfy the library's own standard of quality. That is a real boundary: if you build for 32-bit ARM, you are on a path the maintainers describe as available for testing and review rather than as production-grade.

Scalar arithmetic avoids data-dependent branches and uses either 4 64-bit limbs relying on __int128 support in the compiler, or 8 32-bit limbs. Modular inverses for both field elements and scalars are based on safegcd, with a variable-time variant credited to Peter Dettman. Group operations use a point addition formula simplified for the curve equation y^2 = x^3 + 7, mix Jacobian and affine coordinates, and use a unified addition/doubling formula where necessary to avoid data-dependent branches. Point comparison avoids a field inversion by comparing in Jacobian coordinate space.

Verification multiplication (a*P + b*G) uses wNAF notation, a much larger window for multiples of G with precomputed multiples, Shamir's trick to multiply the public key and the generator simultaneously, and secp256k1's efficiently-computable endomorphism to split the P multiplicand into two half-sized ones. Signing multiplication uses a precomputed table of multiples of powers of 16 multiplied with the generator, so general multiplication becomes a series of additions. The table is accessed with branch-free conditional moves so memory access is uniform, and the README states the intent is to be completely free of timing sidechannels for secret-key operations on reasonable hardware and toolchains. There is optional runtime blinding that attempts to frustrate differential power analysis, and the precomputed tables add and eventually subtract points for which no known scalar is known, so an attacker with control over the secret key cannot control the internal data. Note the hedging: the sidechannel claim is scoped to reasonable hardware and toolchains, not to every platform.

Building with Autotools and running the test suite

The README's Autotools path is short. Run autogen.sh to generate the configure script, configure to generate the build system, make to build, make check to run the test suite, and optionally sudo make install to install into the system. The test suite is not decoration here: the README lists extensive testing infrastructure as a general implementation detail, and make check is the only way to confirm the build on your platform behaves.

bash
./autogen.sh       # Generate a ./configure script
./configure        # Generate a build system
make               # Run the actual build process
make check         # Run the test suite
sudo make install  # Install the library into the system (optional)

Optional modules are off unless you ask for them. The README says that to compile optional modules such as Schnorr signatures you run configure with additional flags such as --enable-module-schnorrsig, and that configure --help lists the full set. So a first real use looks like this: configure with the modules your application needs, build, run the tests, then link against the installed library.

bash
./configure --enable-module-schnorrsig
make
make check

If you prefer CMake, the README notes that CMake encourages an out-of-source build using a separate dedicated build tree, to maintain a pristine source tree. The repository carries CMakeLists.txt and CMakePresets.json at the top level, and the README section on CMake is where the exact invocation lives. Whichever build system you pick, do not skip make check on a new platform; the arithmetic paths differ by compiler and word size.

Working from examples rather than from the header alone

The repository ships an examples directory with ecdsa.c, ecdh.c, schnorr.c, musig.c, ellswift.c, silentpayments.c, a shared examples_util.h, plus examples/CMakeLists.txt and examples/EXAMPLES_COPYING. For anyone learning the API, those files matter more than the README, which is a build and verification document rather than an API tutorial. The README does not walk through signing a message or parsing a public key. It tells you what the library does and how to build it, then stops.

That is a deliberate shape, and it has a cost. The library exposes higher-level interfaces on purpose, but it still hands you opaque objects and expects you to manage contexts and serialization correctly. If you are coming from a language binding, expect to spend your first hour in examples/ and include/ rather than in prose. The examples also carry their own copying file, so if you copy code out of them, read EXAMPLES_COPYING before you paste.

Verifying the release tag before you build

The README has a dedicated Obtaining and verifying section, and it is the strongest argument for taking this project seriously. The git tag for each release, for example v0.6.0, is GPG-signed by one of the maintainers. The recommended flow is to obtain the repository via git, obtain the GPG keys of the signing maintainers, and verify the release tag's signature with git. The steps are: get the GPG keys listed in SECURITY.md, cross-reference those key IDs against another source controlled by the owner such as social media or a personal website, clone the repository, check out the latest release tag, and run git tag -v.

bash
git clone https://github.com/bitcoin-core/secp256k1
git checkout v0.7.1
git tag -v v0.7.1 | grep -C 3 'Good signature'

The README shows the expected output: a Good signature line from Pieter Wuille, an RSA key, and a warning that the key is not certified with a trusted signature. That warning is normal and is exactly why step two exists. Cross-referencing the fingerprint out of band is the part people skip, and it is the part that makes the signature meaningful. The current release line is v0.8.0, published on 2026-08-03, following v0.7.1 on 2026-01-26 and v0.7.0 on 2025-07-21. The last push to the repository was on 2026-09-25. The repository is not archived.

Where libsecp256k1 is the wrong tool

Start with the project's own disclaimer, because it is stronger than most: the primary focus has been Bitcoin, and non-Bitcoin usage may be less well tested or less well verified. If you are implementing a protocol that uses secp256k1 in a way Bitcoin does not, you are on ground the maintainers do not claim to have covered.

The second limitation is the interface itself. The README states that correct usage requires some care and consideration that the library is fit for your application's purpose. This is a C library with no runtime dependencies, no heap allocation, and no floating point. That profile is excellent for embedded systems and for a Bitcoin node, and it is a poor fit if you wanted a managed runtime to handle key lifetimes for you. There is no key store, no policy layer, no serialization format beyond the primitives.

The third is the experimental 32-bit ARM field path, which the README says has not received enough scrutiny to meet the library's standard. If your target is 32-bit ARM and you need the highest assurance, that is a reason to look hard at the build configuration rather than assume parity with the 64-bit path. Finally, if you need a general-purpose TLS or messaging stack, this library is not one: it provides curve operations and signature schemes, and nothing above them.

Alternatives and how they differ in approach

If you are writing Rust, the related searches point at a Rust binding rather than at this C library, and the difference is real: a binding wraps the same curve arithmetic behind Rust's type system and ownership rules, which removes a class of memory mistakes at the cost of an FFI boundary and a dependency on the underlying C build. If you are writing Python, the same applies in the other direction: a Python binding is convenient for scripting and testing, but the constant-time guarantees the README describes for signing apply to the C implementation, and a scripting layer is the wrong place to hold long-lived secret keys.

The other real comparison is the curve itself. secp256k1 versus secp256r1 (also called prime256v1 or NIST P-256) is a choice of parameters, not of library. P-256 is the NIST curve and is what most TLS deployments use; secp256k1 is the curve Bitcoin uses, and this library is built specifically around its equation and its efficiently-computable endomorphism. If your protocol already specifies P-256, libsecp256k1 is not an option at all, because it implements one curve. If your protocol specifies secp256k1 and you are in C, the realistic alternative is a general cryptographic library that also happens to support the curve, and the trade-off is that you take on a much larger dependency surface in exchange for not building this one yourself.

Licence, maintenance and upgrade cost

The licence is MIT, and the top level carries a COPYING file alongside it. MIT is permissive: it allows use in closed products with attribution and without a copyleft obligation on your own code. That is a statement about the licence text, not legal advice, and the examples directory carries a separate EXAMPLES_COPYING file, so code lifted from examples/ should be checked against that file rather than assumed to be under the same terms as the library itself.

On maintenance, the evidence is the release cadence and the last push. v0.8.0 landed on 2026-08-03, v0.7.1 on 2026-01-26, v0.7.0 on 2025-07-21, and the last push to the repository was on 2026-09-25. The repository is not archived. The upgrade cost is concentrated in two places. First, optional modules are compile-time flags, so moving to a new release can change which modules are enabled if your build script drifts from the defaults. Second, this is a C library with an interface the maintainers deliberately keep small, and small interfaces still change: the CHANGELOG.md at the top level is the file to read before bumping a pinned version, and the test suite is the check to run after.

Editorial conclusion

Adopt libsecp256k1 when you need secp256k1 primitives at C speed with no runtime dependencies, and you are prepared to build it yourself and call its C API directly. Do not adopt it as a general-purpose crypto toolkit: it is not a TLS stack, it is not a Bitcoin wallet, and the README warns that usage unlike Bitcoin's may be less well tested. Before writing code, verify the GPG signature on the release tag with git tag -v, and check that the module you need (for example --enable-module-musig) is actually built, because optional modules are off by default.

Frequently asked questions

How do I install bitcoin-core/secp256k1?

The README gives an Autotools path: run ./autogen.sh, then ./configure, then make, then make check, and optionally sudo make install. Optional modules require configure flags such as --enable-module-schnorrsig, and configure --help lists the full set.

What is bitcoin-core/secp256k1?

It is a high-performance high-assurance C library for digital signatures and other cryptographic primitives on the secp256k1 elliptic curve, with no runtime dependencies and no runtime heap allocation. The README states its primary development focus has been usage in the Bitcoin system.

Is bitcoin-core/secp256k1 secure?

The README states that signing is intended to be completely free of timing sidechannels for secret-key operations on reasonable hardware and toolchains, using branch-free conditional moves and no data-dependent branches, with optional runtime blinding against differential power analysis. It also warns that usage unlike Bitcoin's may be less well tested or verified.

How does bitcoin-core/secp256k1 compare with prime256v1 or NIST P-256?

The difference is the curve, not the library: secp256k1 is the curve Bitcoin uses and the one this library implements, while prime256v1 (NIST P-256) is a different set of curve parameters used widely in TLS. libsecp256k1 implements one curve, so if your protocol specifies P-256 it is not an option.

Is bitcoin-core/secp256k1 quantum resistant?

The README makes no quantum-resistance claim: it describes ECDSA, Schnorr signatures, ECDH, MuSig2, ElligatorSwift and Silent Payments on the secp256k1 elliptic curve, all of which rest on elliptic curve discrete logarithms. Nothing in the README addresses post-quantum security.

Official sources

  1. bitcoin-core/secp256k1 on GitHub
  2. Issues
  3. License: MIT
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/bitcoin-core-secp256k1.svg)](https://hysenlabs.com/projects/bitcoin-core-secp256k1)