secp256k1-jdk is a Java library providing Bitcoin-related Elliptic Curve Cryptography functions using the SECG curve
secp256k1. It provides ECDSA and Schnorr message signing, verification, and other functions.
The secp256k1-jdk API supports multiple implementations. The project includes an implementation that adapts bitcoin-core/secp256k1, a high-quality, native C
library implementing elliptic curve operations on the secp256k1 curve. In addition, there is a pure-Java implementation using the popular Bouncy Castle library.
The library supports other JDK-based languages such as Kotlin, Groovy, Scala, and Clojure (as these languages can all use Java classes directly.) Kotlin examples are provided. In the future, we may provide documentation, examples, and language-specific extensions for one or more additional JVM languages.
- WARNING
-
This prototype software has had limited testing and has not been reviewed. Do not use this software to store private keys for Bitcoin or any other purpose. It is provided AS-IS for experimentation and feedback.
The API is based on the C-language API of bitcoin-core/secp256k1, but adapted
to modern, idiomatic, functional-style Java. It also can convert to and from Elliptic Curve types in the Java Class Library, such as ECPoint where appropriate.
The API is distributed as an API-only JAR () and there are multiple implementations of the API. secp-api-0.3.1.jarsecp-api requires JDK 9 or later.
For details see the Javadoc.
- NOTE
-
At this point, we are especially interested in feedback on the API.
The provided implementation uses the bitcoin-core/secp256k1 C-language library via JEP-454: Foreign Function & Memory API (known as Panama.) It is provided in a separate JAR () that requires JDK 25 or later.secp-ffm-0.3.1.jar
We recommend secp-ffm as the preferred secp-api implementation for use in projects using modern JVMs.
The minimum required JDK for the secp-ffm module is JDK 25 (the first LTS release with FFM included.)
- WARNING
-
This is a preliminary implementation provided for experimentation and feedback and should not be used in real applications.
A Bouncy Castle-based submodule is included. Bouncy Castle is a well-regarded cryptography library that includes support for the secp256k1 curve and is currently used by bitcoinj and other Java-based Bitcoin implementations. The secp-bouncy module provides a pure-Java implementation for those who are unable to use the FFM-based libsecp256k1 implementation.
The Bouncy Castle implementation works with JDK 9 or later.
There are currently no plans for an implementation using earlier Java-to-C adapter technologies such as JNI or JNA. However, the secp256k1-jdk API can support a JNI implementation. We would be supportive if someone in the community endeavors to create an implementation or adapt one of the existing implementations to use the secp256k1-jdk API.
This project is hosted by the bitcoinj organization on GitHub, but secp256k1-jdk does not use or require the bitcoinj library (website / GitHub) and bitcoinj doesn’t (yet) use secp256k1-jdk for its ECC implementation. bitcoinj is currently being refactored to be more modular, and we would like to have pluggable ECC implementations (and Schnorr signatures!) in the near future, but further refactoring will be required before this can happen.
For information on the in-process refactoring of bitcoinj, see the following:
secp256k1-jdk currently does not use any Java Cryptography Architecture ECC providers nor does it make itself available as a provider. It does use some of the built-in Java ECC interfaces (such as ECPublicKey) for interoperability and to avoid reinventing the wheel.
The SECG secp256K1 curve was removed from Java in the JDK 16 release (see JDK-8251547). It is possible that a secp256k1 JCA provider could be developed, but that is not currently a goal of this project.
Binary packages are available on GitLab.com. You can download JARs or use the provided Maven coordinates to link to them directly from your pom.xml or build.gradle.
- WARNING
-
This is an experimental pre-release and should be used only for testing and evaluation only.
To your pom.xml:
<repositories>
<repository>
<id>secpjdk-repo</id>
<url>https://gitlab.com/api/v4/projects/55956336/packages/maven</url>
</repository>
</repositories>Or to your build.gradle:
maven {
url 'https://gitlab.com/api/v4/projects/55956336/packages/maven'
}
For example to depend on the API only, add the following to your pom.xml:
<dependency>
<groupId>org.bitcoinj.secp</groupId>
<artifactId>secp-api</artifactId>
<version>0.3.1</version>
</dependency>Or for Gradle, use:
dependencies {
implementation "org.bitcoinj.secp:secp-api:0.3.1"
}
The build requires JDK 25. Maven 3.9.0 or later is required and is provided by the Nix devShell. You must also install the native secp256k1 library.
The native-schnorr Maven profile uses $GRAALVM_HOME to find the native-image binary. The Nix devShell sets this up automatically. If you install GraalVM using one of the other mechanisms, you should verify that GRAALVM_HOME is set correctly.
-
apt-get -y install openjdk-25-jdk
There is no APT package for GraalVM, see GraalVM Download.
SDKMAN! provides JDK 25 in both Temurin and GraalVM Community Edition flavors (among others).
-
sdk install java 25.0.3-tem
or for GraalVM builds:
-
sdk install java 25.0.2-graalce
The Nix devshell sets up everything correctly, so simply run nix develop and you’ll be ready to build and run. It sets up LD_LIBRARY_PATH on Linux and DYLD_LIBRARY_PATH on macOS. It also sets LIBSECP_DIR which is what the Maven pom.xml file references.
-
apt-get -y install libsecp256k1-dev
This will correctly set up LD_LIBRARY_PATH, but you’ll need to set the following for pom.xml:
export LIBSECP_DIR="$LD_LIBRARY_PATH"-
brew install secp256k1 -
export DYLD_LIBRARY_PATH="$(brew --prefix secp256k1)/lib:$DYLD_LIBRARY_PATH" -
export LIBSECP_DIR="$LD_LIBRARY_PATH"
Step 2 sets up DYLD_LIBRARY_PATH correctly, but DYLD_LIBRARY_PATH is cleared by macOS System Integrity Protection before running protected executables (notably the shell scripts used to start Maven) so step 3 sets LIBSECP_DIR which our Maven pom.xml references to pick up the correct library path.
Other mechanisms should work as long as you set up LIBSECP_DIR and LD_LIBRARY_PATH and/or DYLD_LIBRARY_PATH properly and are mindful of System Integrity Protection on macOS.
This will be provided in a future release, see Issue #137
-
mvn verify
-
mvn verify -Prun-schnorr
To run all Java and Kotlin examples:
-
mvn verify -Prun-schnorr,run-ecdsa,run-schnorr-kotlin,run-ecdsa-kotlin
To build using GraalVM native-image:
-
Make sure you have GraalVM 25 or later installed
-
Make sure
GRAALVM_HOMEpoints to the Graal JDK 25 installation -
mvn verify -Pnative-schnorr -
mvn verify -Pnative-ecdsa
Run the native image binary:
-
./secp-examples-java/target/schnorr-example -
./secp-examples-java/target/ecdsa-example
To start a development shell with all build prerequisites installed and run the Gradle build:
-
nix develop -
mvn verify
The other commands described in the "Building with Maven" section also work in the Nix devShell.
secp256k1-jdk is available in Nixpkgs, see: nixpkgs#secp256k1-jdk
To extract the libsecp256k1 headers into Java classes via jextract using the extract-header.sh script:
-
nix develop -
./extract-headers.sh
The extracted headers will be writen to ./target/org/bitcoinj/secp/ffm/jextract. You can compare the generated headers with the checked-in headers with:
-
diff -r secp-ffm/src/main/java/org/bitcoinj/secp/ffm/jextract build/org/bitcoinj/secp/ffm/jextract
See SECURITY.md
-
bitcoin-core/secp256k1 on GitHub
-
libsecp256k1 tutorial by Pieter Wuille.
-
bitcoin-s fork https://bitcoin-s.org/docs/secp256k1/jni-modify
-
Sparrow/Drongo JNI: https://github.com/sparrowwallet/drongo/tree/master/src/main/java/org/bitcoin
-
Kotlin multiplatform wrapper: https://github.com/acinq/secp256k1-kmp
-
Nayuki’s Bitcoin Cryptography Library
-
Samourai port of Sipa’s Python reference implementation to Java: BIP340_Schnorr
-
OpenJDK Project Brisbane - uses Foreign Function & Memory API to encapsulate the FIPS 140 validated OpenSSL library.
-
https://www.chosenplaintext.ca/articles/beginners-guide-constant-time-cryptography.html
-
Complete addition formulas for prime order elliptic curves: Joost Renes, Craig Costello, and Lejla Batina
-
https://www.novixys.com/blog/generate-bitcoin-addresses-java/ (Obsolete as of JDK 16)