bitcoinj / secp256k1-jdk

Java library providing Bitcoin-related Elliptic Curve Cryptography
Apache License 2.0
9 stars 3 forks source link

= secp256k1-jdk

image:https://github.com/bitcoinj/secp256k1-jdk/workflows/Gradle%20Build/badge.svg[GitHub Build Status,link=https://github.com/bitcoinj/secp256k1-jdk/actions]

image::https://img.shields.io/badge/Matrix%20Chat-Join%20secp256k1--jdk--developers%20-blue[Join the secp256k1-jdk-developers Matrix room, link=https://matrix.to/#/#secp256k1-jdk-developers:matrix.org]

secp256k1-jdk is a Java library providing Bitcoin-related Elliptic Curve Cryptography functions using the https://www.secg.org/[SECG] curve https://en.bitcoin.it/wiki/Secp256k1[secp256k1]. It provides both ECDSA and Schnorr message signing functions.

It provides a Java API that enables multiple implementations. The proof-of-concept includes an implementation that adapts https://github.com/bitcoin-core/secp256k1[bitcoin-core/secp256k1], a native C library implementing elliptic curve operations on the secp256k1 curve. We also plan to provide an implementation using the popular https://www.bouncycastle.org[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.) In the future, we may provide documentation, examples, and language-specific extensions for one or more additional JVM languages. (Kotlin examples are in-progress.)

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.

== API

The API is based on the C-language API of https://github.com/bitcoin-core/secp256k1[bitcoin-core/secp256k1], but adapted to modern, idiomatic, functional-style Java and to use Elliptic Curve types from the Java Class Library, such as https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/security/interfaces/ECPublicKey.html[ECPublicKey] where appropriate.

The API is distributed as an API-only JAR (secp-api-_version_.jar) and we expect that there will be multiple implementations of the API. The API JAR currently requires JDK 9 or later but we may backport it to JDK 8 in a future release depending upon feedback from the community.

NOTE:: At this point, we are especially interested in feedback on the API.

== libsecp256k1 Panama Implementation (JDK 22+)

The provided proof-of-concept implementation uses the https://github.com/bitcoin-core/secp256k1[bitcoin-core/secp256k1] C-language library via https://openjdk.org/jeps/454[JEP-454: Foreign Function & Memory API] (known as Panama.) It is provided in a separate JAR (secp-ffm-_version_.jar) that requires JDK 22 or later.

Panama is available in https://openjdk.org/projects/jdk/22/[OpenJDK 22] and later. We anticipate secp-ffm will be the recommended/preferred secp-api implementation for use in projects using modern JVMs.

The minimum required JDK for this module will likely be incremented with each new JDK release, with a target of requiring JDK 25 (the next LTS release of the JDK) for the 1.0 release of secp-ffm.

WARNING:: This is a preliminary implementation provided for experimentation and feedback and should not be used in real applications.

== Bouncy Castle Implementation

An incomplete https://www.bouncycastle.org[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 https://bitcoinj.org[bitcoinj] and other Java-based Bitcoin implementations. We expect this implementation to be completed and made available as a pure-Java implementation for those who are unable to use the native libsecp256k1 implementation and/or Panama.

The Bouncy Castle implementation is currently targeting JDK 9, but if the API is backported to JDK 8, so will the Bouncy Castle implementation.

== libsecp256k1 Implementation for older JDKs

There are currently no plans for an implementation using earlier Java-to-C adapter technologies such as https://docs.oracle.com/en/java/javase/21/docs/specs/jni/index.html[JNI] or https://github.com/java-native-access/jna[JNA]. However, the secp256k1-jdk API should support such an implementation. We would be supportive if someone in the community endeavours to create an implementation or adapt one of the existing implementations to use the secp256k1-jdk API.

== Relation to bitcoinj

This project is hosted by the https://github.com/bitcoinj[bitcoinj organization] on GitHub, but secp256k1-jdk does not use or require the bitcoinj library (https://bitcoinj.org[website] / https://github.com/bitcoinj[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:

== Relation to Java Cryptography Architecture

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 https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/security/interfaces/ECPublicKey.html[ECPublicKey]) for interoperability and to avoid reinventing the wheel.

The SECG secp256K1 curve was removed from Java in the JDK 16 release (see https://bugs.openjdk.org/browse/JDK-8251547[JDK-8251547]). It is possible that a secp256k1 JCA provider could be developed, but that is not currently a goal of this project.

== Current Build Status

The build requires JDK 23 installed to run. Gradle 8.11 should be used and is provided by the included Gradle Wrapper.

(It may be possible to build with JDK 22 and/or an earlier Gradle if you configure the "Java Toolchains" configuration correctly, but as JDK 22 is unsupported you should migrate to JDK 23 as soon as possible.)

== Installing libsecp256k into your profile with Nix

We assume you are using Nix with experimental-features = nix-command flakes:

. nix profile install nixpkgs#secp256k1 . Verify that the secp256k1 library is in your ~/.nix-profile/lib directory.

By default, the Gradle build looks for the secp256k1 library in ~/.nix-profile/lib. If you have installed it with a different package manager or built it from source you can use the -PjavaPath option to Gradle to change the library path to your location.

== Building with Gradle Wrapper

Make sure you have installed version (0.5.0) of secp256k1 with nix profile install nixpkgs#secp256k1

. ./gradlew build

== Running the Schnorr Example with Gradle Wrapper

== Build a Start Script and use it to run the Schnorr Example

Build the script:

Set the script's Java options shell variable (this assumes you installed libsecp2565k1 with Nix):

Run the script:

== Building with Nix

NOTE:: We currently only support setting up a development environment with Nix. In the future we hope to support a full Nix build.

To start a development shell with all build prerequisites installed and run the Gradle build:

. nix develop . gradle build

== Extracting Headers with Nix

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 ./build/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

== Reporting a vulnerability

See SECURITY.adoc (TBD)

== References

=== secp256k1 library

=== Other JDK Implementations of secp256k1

=== Other JDK implementations of Elliptic Curve Cryptography

=== BIPS

=== General and Elliptic Curve Cryptography

=== Elligator

=== Java Cryptography Books & Articles