Bitcoin Magazine
The Core Issue: libsecp256k1, Bitcoin’s Cryptographic Heart
Common phrases heard among Bitcoiners include “don’t trust, verify” or “not your keys, not your coins”, sometimes even claiming that it’s “backed by math”. But what do these proverbs ultimately boil down to, and how exactly is this involved math put into practice? Most readers are surely aware that a fundamental ingredient in the design of Bitcoin is public-key cryptography and more specifically digital signatures, which are essential to prove ownership without needing a central entity. Probably less well-known is what piece of software is under the hood to make that elliptic curve math work and what efforts are involved to ensure that this happens in the most secure and performant way, with continuous improvements. Let’s dive into the exciting history and evolution of “libsecp256k1”, a library that started out as a small hobby project and over the years evolved into an essential part of consensus rules protecting a multi-trillion dollar asset.
The Genesis
For reasons we don’t know for sure, Satoshi picked an elliptic curve named “secp256k1” for creating and verifying digital signatures in Bitcoin. The initial version of the Bitcoin client was shipped using the widespread OpenSSL library for signing and verifying transactions. Relying on a third-party library sounds like a reasonable approach from a software engineering perspective (even more so if it is something as domain-specific and complex as elliptic-curve
cryptography), but this choice turned out to be problematic later due to inconsistencies in the signature parsing code. In the worst case, this could even lead to unintended chain splits. One lesson from that time period was that OpenSSL is not a suitable library for a consensus-critical system like Bitcoin. The issue was later fixed by BIP66, which ensured a strict encoding of ECDSA signatures. After that, the OpenSSL dependency was replaced with libsecp256k1 in Bitcoin Core v0.12, released in early 2016.1
But taking a step back, the initial motivation behind starting the libsecp256k1 project was mostly curiosity about a potential speed-up. Sometime in the year 2012, Bitcoin Core developer Pieter Wuille a.k.a. “sipa” stumbled upon a bitcointalk thread by Hal Finney (known for being the recipient of the very first Bitcoin transaction in 2009 from Satoshi).
Under the subject “Speeding up signature verification”, the post discussed an optimization that would make use of a so-called “endomorphism” (more specifically using the so-called GLV-method, Gallant-Lambert-Vanstone), something that only certain elliptic curves allow, secp256k1 conveniently being one of them. Hal Finney himself implemented it using OpenSSL primitives, it was later even submitted as a PR to Bitcoin Core.2 Even though it showed a solid
~20% speedup, it was never merged in the end due to concerns about increasing code complexity an
