Top Related Projects
Fast Elliptic Curve Cryptography in plain javascript
Quick Overview
The bitcoin-core/secp256k1 repository is an optimized C library for elliptic curve operations on the secp256k1 curve. This curve is used in Bitcoin's public key cryptography and digital signature algorithms. The library provides high-performance implementations of various cryptographic operations essential for Bitcoin and other cryptocurrencies.
Pros
- Extremely optimized for performance, making it ideal for high-throughput cryptographic operations
- Extensively tested and audited, ensuring reliability and security
- Designed with side-channel attack resistance in mind
- Provides a clean API for easy integration into other projects
Cons
- Limited to operations on the secp256k1 curve, not a general-purpose cryptographic library
- Requires careful use and understanding of cryptographic principles to implement securely
- May have a steeper learning curve compared to higher-level cryptographic libraries
Code Examples
- Creating and verifying a signature:
#include <secp256k1.h>
// Create a context
secp256k1_context* ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);
// Generate a private key
unsigned char seckey[32];
secp256k1_keypair keypair;
secp256k1_keypair_create(ctx, &keypair, seckey);
// Sign a message
unsigned char msg[32] = {...}; // 32-byte message to sign
secp256k1_ecdsa_signature signature;
secp256k1_ecdsa_sign(ctx, &signature, msg, seckey, NULL, NULL);
// Verify the signature
secp256k1_pubkey pubkey;
secp256k1_keypair_pub(ctx, &pubkey, &keypair);
int result = secp256k1_ecdsa_verify(ctx, &signature, msg, &pubkey);
- Performing key exchange:
#include <secp256k1.h>
// Generate two key pairs
secp256k1_keypair keypair1, keypair2;
secp256k1_keypair_create(ctx, &keypair1, seckey1);
secp256k1_keypair_create(ctx, &keypair2, seckey2);
// Perform ECDH
unsigned char shared_secret[32];
secp256k1_pubkey pubkey2;
secp256k1_keypair_pub(ctx, &pubkey2, &keypair2);
secp256k1_ecdh(ctx, shared_secret, &pubkey2, seckey1, NULL, NULL);
- Generating a public key:
#include <secp256k1.h>
// Generate a private key
unsigned char seckey[32];
secp256k1_pubkey pubkey;
// Create the public key
secp256k1_ec_pubkey_create(ctx, &pubkey, seckey);
// Serialize the public key
unsigned char output[65];
size_t outputlen = 65;
secp256k1_ec_pubkey_serialize(ctx, output, &outputlen, &pubkey, SECP256K1_EC_UNCOMPRESSED);
Getting Started
To use the secp256k1 library in your project:
-
Clone the repository:
git clone https://github.com/bitcoin-core/secp256k1.git
-
Build the library:
cd secp256k1 ./autogen.sh ./configure make make check
-
Include the header in your C code:
#include <secp256k1.h>
-
Link against the built library when compiling your project.
Remember to create and destroy the context appropriately in your application:
secp256k1_context* ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);
// Use the context...
secp256k1_context_destroy(
Competitor Comparisons
Fast Elliptic Curve Cryptography in plain javascript
Pros of elliptic
- Written in JavaScript, making it easily integrable into web and Node.js applications
- Supports a wider range of elliptic curves, including secp256k1, p192, p224, p384, p521
- More flexible and customizable for various use cases beyond cryptocurrency
Cons of elliptic
- Generally slower performance compared to secp256k1's optimized C implementation
- May have a larger attack surface due to its broader feature set
- Less specialized for Bitcoin-specific use cases
Code Comparison
secp256k1:
static int secp256k1_ecdsa_sig_verify(const secp256k1_ecmult_context *ctx, const secp256k1_scalar *sigr, const secp256k1_scalar *sigs, const secp256k1_ge *pubkey, const secp256k1_scalar *message) {
unsigned char c[32];
secp256k1_scalar sn, u1, u2;
secp256k1_fe xr;
secp256k1_gej pubkeyj;
secp256k1_gej pr;
elliptic:
ECDSA.prototype.verify = function verify(msg, signature, key, enc) {
msg = this._truncateToN(new BN(msg, 16));
key = this.keyFromPublic(key, enc);
signature = new Signature(signature, 'hex');
// Perform primitive values validation
Both libraries implement ECDSA signature verification, but secp256k1 uses low-level C operations for optimized performance, while elliptic uses higher-level JavaScript constructs for better readability and flexibility.
Convert designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual CopilotREADME
libsecp256k1
High-performance high-assurance C library for digital signatures and other cryptographic primitives on the secp256k1 elliptic curve.
This library is intended to be the highest quality publicly available library for cryptography on the secp256k1 curve. However, the primary focus of its development has been for usage in the Bitcoin system and usage unlike Bitcoin's may be less well tested, verified, or suffer from a less well thought out interface. Correct usage requires some care and consideration that the library is fit for your application's purpose.
Features:
- secp256k1 ECDSA signing/verification and key generation.
- Additive and multiplicative tweaking of secret/public keys.
- Serialization/parsing of secret keys, public keys, signatures.
- Constant time, constant memory access signing and public key generation.
- Derandomized ECDSA (via RFC6979 or with a caller provided function.)
- Very efficient implementation.
- Suitable for embedded systems.
- No runtime dependencies.
- Optional module for public key recovery.
- Optional module for ECDH key exchange.
- Optional module for Schnorr signatures according to BIP-340.
- Optional module for ElligatorSwift key exchange according to BIP-324.
Implementation details
- General
- No runtime heap allocation.
- Extensive testing infrastructure.
- Structured to facilitate review and analysis.
- Intended to be portable to any system with a C89 compiler and uint64_t support.
- No use of floating types.
- Expose only higher level interfaces to minimize the API surface and improve application security. ("Be difficult to use insecurely.")
- Field operations
- Optimized implementation of arithmetic modulo the curve's field size (2^256 - 0x1000003D1).
- Using 5 52-bit limbs
- Using 10 26-bit limbs (including hand-optimized assembly for 32-bit ARM, by Wladimir J. van der Laan).
- This is an experimental feature that has not received enough scrutiny to satisfy the standard of quality of this library but is made available for testing and review by the community.
- Optimized implementation of arithmetic modulo the curve's field size (2^256 - 0x1000003D1).
- Scalar operations
- Optimized implementation without data-dependent branches of arithmetic modulo the curve's order.
- Using 4 64-bit limbs (relying on __int128 support in the compiler).
- Using 8 32-bit limbs.
- Optimized implementation without data-dependent branches of arithmetic modulo the curve's order.
- Modular inverses (both field elements and scalars) based on safegcd with some modifications, and a variable-time variant (by Peter Dettman).
- Group operations
- Point addition formula specifically simplified for the curve equation (y^2 = x^3 + 7).
- Use addition between points in Jacobian and affine coordinates where possible.
- Use a unified addition/doubling formula where necessary to avoid data-dependent branches.
- Point/x comparison without a field inversion by comparison in the Jacobian coordinate space.
- Point multiplication for verification (aP + bG).
- Use wNAF notation for point multiplicands.
- Use a much larger window for multiples of G, using precomputed multiples.
- Use Shamir's trick to do the multiplication with the public key and the generator simultaneously.
- Use secp256k1's efficiently-computable endomorphism to split the P multiplicand into 2 half-sized ones.
- Point multiplication for signing
- Use a precomputed table of multiples of powers of 16 multiplied with the generator, so general multiplication becomes a series of additions.
- Intended to be completely free of timing sidechannels for secret-key operations (on reasonable hardware/toolchains)
- Access the table with branch-free conditional moves so memory access is uniform.
- No data-dependent branches
- Optional runtime blinding which attempts to frustrate differential power analysis.
- The precomputed tables add and eventually subtract points for which no known scalar (secret key) is known, preventing even an attacker with control over the secret key used to control the data internally.
Building with Autotools
$ ./autogen.sh
$ ./configure
$ make
$ make check # run the test suite
$ sudo make install # optional
To compile optional modules (such as Schnorr signatures), you need to run ./configure
with additional flags (such as --enable-module-schnorrsig
). Run ./configure --help
to see the full list of available flags.
Building with CMake (experimental)
To maintain a pristine source tree, CMake encourages to perform an out-of-source build by using a separate dedicated build tree.
Building on POSIX systems
$ mkdir build && cd build
$ cmake ..
$ cmake --build .
$ ctest # run the test suite
$ sudo cmake --install . # optional
To compile optional modules (such as Schnorr signatures), you need to run cmake
with additional flags (such as -DSECP256K1_ENABLE_MODULE_SCHNORRSIG=ON
). Run cmake .. -LH
to see the full list of available flags.
Cross compiling
To alleviate issues with cross compiling, preconfigured toolchain files are available in the cmake
directory.
For example, to cross compile for Windows:
$ cmake .. -DCMAKE_TOOLCHAIN_FILE=../cmake/x86_64-w64-mingw32.toolchain.cmake
To cross compile for Android with NDK (using NDK's toolchain file, and assuming the ANDROID_NDK_ROOT
environment variable has been set):
$ cmake .. -DCMAKE_TOOLCHAIN_FILE="${ANDROID_NDK_ROOT}/build/cmake/android.toolchain.cmake" -DANDROID_ABI=arm64-v8a -DANDROID_PLATFORM=28
Building on Windows
To build on Windows with Visual Studio, a proper generator must be specified for a new build tree.
The following example assumes using of Visual Studio 2022 and CMake v3.21+.
In "Developer Command Prompt for VS 2022":
>cmake -G "Visual Studio 17 2022" -A x64 -S . -B build
>cmake --build build --config RelWithDebInfo
Usage examples
Usage examples can be found in the examples directory. To compile them you need to configure with --enable-examples
.
- ECDSA example
- Schnorr signatures example
- Deriving a shared secret (ECDH) example
- ElligatorSwift key exchange example
To compile the Schnorr signature and ECDH examples, you also need to configure with --enable-module-schnorrsig
and --enable-module-ecdh
.
Benchmark
If configured with --enable-benchmark
(which is the default), binaries for benchmarking the libsecp256k1 functions will be present in the root directory after the build.
To print the benchmark result to the command line:
$ ./bench_name
To create a CSV file for the benchmark result :
$ ./bench_name | sed '2d;s/ \{1,\}//g' > bench_name.csv
Reporting a vulnerability
See SECURITY.md
Contributing to libsecp256k1
See CONTRIBUTING.md
Top Related Projects
Fast Elliptic Curve Cryptography in plain javascript
Convert designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual Copilot