mirror of
https://github.com/bitcoin-s/bitcoin-s.git
synced 2025-02-27 00:06:26 +01:00
* Added crypto project and decoupled BitcoinSLogger from NetworkElement Decoupled BitcoinSLogger from Factory Moved NetworkElement into crypto project Moved Factory and BitcoinSUtil (renamed to BytesUtil) to crypto project Moved MaskedToString to crypto project Added BytesUtil to imports and cleaned up CryptoUtil.recoverPoint Moved the rest of crypto stuff to the crypto project Moved crypto tests to crypto-test project * Added documentation for crypto project
90 lines
2.8 KiB
Markdown
90 lines
2.8 KiB
Markdown
---
|
|
id: secp256k1
|
|
title: Secp256k1
|
|
---
|
|
|
|
[Libsecp256k1](https://github.com/bitcoin-core/secp256k1) is used to preform cryptographic operations on the secp256k1 curve.
|
|
This is the curve that bitcoin uses. There is a _signficant_ speedup when using this library compared to java crypto libraries
|
|
like bouncy castle.
|
|
|
|
In bitcoin-s, we support native binaries for libsecp256k1
|
|
|
|
1. [linux 32 bit](../../secp256k1jni/natives/linux_32)
|
|
2. [linux 64 bit](../../secp256k1jni/natives/linux_64)
|
|
3. [mac osx 64 bit](../../secp256k1jni/natives/osx_64)
|
|
4. [windows 64 bit](../../secp256k1jni/natives/windows_64)
|
|
|
|
Bitcoin-s uses a zero dependency library called [`native-lib-loader`](https://github.com/scijava/native-lib-loader).
|
|
That does the appropriate loading of the library onto your classpath to be accessed.
|
|
|
|
### Using libsecp256k1
|
|
|
|
To tell if you have access to libsecp256k1 you can do the following
|
|
|
|
```scala mdoc:invisible
|
|
import org.bitcoin._
|
|
import org.bitcoins.crypto._
|
|
|
|
```
|
|
|
|
```scala mdoc:compile-only
|
|
val isEnabled = org.bitcoin.Secp256k1Context.isEnabled()
|
|
|
|
println(s"Secp256k1Context.isEnabled=${isEnabled}")
|
|
```
|
|
|
|
If libsecp256k1 is enabled, you can use [NativeSecp256k1](../../secp256k1jni/src/main/java/org/bitcoin/NativeSecp256k1.java)
|
|
with static method defined in the class.
|
|
|
|
|
|
```scala mdoc:compile-only
|
|
val privKey = ECPrivateKey.freshPrivateKey
|
|
val pubKey = privKey.publicKey
|
|
val dataToSign = DoubleSha256Digest.empty
|
|
|
|
val signature = NativeSecp256k1.sign(dataToSign.bytes.toArray, privKey.bytes.toArray)
|
|
|
|
val verify = NativeSecp256k1.verify(dataToSign.bytes.toArray, signature, pubKey.bytes.toArray)
|
|
|
|
println(s"Verified with NativeSecp256k1 signature=${verify}")
|
|
|
|
//you can also just directly sign with the ECKey interface:
|
|
val signature2 = privKey.sign(dataToSign)
|
|
|
|
val verified2 = pubKey.verify(dataToSign, signature2)
|
|
|
|
println(s"Verified with NativeSecp256k1 again=${verified2}")
|
|
|
|
```
|
|
|
|
### When libsecp256k1 isn't available, or you want to turn it off
|
|
|
|
There are two reasons you wouldn't want to use libsecp256k1
|
|
|
|
1. You don't trust the pre-compiled binaries we are using
|
|
2. Your OS/arch is not supported
|
|
|
|
There are two ways you can circumvent libsecp256k1
|
|
|
|
1. Set `DISABLE_SECP256K1=true` in your environment variables. This will force `Secp256k1Context.isEnabled()` to return false
|
|
2. Call Bouncy castle methods in `ECKey`.
|
|
|
|
Here is an example of calling bouncy castle methods in `ECKey`
|
|
|
|
```scala mdoc:to-string
|
|
|
|
val privKey = ECPrivateKey.freshPrivateKey
|
|
val publicKey = privKey.publicKeyWithBouncyCastle
|
|
val dataToSign = DoubleSha256Digest.empty
|
|
|
|
val signature = privKey.signWithBouncyCastle(dataToSign.bytes)
|
|
|
|
val verified = publicKey.verifyWithBouncyCastle(dataToSign.bytes, signature)
|
|
|
|
println(s"Verified with bouncy castle=${verified}")
|
|
|
|
```
|
|
|
|
### Building libsecp256k1
|
|
|
|
[See instructions here](add-to-jni.md#adding-to-bitcoin-s)
|