JNI Implementation in their own package
This commit is contained in:
parent
1d9d57ca0a
commit
720637ec24
@ -11,6 +11,7 @@ kotlin {
|
|||||||
|
|
||||||
val commonMain by sourceSets.getting {
|
val commonMain by sourceSets.getting {
|
||||||
dependencies {
|
dependencies {
|
||||||
|
api(rootProject)
|
||||||
implementation(kotlin("stdlib-common"))
|
implementation(kotlin("stdlib-common"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,16 @@
|
|||||||
package fr.acinq.secp256k1.jni
|
package fr.acinq.secp256k1.jni
|
||||||
|
|
||||||
|
import fr.acinq.secp256k1.Secp256k1
|
||||||
|
import org.bitcoin.NativeSecp256k1
|
||||||
|
|
||||||
public actual object NativeSecp256k1Loader {
|
public actual object NativeSecp256k1Loader {
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
@Synchronized
|
@Synchronized
|
||||||
@Throws(Exception::class)
|
@Throws(Exception::class)
|
||||||
actual fun load() {
|
actual fun load(): Secp256k1 {
|
||||||
System.loadLibrary("secp256k1-jni")
|
System.loadLibrary("secp256k1-jni")
|
||||||
|
return NativeSecp256k1
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
package fr.acinq.secp256k1.jni
|
package fr.acinq.secp256k1.jni
|
||||||
|
|
||||||
import kotlin.jvm.JvmStatic
|
import fr.acinq.secp256k1.Secp256k1
|
||||||
|
|
||||||
|
|
||||||
public expect object NativeSecp256k1Loader {
|
public expect object NativeSecp256k1Loader {
|
||||||
|
|
||||||
public fun load()
|
public fun load(): Secp256k1
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,9 @@
|
|||||||
*/
|
*/
|
||||||
package org.bitcoin
|
package org.bitcoin
|
||||||
|
|
||||||
|
import fr.acinq.secp256k1.PubKeyFormat
|
||||||
|
import fr.acinq.secp256k1.Secp256k1
|
||||||
|
import fr.acinq.secp256k1.SigFormat
|
||||||
import org.bitcoin.NativeSecp256k1Util.AssertFailException
|
import org.bitcoin.NativeSecp256k1Util.AssertFailException
|
||||||
import java.math.BigInteger
|
import java.math.BigInteger
|
||||||
import java.nio.ByteBuffer
|
import java.nio.ByteBuffer
|
||||||
@ -37,7 +40,7 @@ import java.util.concurrent.locks.ReentrantReadWriteLock
|
|||||||
* or point the JVM to the folder containing it with -Djava.library.path
|
* or point the JVM to the folder containing it with -Djava.library.path
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public object NativeSecp256k1 {
|
internal object NativeSecp256k1 : Secp256k1 {
|
||||||
private val rwl = ReentrantReadWriteLock()
|
private val rwl = ReentrantReadWriteLock()
|
||||||
private val r: Lock = rwl.readLock()
|
private val r: Lock = rwl.readLock()
|
||||||
private val w: Lock = rwl.writeLock()
|
private val w: Lock = rwl.writeLock()
|
||||||
@ -71,9 +74,8 @@ public object NativeSecp256k1 {
|
|||||||
* @return true if the signature is valid
|
* @return true if the signature is valid
|
||||||
* @throws AssertFailException in case of failure
|
* @throws AssertFailException in case of failure
|
||||||
*/
|
*/
|
||||||
@JvmStatic
|
|
||||||
@Throws(AssertFailException::class)
|
@Throws(AssertFailException::class)
|
||||||
public fun verify(data: ByteArray, signature: ByteArray, pub: ByteArray): Boolean {
|
override fun verify(data: ByteArray, signature: ByteArray, pub: ByteArray): Boolean {
|
||||||
require(data.size == 32 && signature.size <= 520 && pub.size <= 520)
|
require(data.size == 32 && signature.size <= 520 && pub.size <= 520)
|
||||||
val byteBuff = pack(data, signature, pub)
|
val byteBuff = pack(data, signature, pub)
|
||||||
r.lock()
|
r.lock()
|
||||||
@ -98,9 +100,8 @@ public object NativeSecp256k1 {
|
|||||||
* @return a signature, or an empty array is signing failed
|
* @return a signature, or an empty array is signing failed
|
||||||
* @throws AssertFailException in case of failure
|
* @throws AssertFailException in case of failure
|
||||||
*/
|
*/
|
||||||
@JvmStatic
|
|
||||||
@Throws(AssertFailException::class)
|
@Throws(AssertFailException::class)
|
||||||
public fun sign(data: ByteArray, sec: ByteArray, compact: Boolean): ByteArray {
|
override fun sign(data: ByteArray, sec: ByteArray, format: SigFormat): ByteArray {
|
||||||
require(data.size == 32 && sec.size <= 32)
|
require(data.size == 32 && sec.size <= 32)
|
||||||
val byteBuff = pack(data, sec)
|
val byteBuff = pack(data, sec)
|
||||||
val retByteArray: Array<ByteArray>
|
val retByteArray: Array<ByteArray>
|
||||||
@ -108,7 +109,7 @@ public object NativeSecp256k1 {
|
|||||||
retByteArray = try {
|
retByteArray = try {
|
||||||
secp256k1_ecdsa_sign(
|
secp256k1_ecdsa_sign(
|
||||||
byteBuff,
|
byteBuff,
|
||||||
compact,
|
format == SigFormat.COMPACT,
|
||||||
Secp256k1Context.getContext()
|
Secp256k1Context.getContext()
|
||||||
)
|
)
|
||||||
} finally {
|
} finally {
|
||||||
@ -125,9 +126,8 @@ public object NativeSecp256k1 {
|
|||||||
return if (retVal == 0) ByteArray(0) else sigArr
|
return if (retVal == 0) ByteArray(0) else sigArr
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmStatic
|
|
||||||
@Throws(AssertFailException::class)
|
@Throws(AssertFailException::class)
|
||||||
public fun signatureNormalize(sig: ByteArray, compact: Boolean): Pair<ByteArray, Boolean> {
|
override fun signatureNormalize(sig: ByteArray, format: SigFormat): Pair<ByteArray, Boolean> {
|
||||||
require(sig.size == 64 || sig.size in 70..73)
|
require(sig.size == 64 || sig.size in 70..73)
|
||||||
val byteBuff = pack(sig)
|
val byteBuff = pack(sig)
|
||||||
val retByteArray: Array<ByteArray>
|
val retByteArray: Array<ByteArray>
|
||||||
@ -136,7 +136,7 @@ public object NativeSecp256k1 {
|
|||||||
secp256k1_ecdsa_normalize(
|
secp256k1_ecdsa_normalize(
|
||||||
byteBuff,
|
byteBuff,
|
||||||
sig.size,
|
sig.size,
|
||||||
compact,
|
format == SigFormat.COMPACT,
|
||||||
Secp256k1Context.getContext()
|
Secp256k1Context.getContext()
|
||||||
)
|
)
|
||||||
} finally {
|
} finally {
|
||||||
@ -160,8 +160,7 @@ public object NativeSecp256k1 {
|
|||||||
* @param seckey ECDSA Secret key, 32 bytes
|
* @param seckey ECDSA Secret key, 32 bytes
|
||||||
* @return true if seckey is valid
|
* @return true if seckey is valid
|
||||||
*/
|
*/
|
||||||
@JvmStatic
|
override fun secKeyVerify(seckey: ByteArray): Boolean {
|
||||||
public fun secKeyVerify(seckey: ByteArray): Boolean {
|
|
||||||
require(seckey.size == 32)
|
require(seckey.size == 32)
|
||||||
val byteBuff = pack(seckey)
|
val byteBuff = pack(seckey)
|
||||||
r.lock()
|
r.lock()
|
||||||
@ -183,9 +182,8 @@ public object NativeSecp256k1 {
|
|||||||
* @return the corresponding public key (uncompressed)
|
* @return the corresponding public key (uncompressed)
|
||||||
*/
|
*/
|
||||||
//TODO add a 'compressed' arg
|
//TODO add a 'compressed' arg
|
||||||
@JvmStatic
|
|
||||||
@Throws(AssertFailException::class)
|
@Throws(AssertFailException::class)
|
||||||
public fun computePubkey(seckey: ByteArray, compressed: Boolean): ByteArray {
|
override fun computePubkey(seckey: ByteArray, format: PubKeyFormat): ByteArray {
|
||||||
require(seckey.size == 32)
|
require(seckey.size == 32)
|
||||||
val byteBuff = pack(seckey)
|
val byteBuff = pack(seckey)
|
||||||
val retByteArray: Array<ByteArray>
|
val retByteArray: Array<ByteArray>
|
||||||
@ -193,7 +191,7 @@ public object NativeSecp256k1 {
|
|||||||
retByteArray = try {
|
retByteArray = try {
|
||||||
secp256k1_ec_pubkey_create(
|
secp256k1_ec_pubkey_create(
|
||||||
byteBuff,
|
byteBuff,
|
||||||
compressed,
|
format == PubKeyFormat.COMPRESSED,
|
||||||
Secp256k1Context.getContext()
|
Secp256k1Context.getContext()
|
||||||
)
|
)
|
||||||
} finally {
|
} finally {
|
||||||
@ -211,9 +209,8 @@ public object NativeSecp256k1 {
|
|||||||
* @return the input public key (uncompressed) if valid, or an empty array
|
* @return the input public key (uncompressed) if valid, or an empty array
|
||||||
* @throws AssertFailException in case of failure
|
* @throws AssertFailException in case of failure
|
||||||
*/
|
*/
|
||||||
@JvmStatic
|
|
||||||
@Throws(AssertFailException::class)
|
@Throws(AssertFailException::class)
|
||||||
public fun parsePubkey(pubkey: ByteArray, compressed: Boolean): ByteArray {
|
override fun parsePubkey(pubkey: ByteArray, format: PubKeyFormat): ByteArray {
|
||||||
require(pubkey.size == 33 || pubkey.size == 65)
|
require(pubkey.size == 33 || pubkey.size == 65)
|
||||||
val byteBuff = pack(pubkey)
|
val byteBuff = pack(pubkey)
|
||||||
val retByteArray: Array<ByteArray>
|
val retByteArray: Array<ByteArray>
|
||||||
@ -223,7 +220,7 @@ public object NativeSecp256k1 {
|
|||||||
byteBuff,
|
byteBuff,
|
||||||
Secp256k1Context.getContext(),
|
Secp256k1Context.getContext(),
|
||||||
pubkey.size,
|
pubkey.size,
|
||||||
compressed
|
format == PubKeyFormat.COMPRESSED
|
||||||
)
|
)
|
||||||
} finally {
|
} finally {
|
||||||
r.unlock()
|
r.unlock()
|
||||||
@ -231,7 +228,11 @@ public object NativeSecp256k1 {
|
|||||||
val pubArr = retByteArray[0]
|
val pubArr = retByteArray[0]
|
||||||
BigInteger(byteArrayOf(retByteArray[1][0])).toInt()
|
BigInteger(byteArrayOf(retByteArray[1][0])).toInt()
|
||||||
val retVal = BigInteger(byteArrayOf(retByteArray[1][1])).toInt()
|
val retVal = BigInteger(byteArrayOf(retByteArray[1][1])).toInt()
|
||||||
NativeSecp256k1Util.assertEquals(pubArr.size, if (compressed) 33 else 65, "Got bad pubkey length.")
|
NativeSecp256k1Util.assertEquals(
|
||||||
|
pubArr.size,
|
||||||
|
format.maxSize,
|
||||||
|
"Got bad pubkey length."
|
||||||
|
)
|
||||||
return if (retVal == 0) ByteArray(0) else pubArr
|
return if (retVal == 0) ByteArray(0) else pubArr
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -239,9 +240,8 @@ public object NativeSecp256k1 {
|
|||||||
* libsecp256k1 Cleanup - This destroys the secp256k1 context object
|
* libsecp256k1 Cleanup - This destroys the secp256k1 context object
|
||||||
* This should be called at the end of the program for proper cleanup of the context.
|
* This should be called at the end of the program for proper cleanup of the context.
|
||||||
*/
|
*/
|
||||||
@JvmStatic
|
|
||||||
@Synchronized
|
@Synchronized
|
||||||
public fun cleanup() {
|
override fun cleanup() {
|
||||||
w.lock()
|
w.lock()
|
||||||
try {
|
try {
|
||||||
secp256k1_destroy_context(Secp256k1Context.getContext())
|
secp256k1_destroy_context(Secp256k1Context.getContext())
|
||||||
@ -250,9 +250,8 @@ public object NativeSecp256k1 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmStatic
|
|
||||||
@Throws(AssertFailException::class)
|
@Throws(AssertFailException::class)
|
||||||
public fun privKeyNegate(privkey: ByteArray): ByteArray {
|
override fun privKeyNegate(privkey: ByteArray): ByteArray {
|
||||||
require(privkey.size == 32)
|
require(privkey.size == 32)
|
||||||
val byteBuff = pack(privkey)
|
val byteBuff = pack(privkey)
|
||||||
val retByteArray: Array<ByteArray>
|
val retByteArray: Array<ByteArray>
|
||||||
@ -285,9 +284,8 @@ public object NativeSecp256k1 {
|
|||||||
* @return privkey * tweak
|
* @return privkey * tweak
|
||||||
* @throws AssertFailException in case of failure
|
* @throws AssertFailException in case of failure
|
||||||
*/
|
*/
|
||||||
@JvmStatic
|
|
||||||
@Throws(AssertFailException::class)
|
@Throws(AssertFailException::class)
|
||||||
public fun privKeyTweakMul(privkey: ByteArray, tweak: ByteArray): ByteArray {
|
override fun privKeyTweakMul(privkey: ByteArray, tweak: ByteArray): ByteArray {
|
||||||
require(privkey.size == 32)
|
require(privkey.size == 32)
|
||||||
val byteBuff = pack(privkey, tweak)
|
val byteBuff = pack(privkey, tweak)
|
||||||
val retByteArray: Array<ByteArray>
|
val retByteArray: Array<ByteArray>
|
||||||
@ -320,9 +318,8 @@ public object NativeSecp256k1 {
|
|||||||
* @return privkey + tweak
|
* @return privkey + tweak
|
||||||
* @throws AssertFailException in case of failure
|
* @throws AssertFailException in case of failure
|
||||||
*/
|
*/
|
||||||
@JvmStatic
|
|
||||||
@Throws(AssertFailException::class)
|
@Throws(AssertFailException::class)
|
||||||
public fun privKeyTweakAdd(privkey: ByteArray, tweak: ByteArray): ByteArray {
|
override fun privKeyTweakAdd(privkey: ByteArray, tweak: ByteArray): ByteArray {
|
||||||
require(privkey.size == 32)
|
require(privkey.size == 32)
|
||||||
val byteBuff = pack(privkey, tweak)
|
val byteBuff = pack(privkey, tweak)
|
||||||
val retByteArray: Array<ByteArray>
|
val retByteArray: Array<ByteArray>
|
||||||
@ -343,9 +340,8 @@ public object NativeSecp256k1 {
|
|||||||
return privArr
|
return privArr
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmStatic
|
|
||||||
@Throws(AssertFailException::class)
|
@Throws(AssertFailException::class)
|
||||||
public fun pubKeyNegate(pubkey: ByteArray): ByteArray {
|
override fun pubKeyNegate(pubkey: ByteArray): ByteArray {
|
||||||
require(pubkey.size == 33 || pubkey.size == 65)
|
require(pubkey.size == 33 || pubkey.size == 65)
|
||||||
val byteBuff = pack(pubkey)
|
val byteBuff = pack(pubkey)
|
||||||
val retByteArray: Array<ByteArray>
|
val retByteArray: Array<ByteArray>
|
||||||
@ -375,9 +371,8 @@ public object NativeSecp256k1 {
|
|||||||
* @return pubkey + tweak
|
* @return pubkey + tweak
|
||||||
* @throws AssertFailException in case of failure
|
* @throws AssertFailException in case of failure
|
||||||
*/
|
*/
|
||||||
@JvmStatic
|
|
||||||
@Throws(AssertFailException::class)
|
@Throws(AssertFailException::class)
|
||||||
public fun pubKeyTweakAdd(pubkey: ByteArray, tweak: ByteArray): ByteArray {
|
override fun pubKeyTweakAdd(pubkey: ByteArray, tweak: ByteArray): ByteArray {
|
||||||
require(pubkey.size == 33 || pubkey.size == 65)
|
require(pubkey.size == 33 || pubkey.size == 65)
|
||||||
val byteBuff = pack(pubkey, tweak)
|
val byteBuff = pack(pubkey, tweak)
|
||||||
val retByteArray: Array<ByteArray>
|
val retByteArray: Array<ByteArray>
|
||||||
@ -407,9 +402,8 @@ public object NativeSecp256k1 {
|
|||||||
* @return pubkey * tweak
|
* @return pubkey * tweak
|
||||||
* @throws AssertFailException in case of failure
|
* @throws AssertFailException in case of failure
|
||||||
*/
|
*/
|
||||||
@JvmStatic
|
|
||||||
@Throws(AssertFailException::class)
|
@Throws(AssertFailException::class)
|
||||||
public fun pubKeyTweakMul(pubkey: ByteArray, tweak: ByteArray): ByteArray {
|
override fun pubKeyTweakMul(pubkey: ByteArray, tweak: ByteArray): ByteArray {
|
||||||
require(pubkey.size == 33 || pubkey.size == 65)
|
require(pubkey.size == 33 || pubkey.size == 65)
|
||||||
val byteBuff = pack(pubkey, tweak)
|
val byteBuff = pack(pubkey, tweak)
|
||||||
val retByteArray: Array<ByteArray>
|
val retByteArray: Array<ByteArray>
|
||||||
@ -431,9 +425,8 @@ public object NativeSecp256k1 {
|
|||||||
return pubArr
|
return pubArr
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmStatic
|
|
||||||
@Throws(AssertFailException::class)
|
@Throws(AssertFailException::class)
|
||||||
public fun pubKeyAdd(pubkey1: ByteArray, pubkey2: ByteArray): ByteArray {
|
override fun pubKeyAdd(pubkey1: ByteArray, pubkey2: ByteArray): ByteArray {
|
||||||
require(pubkey1.size == 33 || pubkey1.size == 65)
|
require(pubkey1.size == 33 || pubkey1.size == 65)
|
||||||
require(pubkey2.size == 33 || pubkey2.size == 65)
|
require(pubkey2.size == 33 || pubkey2.size == 65)
|
||||||
val byteBuff = pack(pubkey1, pubkey2)
|
val byteBuff = pack(pubkey1, pubkey2)
|
||||||
@ -465,9 +458,8 @@ public object NativeSecp256k1 {
|
|||||||
* @return ecdh(sedckey, pubkey)
|
* @return ecdh(sedckey, pubkey)
|
||||||
* @throws AssertFailException in case of failure
|
* @throws AssertFailException in case of failure
|
||||||
*/
|
*/
|
||||||
@JvmStatic
|
|
||||||
@Throws(AssertFailException::class)
|
@Throws(AssertFailException::class)
|
||||||
public fun createECDHSecret(seckey: ByteArray, pubkey: ByteArray): ByteArray {
|
override fun createECDHSecret(seckey: ByteArray, pubkey: ByteArray): ByteArray {
|
||||||
require(seckey.size <= 32 && pubkey.size <= 65)
|
require(seckey.size <= 32 && pubkey.size <= 65)
|
||||||
val byteBuff = pack(seckey, pubkey)
|
val byteBuff = pack(seckey, pubkey)
|
||||||
val retByteArray: Array<ByteArray>
|
val retByteArray: Array<ByteArray>
|
||||||
@ -488,9 +480,8 @@ public object NativeSecp256k1 {
|
|||||||
return resArr
|
return resArr
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmStatic
|
|
||||||
@Throws(AssertFailException::class)
|
@Throws(AssertFailException::class)
|
||||||
public fun ecdsaRecover(sig: ByteArray, message: ByteArray, recid: Int, compressed: Boolean): ByteArray {
|
override fun ecdsaRecover(sig: ByteArray, message: ByteArray, recid: Int, format: PubKeyFormat): ByteArray {
|
||||||
require(sig.size == 64)
|
require(sig.size == 64)
|
||||||
require(message.size == 32)
|
require(message.size == 32)
|
||||||
val byteBuff = pack(sig, message)
|
val byteBuff = pack(sig, message)
|
||||||
@ -501,14 +492,18 @@ public object NativeSecp256k1 {
|
|||||||
byteBuff,
|
byteBuff,
|
||||||
Secp256k1Context.getContext(),
|
Secp256k1Context.getContext(),
|
||||||
recid,
|
recid,
|
||||||
compressed
|
format == PubKeyFormat.COMPRESSED
|
||||||
)
|
)
|
||||||
} finally {
|
} finally {
|
||||||
r.unlock()
|
r.unlock()
|
||||||
}
|
}
|
||||||
val resArr = retByteArray[0]
|
val resArr = retByteArray[0]
|
||||||
val retVal = BigInteger(byteArrayOf(retByteArray[1][0])).toInt()
|
val retVal = BigInteger(byteArrayOf(retByteArray[1][0])).toInt()
|
||||||
NativeSecp256k1Util.assertEquals(resArr.size, if (compressed) 33 else 65, "Got bad result length.")
|
NativeSecp256k1Util.assertEquals(
|
||||||
|
resArr.size,
|
||||||
|
format.maxSize,
|
||||||
|
"Got bad result length."
|
||||||
|
)
|
||||||
NativeSecp256k1Util.assertEquals(retVal, 1, "Failed return value check.")
|
NativeSecp256k1Util.assertEquals(retVal, 1, "Failed return value check.")
|
||||||
return resArr
|
return resArr
|
||||||
}
|
}
|
||||||
@ -520,10 +515,9 @@ public object NativeSecp256k1 {
|
|||||||
* @return true if successful
|
* @return true if successful
|
||||||
* @throws AssertFailException in case of failure
|
* @throws AssertFailException in case of failure
|
||||||
*/
|
*/
|
||||||
@JvmStatic
|
|
||||||
@Synchronized
|
@Synchronized
|
||||||
@Throws(AssertFailException::class)
|
@Throws(AssertFailException::class)
|
||||||
public fun randomize(seed: ByteArray): Boolean {
|
override fun randomize(seed: ByteArray): Boolean {
|
||||||
require(seed.size == 32)
|
require(seed.size == 32)
|
||||||
val byteBuff = pack(seed)
|
val byteBuff = pack(seed)
|
||||||
w.lock()
|
w.lock()
|
||||||
|
@ -15,7 +15,6 @@
|
|||||||
*/
|
*/
|
||||||
package org.bitcoin
|
package org.bitcoin
|
||||||
|
|
||||||
import kotlin.jvm.Throws
|
|
||||||
import java.lang.Exception
|
import java.lang.Exception
|
||||||
|
|
||||||
internal object NativeSecp256k1Util {
|
internal object NativeSecp256k1Util {
|
||||||
|
@ -15,8 +15,6 @@
|
|||||||
*/
|
*/
|
||||||
package org.bitcoin
|
package org.bitcoin
|
||||||
|
|
||||||
import kotlin.jvm.JvmStatic
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class holds the context reference used in native methods
|
* This class holds the context reference used in native methods
|
||||||
* to handle ECDSA operations.
|
* to handle ECDSA operations.
|
||||||
@ -35,6 +33,7 @@ public object Secp256k1Context {
|
|||||||
|
|
||||||
init { //static initializer
|
init { //static initializer
|
||||||
isEnabled = true
|
isEnabled = true
|
||||||
context = secp256k1_init_context()
|
context =
|
||||||
|
secp256k1_init_context()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package fr.acinq.secp256k1.jni
|
package fr.acinq.secp256k1.jni
|
||||||
|
|
||||||
|
import fr.acinq.secp256k1.Secp256k1
|
||||||
|
import org.bitcoin.NativeSecp256k1
|
||||||
import java.io.*
|
import java.io.*
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
@ -24,12 +26,13 @@ public actual object NativeSecp256k1Loader {
|
|||||||
@JvmStatic
|
@JvmStatic
|
||||||
@Synchronized
|
@Synchronized
|
||||||
@Throws(Exception::class)
|
@Throws(Exception::class)
|
||||||
public actual fun load() {
|
public actual fun load(): Secp256k1 {
|
||||||
// only cleanup before the first extract
|
// only cleanup before the first extract
|
||||||
if (!extracted) {
|
if (!extracted) {
|
||||||
cleanup()
|
cleanup()
|
||||||
}
|
}
|
||||||
loadSecp256k1NativeLibrary()
|
loadSecp256k1NativeLibrary()
|
||||||
|
return NativeSecp256k1
|
||||||
}
|
}
|
||||||
|
|
||||||
private val tempDir: File
|
private val tempDir: File
|
||||||
|
@ -18,60 +18,49 @@ package fr.acinq.secp256k1
|
|||||||
|
|
||||||
import kotlin.jvm.JvmStatic
|
import kotlin.jvm.JvmStatic
|
||||||
|
|
||||||
public enum class SigFormat(internal val size: Int) { COMPACT(64), DER(72) }
|
public enum class SigFormat(public val maxSize: Int) { COMPACT(64), DER(72) }
|
||||||
|
|
||||||
public enum class PubKeyFormat(internal val size: Int) { COMPRESSED(33), UNCOMPRESSED(65) }
|
public enum class PubKeyFormat(public val maxSize: Int) { COMPRESSED(33), UNCOMPRESSED(65) }
|
||||||
|
|
||||||
public expect object Secp256k1 {
|
public interface Secp256k1 {
|
||||||
|
|
||||||
@JvmStatic
|
|
||||||
public fun verify(data: ByteArray, signature: ByteArray, pub: ByteArray): Boolean
|
public fun verify(data: ByteArray, signature: ByteArray, pub: ByteArray): Boolean
|
||||||
|
|
||||||
@JvmStatic
|
|
||||||
public fun sign(data: ByteArray, sec: ByteArray, format: SigFormat): ByteArray
|
public fun sign(data: ByteArray, sec: ByteArray, format: SigFormat): ByteArray
|
||||||
|
|
||||||
@JvmStatic
|
|
||||||
public fun signatureNormalize(sig: ByteArray, format: SigFormat): Pair<ByteArray, Boolean>
|
public fun signatureNormalize(sig: ByteArray, format: SigFormat): Pair<ByteArray, Boolean>
|
||||||
|
|
||||||
@JvmStatic
|
|
||||||
public fun secKeyVerify(seckey: ByteArray): Boolean
|
public fun secKeyVerify(seckey: ByteArray): Boolean
|
||||||
|
|
||||||
@JvmStatic
|
|
||||||
public fun computePubkey(seckey: ByteArray, format: PubKeyFormat): ByteArray
|
public fun computePubkey(seckey: ByteArray, format: PubKeyFormat): ByteArray
|
||||||
|
|
||||||
@JvmStatic
|
|
||||||
public fun parsePubkey(pubkey: ByteArray, format: PubKeyFormat): ByteArray
|
public fun parsePubkey(pubkey: ByteArray, format: PubKeyFormat): ByteArray
|
||||||
|
|
||||||
@JvmStatic
|
|
||||||
public fun cleanup()
|
public fun cleanup()
|
||||||
|
|
||||||
@JvmStatic
|
|
||||||
public fun privKeyNegate(privkey: ByteArray): ByteArray
|
public fun privKeyNegate(privkey: ByteArray): ByteArray
|
||||||
|
|
||||||
@JvmStatic
|
|
||||||
public fun privKeyTweakMul(privkey: ByteArray, tweak: ByteArray): ByteArray
|
public fun privKeyTweakMul(privkey: ByteArray, tweak: ByteArray): ByteArray
|
||||||
|
|
||||||
@JvmStatic
|
|
||||||
public fun privKeyTweakAdd(privkey: ByteArray, tweak: ByteArray): ByteArray
|
public fun privKeyTweakAdd(privkey: ByteArray, tweak: ByteArray): ByteArray
|
||||||
|
|
||||||
@JvmStatic
|
|
||||||
public fun pubKeyNegate(pubkey: ByteArray): ByteArray
|
public fun pubKeyNegate(pubkey: ByteArray): ByteArray
|
||||||
|
|
||||||
@JvmStatic
|
|
||||||
public fun pubKeyTweakAdd(pubkey: ByteArray, tweak: ByteArray): ByteArray
|
public fun pubKeyTweakAdd(pubkey: ByteArray, tweak: ByteArray): ByteArray
|
||||||
|
|
||||||
@JvmStatic
|
|
||||||
public fun pubKeyTweakMul(pubkey: ByteArray, tweak: ByteArray): ByteArray
|
public fun pubKeyTweakMul(pubkey: ByteArray, tweak: ByteArray): ByteArray
|
||||||
|
|
||||||
@JvmStatic
|
|
||||||
public fun pubKeyAdd(pubkey1: ByteArray, pubkey2: ByteArray): ByteArray
|
public fun pubKeyAdd(pubkey1: ByteArray, pubkey2: ByteArray): ByteArray
|
||||||
|
|
||||||
@JvmStatic
|
|
||||||
public fun createECDHSecret(seckey: ByteArray, pubkey: ByteArray): ByteArray
|
public fun createECDHSecret(seckey: ByteArray, pubkey: ByteArray): ByteArray
|
||||||
|
|
||||||
@JvmStatic
|
|
||||||
public fun ecdsaRecover(sig: ByteArray, message: ByteArray, recid: Int, format: PubKeyFormat): ByteArray
|
public fun ecdsaRecover(sig: ByteArray, message: ByteArray, recid: Int, format: PubKeyFormat): ByteArray
|
||||||
|
|
||||||
@JvmStatic
|
|
||||||
public fun randomize(seed: ByteArray): Boolean
|
public fun randomize(seed: ByteArray): Boolean
|
||||||
|
|
||||||
|
public companion object : Secp256k1 by getSecpk256k1() {
|
||||||
|
@JvmStatic public fun get(): Secp256k1 = this
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal expect fun getSecpk256k1(): Secp256k1
|
||||||
|
@ -1,68 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2020 ACINQ SAS
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package fr.acinq.secp256k1
|
|
||||||
|
|
||||||
import org.bitcoin.NativeSecp256k1
|
|
||||||
import java.lang.IllegalStateException
|
|
||||||
|
|
||||||
public actual object Secp256k1 {
|
|
||||||
|
|
||||||
init {
|
|
||||||
try {
|
|
||||||
val cls = Class.forName("fr.acinq.secp256k1.jni.NativeSecp256k1Loader")
|
|
||||||
val load = cls.getMethod("load")
|
|
||||||
load.invoke(null)
|
|
||||||
} catch (ex: ClassNotFoundException) {
|
|
||||||
throw IllegalStateException("Could not load native Secp256k1 JNI library. Have you added the JNI dependency?", ex)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public actual fun verify(data: ByteArray, signature: ByteArray, pub: ByteArray): Boolean = NativeSecp256k1.verify(data, signature, pub)
|
|
||||||
|
|
||||||
public actual fun sign(data: ByteArray, sec: ByteArray, format: SigFormat): ByteArray = NativeSecp256k1.sign(data, sec, format == SigFormat.COMPACT)
|
|
||||||
|
|
||||||
public actual fun signatureNormalize(sig: ByteArray, format: SigFormat): Pair<ByteArray, Boolean> = NativeSecp256k1.signatureNormalize(sig, format == SigFormat.COMPACT)
|
|
||||||
|
|
||||||
public actual fun secKeyVerify(seckey: ByteArray): Boolean = NativeSecp256k1.secKeyVerify(seckey)
|
|
||||||
|
|
||||||
public actual fun computePubkey(seckey: ByteArray, format: PubKeyFormat): ByteArray = NativeSecp256k1.computePubkey(seckey, format == PubKeyFormat.COMPRESSED)
|
|
||||||
|
|
||||||
public actual fun parsePubkey(pubkey: ByteArray, format: PubKeyFormat): ByteArray = NativeSecp256k1.parsePubkey(pubkey, format == PubKeyFormat.COMPRESSED)
|
|
||||||
|
|
||||||
public actual fun cleanup(): Unit = NativeSecp256k1.cleanup()
|
|
||||||
|
|
||||||
public actual fun privKeyNegate(privkey: ByteArray): ByteArray = NativeSecp256k1.privKeyNegate(privkey)
|
|
||||||
|
|
||||||
public actual fun privKeyTweakMul(privkey: ByteArray, tweak: ByteArray): ByteArray = NativeSecp256k1.privKeyTweakMul(privkey, tweak)
|
|
||||||
|
|
||||||
public actual fun privKeyTweakAdd(privkey: ByteArray, tweak: ByteArray): ByteArray = NativeSecp256k1.privKeyTweakAdd(privkey, tweak)
|
|
||||||
|
|
||||||
public actual fun pubKeyNegate(pubkey: ByteArray): ByteArray = NativeSecp256k1.pubKeyNegate(pubkey)
|
|
||||||
|
|
||||||
public actual fun pubKeyTweakAdd(pubkey: ByteArray, tweak: ByteArray): ByteArray = NativeSecp256k1.pubKeyTweakAdd(pubkey, tweak)
|
|
||||||
|
|
||||||
public actual fun pubKeyTweakMul(pubkey: ByteArray, tweak: ByteArray): ByteArray = NativeSecp256k1.pubKeyTweakMul(pubkey, tweak)
|
|
||||||
|
|
||||||
public actual fun pubKeyAdd(pubkey1: ByteArray, pubkey2: ByteArray): ByteArray = NativeSecp256k1.pubKeyAdd(pubkey1, pubkey2)
|
|
||||||
|
|
||||||
public actual fun createECDHSecret(seckey: ByteArray, pubkey: ByteArray): ByteArray = NativeSecp256k1.createECDHSecret(seckey, pubkey)
|
|
||||||
|
|
||||||
public actual fun ecdsaRecover(sig: ByteArray, message: ByteArray, recid: Int, format: PubKeyFormat): ByteArray = NativeSecp256k1.ecdsaRecover(sig, message, recid, format == PubKeyFormat.COMPRESSED)
|
|
||||||
|
|
||||||
public actual fun randomize(seed: ByteArray): Boolean = NativeSecp256k1.randomize(seed)
|
|
||||||
|
|
||||||
}
|
|
30
src/jvmMain/kotlin/fr/acinq/secp256k1/Secp256k1Jvm.kt
Normal file
30
src/jvmMain/kotlin/fr/acinq/secp256k1/Secp256k1Jvm.kt
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2020 ACINQ SAS
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package fr.acinq.secp256k1
|
||||||
|
|
||||||
|
import java.lang.IllegalStateException
|
||||||
|
|
||||||
|
|
||||||
|
internal actual fun getSecpk256k1(): Secp256k1 {
|
||||||
|
try {
|
||||||
|
val cls = Class.forName("fr.acinq.secp256k1.jni.NativeSecp256k1Loader")
|
||||||
|
val load = cls.getMethod("load")
|
||||||
|
return load.invoke(null) as Secp256k1
|
||||||
|
} catch (ex: ClassNotFoundException) {
|
||||||
|
throw IllegalStateException("Could not load native Secp256k1 JNI library. Have you added the JNI dependency?", ex)
|
||||||
|
}
|
||||||
|
}
|
@ -1,565 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2013 Google Inc.
|
|
||||||
* Copyright 2014-2016 the libsecp256k1 contributors
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package org.bitcoin
|
|
||||||
|
|
||||||
import org.bitcoin.NativeSecp256k1Util.AssertFailException
|
|
||||||
import java.math.BigInteger
|
|
||||||
import java.nio.ByteBuffer
|
|
||||||
import java.nio.ByteOrder
|
|
||||||
import java.util.concurrent.locks.Lock
|
|
||||||
import java.util.concurrent.locks.ReentrantReadWriteLock
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* This class holds native methods to handle ECDSA verification.
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* You can find an example library that can be used for this at https://github.com/bitcoin/secp256k1
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* To build secp256k1 for use with bitcoinj, run
|
|
||||||
* `./configure --enable-jni --enable-experimental --enable-module-ecdh`
|
|
||||||
* and `make` then copy `.libs/libsecp256k1.so` to your system library path
|
|
||||||
* or point the JVM to the folder containing it with -Djava.library.path
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public object NativeSecp256k1 {
|
|
||||||
private val rwl = ReentrantReadWriteLock()
|
|
||||||
private val r: Lock = rwl.readLock()
|
|
||||||
private val w: Lock = rwl.writeLock()
|
|
||||||
private val nativeECDSABuffer = ThreadLocal<ByteBuffer?>()
|
|
||||||
|
|
||||||
private fun pack(vararg buffers: ByteArray): ByteBuffer {
|
|
||||||
var size = 0
|
|
||||||
for (i in buffers.indices) {
|
|
||||||
size += buffers[i].size
|
|
||||||
}
|
|
||||||
|
|
||||||
val byteBuff = nativeECDSABuffer.get()?.takeIf { it.capacity() >= size }
|
|
||||||
?: ByteBuffer.allocateDirect(size).also {
|
|
||||||
it.order(ByteOrder.nativeOrder())
|
|
||||||
nativeECDSABuffer.set(it)
|
|
||||||
}
|
|
||||||
byteBuff.rewind()
|
|
||||||
for (i in buffers.indices) {
|
|
||||||
byteBuff.put(buffers[i])
|
|
||||||
}
|
|
||||||
return byteBuff
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Verifies the given secp256k1 signature in native code.
|
|
||||||
* Calling when enabled == false is undefined (probably library not loaded)
|
|
||||||
*
|
|
||||||
* @param data The data which was signed, must be exactly 32 bytes
|
|
||||||
* @param signature The signature
|
|
||||||
* @param pub The public key which did the signing
|
|
||||||
* @return true if the signature is valid
|
|
||||||
* @throws AssertFailException in case of failure
|
|
||||||
*/
|
|
||||||
@JvmStatic
|
|
||||||
@Throws(AssertFailException::class)
|
|
||||||
public fun verify(data: ByteArray, signature: ByteArray, pub: ByteArray): Boolean {
|
|
||||||
require(data.size == 32 && signature.size <= 520 && pub.size <= 520)
|
|
||||||
val byteBuff = pack(data, signature, pub)
|
|
||||||
r.lock()
|
|
||||||
return try {
|
|
||||||
secp256k1_ecdsa_verify(
|
|
||||||
byteBuff,
|
|
||||||
Secp256k1Context.getContext(),
|
|
||||||
signature.size,
|
|
||||||
pub.size
|
|
||||||
) == 1
|
|
||||||
} finally {
|
|
||||||
r.unlock()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* libsecp256k1 Create an ECDSA signature.
|
|
||||||
*
|
|
||||||
* @param data Message hash, 32 bytes
|
|
||||||
* @param sec Secret key, 32 bytes
|
|
||||||
* @param compact True for compact signature, false for DER
|
|
||||||
* @return a signature, or an empty array is signing failed
|
|
||||||
* @throws AssertFailException in case of failure
|
|
||||||
*/
|
|
||||||
@JvmStatic
|
|
||||||
@Throws(AssertFailException::class)
|
|
||||||
public fun sign(data: ByteArray, sec: ByteArray, compact: Boolean): ByteArray {
|
|
||||||
require(data.size == 32 && sec.size <= 32)
|
|
||||||
val byteBuff = pack(data, sec)
|
|
||||||
val retByteArray: Array<ByteArray>
|
|
||||||
r.lock()
|
|
||||||
retByteArray = try {
|
|
||||||
secp256k1_ecdsa_sign(
|
|
||||||
byteBuff,
|
|
||||||
compact,
|
|
||||||
Secp256k1Context.getContext()
|
|
||||||
)
|
|
||||||
} finally {
|
|
||||||
r.unlock()
|
|
||||||
}
|
|
||||||
val sigArr = retByteArray[0]
|
|
||||||
val sigLen = BigInteger(byteArrayOf(retByteArray[1][0])).toInt()
|
|
||||||
val retVal = BigInteger(byteArrayOf(retByteArray[1][1])).toInt()
|
|
||||||
NativeSecp256k1Util.assertEquals(
|
|
||||||
sigArr.size,
|
|
||||||
sigLen,
|
|
||||||
"Got bad signature length."
|
|
||||||
)
|
|
||||||
return if (retVal == 0) ByteArray(0) else sigArr
|
|
||||||
}
|
|
||||||
|
|
||||||
@JvmStatic
|
|
||||||
@Throws(AssertFailException::class)
|
|
||||||
public fun signatureNormalize(sig: ByteArray, compact: Boolean): Pair<ByteArray, Boolean> {
|
|
||||||
require(sig.size == 64 || sig.size in 70..73)
|
|
||||||
val byteBuff = pack(sig)
|
|
||||||
val retByteArray: Array<ByteArray>
|
|
||||||
r.lock()
|
|
||||||
retByteArray = try {
|
|
||||||
secp256k1_ecdsa_normalize(
|
|
||||||
byteBuff,
|
|
||||||
sig.size,
|
|
||||||
compact,
|
|
||||||
Secp256k1Context.getContext()
|
|
||||||
)
|
|
||||||
} finally {
|
|
||||||
r.unlock()
|
|
||||||
}
|
|
||||||
val sigArr = retByteArray[0]
|
|
||||||
val sigLen = BigInteger(byteArrayOf(retByteArray[1][0])).toInt()
|
|
||||||
val retVal = BigInteger(byteArrayOf(retByteArray[1][1])).toInt()
|
|
||||||
val retBool = BigInteger(byteArrayOf(retByteArray[1][2])).toInt()
|
|
||||||
NativeSecp256k1Util.assertEquals(
|
|
||||||
sigArr.size,
|
|
||||||
sigLen,
|
|
||||||
"Got bad signature length."
|
|
||||||
)
|
|
||||||
return (if (retVal == 0) ByteArray(0) else sigArr) to (retBool == 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* libsecp256k1 Seckey Verify - returns 1 if valid, 0 if invalid
|
|
||||||
*
|
|
||||||
* @param seckey ECDSA Secret key, 32 bytes
|
|
||||||
* @return true if seckey is valid
|
|
||||||
*/
|
|
||||||
@JvmStatic
|
|
||||||
public fun secKeyVerify(seckey: ByteArray): Boolean {
|
|
||||||
require(seckey.size == 32)
|
|
||||||
val byteBuff = pack(seckey)
|
|
||||||
r.lock()
|
|
||||||
return try {
|
|
||||||
secp256k1_ec_seckey_verify(
|
|
||||||
byteBuff,
|
|
||||||
Secp256k1Context.getContext()
|
|
||||||
) == 1
|
|
||||||
} finally {
|
|
||||||
r.unlock()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* libsecp256k1 Compute Pubkey - computes public key from secret key
|
|
||||||
*
|
|
||||||
* @param seckey ECDSA Secret key, 32 bytes
|
|
||||||
* @throws AssertFailException if parameters are not valid
|
|
||||||
* @return the corresponding public key (uncompressed)
|
|
||||||
*/
|
|
||||||
//TODO add a 'compressed' arg
|
|
||||||
@JvmStatic
|
|
||||||
@Throws(AssertFailException::class)
|
|
||||||
public fun computePubkey(seckey: ByteArray, compressed: Boolean): ByteArray {
|
|
||||||
require(seckey.size == 32)
|
|
||||||
val byteBuff = pack(seckey)
|
|
||||||
val retByteArray: Array<ByteArray>
|
|
||||||
r.lock()
|
|
||||||
retByteArray = try {
|
|
||||||
secp256k1_ec_pubkey_create(
|
|
||||||
byteBuff,
|
|
||||||
compressed,
|
|
||||||
Secp256k1Context.getContext()
|
|
||||||
)
|
|
||||||
} finally {
|
|
||||||
r.unlock()
|
|
||||||
}
|
|
||||||
val pubArr = retByteArray[0]
|
|
||||||
val pubLen = BigInteger(byteArrayOf(retByteArray[1][0])).toInt()
|
|
||||||
val retVal = BigInteger(byteArrayOf(retByteArray[1][1])).toInt()
|
|
||||||
NativeSecp256k1Util.assertEquals(pubArr.size, pubLen, "Got bad pubkey length.")
|
|
||||||
return if (retVal == 0) ByteArray(0) else pubArr
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param pubkey public key
|
|
||||||
* @return the input public key (uncompressed) if valid, or an empty array
|
|
||||||
* @throws AssertFailException in case of failure
|
|
||||||
*/
|
|
||||||
@JvmStatic
|
|
||||||
@Throws(AssertFailException::class)
|
|
||||||
public fun parsePubkey(pubkey: ByteArray, compressed: Boolean): ByteArray {
|
|
||||||
require(pubkey.size == 33 || pubkey.size == 65)
|
|
||||||
val byteBuff = pack(pubkey)
|
|
||||||
val retByteArray: Array<ByteArray>
|
|
||||||
r.lock()
|
|
||||||
retByteArray = try {
|
|
||||||
secp256k1_ec_pubkey_parse(
|
|
||||||
byteBuff,
|
|
||||||
Secp256k1Context.getContext(),
|
|
||||||
pubkey.size,
|
|
||||||
compressed
|
|
||||||
)
|
|
||||||
} finally {
|
|
||||||
r.unlock()
|
|
||||||
}
|
|
||||||
val pubArr = retByteArray[0]
|
|
||||||
BigInteger(byteArrayOf(retByteArray[1][0])).toInt()
|
|
||||||
val retVal = BigInteger(byteArrayOf(retByteArray[1][1])).toInt()
|
|
||||||
NativeSecp256k1Util.assertEquals(
|
|
||||||
pubArr.size,
|
|
||||||
if (compressed) 33 else 65,
|
|
||||||
"Got bad pubkey length."
|
|
||||||
)
|
|
||||||
return if (retVal == 0) ByteArray(0) else pubArr
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* libsecp256k1 Cleanup - This destroys the secp256k1 context object
|
|
||||||
* This should be called at the end of the program for proper cleanup of the context.
|
|
||||||
*/
|
|
||||||
@JvmStatic
|
|
||||||
@Synchronized
|
|
||||||
public fun cleanup() {
|
|
||||||
w.lock()
|
|
||||||
try {
|
|
||||||
secp256k1_destroy_context(Secp256k1Context.getContext())
|
|
||||||
} finally {
|
|
||||||
w.unlock()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@JvmStatic
|
|
||||||
@Throws(AssertFailException::class)
|
|
||||||
public fun privKeyNegate(privkey: ByteArray): ByteArray {
|
|
||||||
require(privkey.size == 32)
|
|
||||||
val byteBuff = pack(privkey)
|
|
||||||
val retByteArray: Array<ByteArray>
|
|
||||||
r.lock()
|
|
||||||
retByteArray = try {
|
|
||||||
secp256k1_privkey_negate(
|
|
||||||
byteBuff,
|
|
||||||
Secp256k1Context.getContext()
|
|
||||||
)
|
|
||||||
} finally {
|
|
||||||
r.unlock()
|
|
||||||
}
|
|
||||||
val privArr = retByteArray[0]
|
|
||||||
val privLen: Int = BigInteger(byteArrayOf(retByteArray[1][0])).toInt() and 0xFF
|
|
||||||
val retVal = BigInteger(byteArrayOf(retByteArray[1][1])).toInt()
|
|
||||||
NativeSecp256k1Util.assertEquals(
|
|
||||||
privArr.size,
|
|
||||||
privLen,
|
|
||||||
"Got bad privkey length."
|
|
||||||
)
|
|
||||||
NativeSecp256k1Util.assertEquals(retVal, 1, "Failed return value check.")
|
|
||||||
return privArr
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* libsecp256k1 PrivKey Tweak-Mul - Tweak privkey by multiplying to it
|
|
||||||
*
|
|
||||||
* @param privkey 32-byte seckey
|
|
||||||
* @param tweak some bytes to tweak with
|
|
||||||
* @return privkey * tweak
|
|
||||||
* @throws AssertFailException in case of failure
|
|
||||||
*/
|
|
||||||
@JvmStatic
|
|
||||||
@Throws(AssertFailException::class)
|
|
||||||
public fun privKeyTweakMul(privkey: ByteArray, tweak: ByteArray): ByteArray {
|
|
||||||
require(privkey.size == 32)
|
|
||||||
val byteBuff = pack(privkey, tweak)
|
|
||||||
val retByteArray: Array<ByteArray>
|
|
||||||
r.lock()
|
|
||||||
retByteArray = try {
|
|
||||||
secp256k1_privkey_tweak_mul(
|
|
||||||
byteBuff,
|
|
||||||
Secp256k1Context.getContext()
|
|
||||||
)
|
|
||||||
} finally {
|
|
||||||
r.unlock()
|
|
||||||
}
|
|
||||||
val privArr = retByteArray[0]
|
|
||||||
val privLen: Int = BigInteger(byteArrayOf(retByteArray[1][0])).toInt() and 0xFF
|
|
||||||
val retVal = BigInteger(byteArrayOf(retByteArray[1][1])).toInt()
|
|
||||||
NativeSecp256k1Util.assertEquals(
|
|
||||||
privArr.size,
|
|
||||||
privLen,
|
|
||||||
"Got bad privkey length."
|
|
||||||
)
|
|
||||||
NativeSecp256k1Util.assertEquals(retVal, 1, "Failed return value check.")
|
|
||||||
return privArr
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* libsecp256k1 PrivKey Tweak-Add - Tweak privkey by adding to it
|
|
||||||
*
|
|
||||||
* @param privkey 32-byte seckey
|
|
||||||
* @param tweak some bytes to tweak with
|
|
||||||
* @return privkey + tweak
|
|
||||||
* @throws AssertFailException in case of failure
|
|
||||||
*/
|
|
||||||
@JvmStatic
|
|
||||||
@Throws(AssertFailException::class)
|
|
||||||
public fun privKeyTweakAdd(privkey: ByteArray, tweak: ByteArray): ByteArray {
|
|
||||||
require(privkey.size == 32)
|
|
||||||
val byteBuff = pack(privkey, tweak)
|
|
||||||
val retByteArray: Array<ByteArray>
|
|
||||||
r.lock()
|
|
||||||
retByteArray = try {
|
|
||||||
secp256k1_privkey_tweak_add(
|
|
||||||
byteBuff,
|
|
||||||
Secp256k1Context.getContext()
|
|
||||||
)
|
|
||||||
} finally {
|
|
||||||
r.unlock()
|
|
||||||
}
|
|
||||||
val privArr = retByteArray[0]
|
|
||||||
val privLen: Int = BigInteger(byteArrayOf(retByteArray[1][0])).toInt() and 0xFF
|
|
||||||
val retVal = BigInteger(byteArrayOf(retByteArray[1][1])).toInt()
|
|
||||||
NativeSecp256k1Util.assertEquals(privArr.size, privLen, "Got bad pubkey length.")
|
|
||||||
NativeSecp256k1Util.assertEquals(retVal, 1, "Failed return value check.")
|
|
||||||
return privArr
|
|
||||||
}
|
|
||||||
|
|
||||||
@JvmStatic
|
|
||||||
@Throws(AssertFailException::class)
|
|
||||||
public fun pubKeyNegate(pubkey: ByteArray): ByteArray {
|
|
||||||
require(pubkey.size == 33 || pubkey.size == 65)
|
|
||||||
val byteBuff = pack(pubkey)
|
|
||||||
val retByteArray: Array<ByteArray>
|
|
||||||
r.lock()
|
|
||||||
retByteArray = try {
|
|
||||||
secp256k1_pubkey_negate(
|
|
||||||
byteBuff,
|
|
||||||
Secp256k1Context.getContext(),
|
|
||||||
pubkey.size
|
|
||||||
)
|
|
||||||
} finally {
|
|
||||||
r.unlock()
|
|
||||||
}
|
|
||||||
val pubArr = retByteArray[0]
|
|
||||||
val pubLen: Int = BigInteger(byteArrayOf(retByteArray[1][0])).toInt() and 0xFF
|
|
||||||
val retVal = BigInteger(byteArrayOf(retByteArray[1][1])).toInt()
|
|
||||||
NativeSecp256k1Util.assertEquals(pubArr.size, pubLen, "Got bad pubkey length.")
|
|
||||||
NativeSecp256k1Util.assertEquals(retVal, 1, "Failed return value check.")
|
|
||||||
return pubArr
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* libsecp256k1 PubKey Tweak-Add - Tweak pubkey by adding to it
|
|
||||||
*
|
|
||||||
* @param tweak some bytes to tweak with
|
|
||||||
* @param pubkey 32-byte seckey
|
|
||||||
* @return pubkey + tweak
|
|
||||||
* @throws AssertFailException in case of failure
|
|
||||||
*/
|
|
||||||
@JvmStatic
|
|
||||||
@Throws(AssertFailException::class)
|
|
||||||
public fun pubKeyTweakAdd(pubkey: ByteArray, tweak: ByteArray): ByteArray {
|
|
||||||
require(pubkey.size == 33 || pubkey.size == 65)
|
|
||||||
val byteBuff = pack(pubkey, tweak)
|
|
||||||
val retByteArray: Array<ByteArray>
|
|
||||||
r.lock()
|
|
||||||
retByteArray = try {
|
|
||||||
secp256k1_pubkey_tweak_add(
|
|
||||||
byteBuff,
|
|
||||||
Secp256k1Context.getContext(),
|
|
||||||
pubkey.size
|
|
||||||
)
|
|
||||||
} finally {
|
|
||||||
r.unlock()
|
|
||||||
}
|
|
||||||
val pubArr = retByteArray[0]
|
|
||||||
val pubLen: Int = BigInteger(byteArrayOf(retByteArray[1][0])).toInt() and 0xFF
|
|
||||||
val retVal = BigInteger(byteArrayOf(retByteArray[1][1])).toInt()
|
|
||||||
NativeSecp256k1Util.assertEquals(pubArr.size, pubLen, "Got bad pubkey length.")
|
|
||||||
NativeSecp256k1Util.assertEquals(retVal, 1, "Failed return value check.")
|
|
||||||
return pubArr
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* libsecp256k1 PubKey Tweak-Mul - Tweak pubkey by multiplying to it
|
|
||||||
*
|
|
||||||
* @param tweak some bytes to tweak with
|
|
||||||
* @param pubkey 32-byte seckey
|
|
||||||
* @return pubkey * tweak
|
|
||||||
* @throws AssertFailException in case of failure
|
|
||||||
*/
|
|
||||||
@JvmStatic
|
|
||||||
@Throws(AssertFailException::class)
|
|
||||||
public fun pubKeyTweakMul(pubkey: ByteArray, tweak: ByteArray): ByteArray {
|
|
||||||
require(pubkey.size == 33 || pubkey.size == 65)
|
|
||||||
val byteBuff = pack(pubkey, tweak)
|
|
||||||
val retByteArray: Array<ByteArray>
|
|
||||||
r.lock()
|
|
||||||
retByteArray = try {
|
|
||||||
secp256k1_pubkey_tweak_mul(
|
|
||||||
byteBuff,
|
|
||||||
Secp256k1Context.getContext(),
|
|
||||||
pubkey.size
|
|
||||||
)
|
|
||||||
} finally {
|
|
||||||
r.unlock()
|
|
||||||
}
|
|
||||||
val pubArr = retByteArray[0]
|
|
||||||
val pubLen: Int = BigInteger(byteArrayOf(retByteArray[1][0])).toInt() and 0xFF
|
|
||||||
val retVal = BigInteger(byteArrayOf(retByteArray[1][1])).toInt()
|
|
||||||
NativeSecp256k1Util.assertEquals(pubArr.size, pubLen, "Got bad pubkey length.")
|
|
||||||
NativeSecp256k1Util.assertEquals(retVal, 1, "Failed return value check.")
|
|
||||||
return pubArr
|
|
||||||
}
|
|
||||||
|
|
||||||
@JvmStatic
|
|
||||||
@Throws(AssertFailException::class)
|
|
||||||
public fun pubKeyAdd(pubkey1: ByteArray, pubkey2: ByteArray): ByteArray {
|
|
||||||
require(pubkey1.size == 33 || pubkey1.size == 65)
|
|
||||||
require(pubkey2.size == 33 || pubkey2.size == 65)
|
|
||||||
val byteBuff = pack(pubkey1, pubkey2)
|
|
||||||
val retByteArray: Array<ByteArray>
|
|
||||||
r.lock()
|
|
||||||
retByteArray = try {
|
|
||||||
secp256k1_ec_pubkey_add(
|
|
||||||
byteBuff,
|
|
||||||
Secp256k1Context.getContext(),
|
|
||||||
pubkey1.size,
|
|
||||||
pubkey2.size
|
|
||||||
)
|
|
||||||
} finally {
|
|
||||||
r.unlock()
|
|
||||||
}
|
|
||||||
val pubArr = retByteArray[0]
|
|
||||||
val pubLen: Int = BigInteger(byteArrayOf(retByteArray[1][0])).toInt() and 0xFF
|
|
||||||
val retVal = BigInteger(byteArrayOf(retByteArray[1][1])).toInt()
|
|
||||||
NativeSecp256k1Util.assertEquals(pubkey1.size, pubLen, "Got bad pubkey length.")
|
|
||||||
NativeSecp256k1Util.assertEquals(retVal, 1, "Failed return value check.")
|
|
||||||
return pubArr
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* libsecp256k1 create ECDH secret - constant time ECDH calculation
|
|
||||||
*
|
|
||||||
* @param seckey byte array of secret key used in exponentiaion
|
|
||||||
* @param pubkey byte array of public key used in exponentiaion
|
|
||||||
* @return ecdh(sedckey, pubkey)
|
|
||||||
* @throws AssertFailException in case of failure
|
|
||||||
*/
|
|
||||||
@JvmStatic
|
|
||||||
@Throws(AssertFailException::class)
|
|
||||||
public fun createECDHSecret(seckey: ByteArray, pubkey: ByteArray): ByteArray {
|
|
||||||
require(seckey.size <= 32 && pubkey.size <= 65)
|
|
||||||
val byteBuff = pack(seckey, pubkey)
|
|
||||||
val retByteArray: Array<ByteArray>
|
|
||||||
r.lock()
|
|
||||||
retByteArray = try {
|
|
||||||
secp256k1_ecdh(
|
|
||||||
byteBuff,
|
|
||||||
Secp256k1Context.getContext(),
|
|
||||||
pubkey.size
|
|
||||||
)
|
|
||||||
} finally {
|
|
||||||
r.unlock()
|
|
||||||
}
|
|
||||||
val resArr = retByteArray[0]
|
|
||||||
val retVal = BigInteger(byteArrayOf(retByteArray[1][0])).toInt()
|
|
||||||
NativeSecp256k1Util.assertEquals(resArr.size, 32, "Got bad result length.")
|
|
||||||
NativeSecp256k1Util.assertEquals(retVal, 1, "Failed return value check.")
|
|
||||||
return resArr
|
|
||||||
}
|
|
||||||
|
|
||||||
@JvmStatic
|
|
||||||
@Throws(AssertFailException::class)
|
|
||||||
public fun ecdsaRecover(sig: ByteArray, message: ByteArray, recid: Int, compressed: Boolean): ByteArray {
|
|
||||||
require(sig.size == 64)
|
|
||||||
require(message.size == 32)
|
|
||||||
val byteBuff = pack(sig, message)
|
|
||||||
val retByteArray: Array<ByteArray>
|
|
||||||
r.lock()
|
|
||||||
retByteArray = try {
|
|
||||||
secp256k1_ecdsa_recover(
|
|
||||||
byteBuff,
|
|
||||||
Secp256k1Context.getContext(),
|
|
||||||
recid,
|
|
||||||
compressed
|
|
||||||
)
|
|
||||||
} finally {
|
|
||||||
r.unlock()
|
|
||||||
}
|
|
||||||
val resArr = retByteArray[0]
|
|
||||||
val retVal = BigInteger(byteArrayOf(retByteArray[1][0])).toInt()
|
|
||||||
NativeSecp256k1Util.assertEquals(
|
|
||||||
resArr.size,
|
|
||||||
if (compressed) 33 else 65,
|
|
||||||
"Got bad result length."
|
|
||||||
)
|
|
||||||
NativeSecp256k1Util.assertEquals(retVal, 1, "Failed return value check.")
|
|
||||||
return resArr
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* libsecp256k1 randomize - updates the context randomization
|
|
||||||
*
|
|
||||||
* @param seed 32-byte random seed
|
|
||||||
* @return true if successful
|
|
||||||
* @throws AssertFailException in case of failure
|
|
||||||
*/
|
|
||||||
@JvmStatic
|
|
||||||
@Synchronized
|
|
||||||
@Throws(AssertFailException::class)
|
|
||||||
public fun randomize(seed: ByteArray): Boolean {
|
|
||||||
require(seed.size == 32)
|
|
||||||
val byteBuff = pack(seed)
|
|
||||||
w.lock()
|
|
||||||
return try {
|
|
||||||
secp256k1_context_randomize(
|
|
||||||
byteBuff,
|
|
||||||
Secp256k1Context.getContext()
|
|
||||||
) == 1
|
|
||||||
} finally {
|
|
||||||
w.unlock()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@JvmStatic private external fun secp256k1_context_randomize(byteBuff: ByteBuffer, context: Long): Int
|
|
||||||
@JvmStatic private external fun secp256k1_privkey_negate(byteBuff: ByteBuffer, context: Long): Array<ByteArray>
|
|
||||||
@JvmStatic private external fun secp256k1_privkey_tweak_add(byteBuff: ByteBuffer, context: Long): Array<ByteArray>
|
|
||||||
@JvmStatic private external fun secp256k1_privkey_tweak_mul(byteBuff: ByteBuffer, context: Long): Array<ByteArray>
|
|
||||||
@JvmStatic private external fun secp256k1_pubkey_negate(byteBuff: ByteBuffer, context: Long, pubLen: Int): Array<ByteArray>
|
|
||||||
@JvmStatic private external fun secp256k1_pubkey_tweak_add(byteBuff: ByteBuffer, context: Long, pubLen: Int): Array<ByteArray>
|
|
||||||
@JvmStatic private external fun secp256k1_pubkey_tweak_mul(byteBuff: ByteBuffer, context: Long, pubLen: Int): Array<ByteArray>
|
|
||||||
@JvmStatic private external fun secp256k1_destroy_context(context: Long)
|
|
||||||
@JvmStatic private external fun secp256k1_ecdsa_verify(byteBuff: ByteBuffer, context: Long, sigLen: Int, pubLen: Int): Int
|
|
||||||
@JvmStatic private external fun secp256k1_ecdsa_sign(byteBuff: ByteBuffer, compact: Boolean, context: Long): Array<ByteArray>
|
|
||||||
@JvmStatic private external fun secp256k1_ecdsa_normalize(byteBuff: ByteBuffer, sigLen: Int, compact: Boolean, context: Long): Array<ByteArray>
|
|
||||||
@JvmStatic private external fun secp256k1_ec_seckey_verify(byteBuff: ByteBuffer, context: Long): Int
|
|
||||||
@JvmStatic private external fun secp256k1_ec_pubkey_create(byteBuff: ByteBuffer, compressed: Boolean, context: Long): Array<ByteArray>
|
|
||||||
@JvmStatic private external fun secp256k1_ec_pubkey_parse(byteBuff: ByteBuffer, context: Long, inputLen: Int, compressed: Boolean): Array<ByteArray>
|
|
||||||
@JvmStatic private external fun secp256k1_ec_pubkey_add(byteBuff: ByteBuffer, context: Long, lent1: Int, len2: Int): Array<ByteArray>
|
|
||||||
@JvmStatic private external fun secp256k1_ecdh(byteBuff: ByteBuffer, context: Long, inputLen: Int): Array<ByteArray>
|
|
||||||
@JvmStatic private external fun secp256k1_ecdsa_recover(byteBuff: ByteBuffer, context: Long, recid: Int, compressed: Boolean): Array<ByteArray>
|
|
||||||
}
|
|
@ -1,28 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2014-2016 the libsecp256k1 contributors
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package org.bitcoin
|
|
||||||
|
|
||||||
import kotlin.jvm.Throws
|
|
||||||
import java.lang.Exception
|
|
||||||
|
|
||||||
internal object NativeSecp256k1Util {
|
|
||||||
@Throws(AssertFailException::class)
|
|
||||||
fun assertEquals(val1: Int, val2: Int, message: String) {
|
|
||||||
if (val1 != val2) throw AssertFailException("FAIL: $message")
|
|
||||||
}
|
|
||||||
|
|
||||||
class AssertFailException(message: String?) : Exception(message)
|
|
||||||
}
|
|
@ -1,39 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2014-2016 the libsecp256k1 contributors
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package org.bitcoin
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This class holds the context reference used in native methods
|
|
||||||
* to handle ECDSA operations.
|
|
||||||
*/
|
|
||||||
public object Secp256k1Context {
|
|
||||||
@JvmStatic
|
|
||||||
public val isEnabled: Boolean //true if the library is loaded
|
|
||||||
private val context: Long //ref to pointer to context obj
|
|
||||||
|
|
||||||
@JvmStatic
|
|
||||||
public fun getContext(): Long {
|
|
||||||
return if (!isEnabled) -1 else context //sanity check
|
|
||||||
}
|
|
||||||
|
|
||||||
@JvmStatic private external fun secp256k1_init_context(): Long
|
|
||||||
|
|
||||||
init { //static initializer
|
|
||||||
isEnabled = true
|
|
||||||
context =
|
|
||||||
secp256k1_init_context()
|
|
||||||
}
|
|
||||||
}
|
|
@ -5,7 +5,7 @@ import platform.posix.size_tVar
|
|||||||
import secp256k1.*
|
import secp256k1.*
|
||||||
|
|
||||||
@OptIn(ExperimentalUnsignedTypes::class)
|
@OptIn(ExperimentalUnsignedTypes::class)
|
||||||
public actual object Secp256k1 {
|
public object Secp256k1Native : Secp256k1 {
|
||||||
|
|
||||||
private val ctx: CPointer<secp256k1_context> by lazy {
|
private val ctx: CPointer<secp256k1_context> by lazy {
|
||||||
secp256k1_context_create((SECP256K1_FLAGS_TYPE_CONTEXT or SECP256K1_FLAGS_BIT_CONTEXT_SIGN or SECP256K1_FLAGS_BIT_CONTEXT_VERIFY).toUInt())
|
secp256k1_context_create((SECP256K1_FLAGS_TYPE_CONTEXT or SECP256K1_FLAGS_BIT_CONTEXT_SIGN or SECP256K1_FLAGS_BIT_CONTEXT_VERIFY).toUInt())
|
||||||
@ -28,7 +28,7 @@ public actual object Secp256k1 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun MemScope.serializeSignature(signature: secp256k1_ecdsa_signature, format: SigFormat): ByteArray {
|
private fun MemScope.serializeSignature(signature: secp256k1_ecdsa_signature, format: SigFormat): ByteArray {
|
||||||
val natOutput = allocArray<UByteVar>(format.size)
|
val natOutput = allocArray<UByteVar>(format.maxSize)
|
||||||
when (format) {
|
when (format) {
|
||||||
SigFormat.DER -> {
|
SigFormat.DER -> {
|
||||||
val outputLen = alloc<size_tVar>()
|
val outputLen = alloc<size_tVar>()
|
||||||
@ -65,7 +65,7 @@ public actual object Secp256k1 {
|
|||||||
return pinned.addressOf(0)
|
return pinned.addressOf(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
public actual fun verify(data: ByteArray, signature: ByteArray, pub: ByteArray): Boolean {
|
public override fun verify(data: ByteArray, signature: ByteArray, pub: ByteArray): Boolean {
|
||||||
require(data.size == 32)
|
require(data.size == 32)
|
||||||
require(pub.size == 33 || pub.size == 65)
|
require(pub.size == 33 || pub.size == 65)
|
||||||
memScoped {
|
memScoped {
|
||||||
@ -76,7 +76,7 @@ public actual object Secp256k1 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public actual fun sign(data: ByteArray, sec: ByteArray, format: SigFormat): ByteArray {
|
public override fun sign(data: ByteArray, sec: ByteArray, format: SigFormat): ByteArray {
|
||||||
require(sec.size == 32)
|
require(sec.size == 32)
|
||||||
require(data.size == 32)
|
require(data.size == 32)
|
||||||
memScoped {
|
memScoped {
|
||||||
@ -89,7 +89,7 @@ public actual object Secp256k1 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public actual fun signatureNormalize(sig: ByteArray, format: SigFormat): Pair<ByteArray, Boolean> {
|
public override fun signatureNormalize(sig: ByteArray, format: SigFormat): Pair<ByteArray, Boolean> {
|
||||||
require(sig.size == 64 || sig.size in 70..73)
|
require(sig.size == 64 || sig.size in 70..73)
|
||||||
memScoped {
|
memScoped {
|
||||||
val nSig = allocSignature(sig)
|
val nSig = allocSignature(sig)
|
||||||
@ -98,7 +98,7 @@ public actual object Secp256k1 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public actual fun secKeyVerify(seckey: ByteArray): Boolean {
|
public override fun secKeyVerify(seckey: ByteArray): Boolean {
|
||||||
require(seckey.size == 32)
|
require(seckey.size == 32)
|
||||||
memScoped {
|
memScoped {
|
||||||
val nSec = toNat(seckey)
|
val nSec = toNat(seckey)
|
||||||
@ -106,30 +106,30 @@ public actual object Secp256k1 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public actual fun computePubkey(seckey: ByteArray, format: PubKeyFormat): ByteArray {
|
public override fun computePubkey(seckey: ByteArray, format: PubKeyFormat): ByteArray {
|
||||||
require(seckey.size == 32)
|
require(seckey.size == 32)
|
||||||
memScoped {
|
memScoped {
|
||||||
val nSec = toNat(seckey)
|
val nSec = toNat(seckey)
|
||||||
val nPubkey = alloc<secp256k1_pubkey>()
|
val nPubkey = alloc<secp256k1_pubkey>()
|
||||||
val result = secp256k1_ec_pubkey_create(ctx, nPubkey.ptr, nSec)
|
val result = secp256k1_ec_pubkey_create(ctx, nPubkey.ptr, nSec)
|
||||||
if (result == 0) return ByteArray(0)
|
if (result == 0) return ByteArray(0)
|
||||||
return serializePubkey(nPubkey, format.size)
|
return serializePubkey(nPubkey, format.maxSize)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public actual fun parsePubkey(pubkey: ByteArray, format: PubKeyFormat): ByteArray {
|
public override fun parsePubkey(pubkey: ByteArray, format: PubKeyFormat): ByteArray {
|
||||||
require(pubkey.size == 33 || pubkey.size == 65)
|
require(pubkey.size == 33 || pubkey.size == 65)
|
||||||
memScoped {
|
memScoped {
|
||||||
val nPubkey = allocPublicKey(pubkey)
|
val nPubkey = allocPublicKey(pubkey)
|
||||||
return serializePubkey(nPubkey, format.size)
|
return serializePubkey(nPubkey, format.maxSize)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public actual fun cleanup() {
|
public override fun cleanup() {
|
||||||
secp256k1_context_destroy(ctx)
|
secp256k1_context_destroy(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
public actual fun privKeyNegate(privkey: ByteArray): ByteArray {
|
public override fun privKeyNegate(privkey: ByteArray): ByteArray {
|
||||||
require(privkey.size == 32)
|
require(privkey.size == 32)
|
||||||
memScoped {
|
memScoped {
|
||||||
val negated = privkey.copyOf()
|
val negated = privkey.copyOf()
|
||||||
@ -139,7 +139,7 @@ public actual object Secp256k1 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public actual fun privKeyTweakMul(privkey: ByteArray, tweak: ByteArray): ByteArray {
|
public override fun privKeyTweakMul(privkey: ByteArray, tweak: ByteArray): ByteArray {
|
||||||
require(privkey.size == 32)
|
require(privkey.size == 32)
|
||||||
memScoped {
|
memScoped {
|
||||||
val multiplied = privkey.copyOf()
|
val multiplied = privkey.copyOf()
|
||||||
@ -150,7 +150,7 @@ public actual object Secp256k1 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public actual fun privKeyTweakAdd(privkey: ByteArray, tweak: ByteArray): ByteArray {
|
public override fun privKeyTweakAdd(privkey: ByteArray, tweak: ByteArray): ByteArray {
|
||||||
require(privkey.size == 32)
|
require(privkey.size == 32)
|
||||||
memScoped {
|
memScoped {
|
||||||
val added = privkey.copyOf()
|
val added = privkey.copyOf()
|
||||||
@ -161,7 +161,7 @@ public actual object Secp256k1 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public actual fun pubKeyNegate(pubkey: ByteArray): ByteArray {
|
public override fun pubKeyNegate(pubkey: ByteArray): ByteArray {
|
||||||
require(pubkey.size == 33 || pubkey.size == 65)
|
require(pubkey.size == 33 || pubkey.size == 65)
|
||||||
memScoped {
|
memScoped {
|
||||||
val nPubkey = allocPublicKey(pubkey)
|
val nPubkey = allocPublicKey(pubkey)
|
||||||
@ -170,7 +170,7 @@ public actual object Secp256k1 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public actual fun pubKeyTweakAdd(pubkey: ByteArray, tweak: ByteArray): ByteArray {
|
public override fun pubKeyTweakAdd(pubkey: ByteArray, tweak: ByteArray): ByteArray {
|
||||||
require(pubkey.size == 33 || pubkey.size == 65)
|
require(pubkey.size == 33 || pubkey.size == 65)
|
||||||
memScoped {
|
memScoped {
|
||||||
val nPubkey = allocPublicKey(pubkey)
|
val nPubkey = allocPublicKey(pubkey)
|
||||||
@ -180,7 +180,7 @@ public actual object Secp256k1 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public actual fun pubKeyTweakMul(pubkey: ByteArray, tweak: ByteArray): ByteArray {
|
public override fun pubKeyTweakMul(pubkey: ByteArray, tweak: ByteArray): ByteArray {
|
||||||
require(pubkey.size == 33 || pubkey.size == 65)
|
require(pubkey.size == 33 || pubkey.size == 65)
|
||||||
memScoped {
|
memScoped {
|
||||||
val nPubkey = allocPublicKey(pubkey)
|
val nPubkey = allocPublicKey(pubkey)
|
||||||
@ -190,7 +190,7 @@ public actual object Secp256k1 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public actual fun pubKeyAdd(pubkey1: ByteArray, pubkey2: ByteArray): ByteArray {
|
public override fun pubKeyAdd(pubkey1: ByteArray, pubkey2: ByteArray): ByteArray {
|
||||||
require(pubkey1.size == 33 || pubkey1.size == 65)
|
require(pubkey1.size == 33 || pubkey1.size == 65)
|
||||||
require(pubkey2.size == 33 || pubkey2.size == 65)
|
require(pubkey2.size == 33 || pubkey2.size == 65)
|
||||||
memScoped {
|
memScoped {
|
||||||
@ -202,7 +202,7 @@ public actual object Secp256k1 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public actual fun createECDHSecret(seckey: ByteArray, pubkey: ByteArray): ByteArray {
|
public override fun createECDHSecret(seckey: ByteArray, pubkey: ByteArray): ByteArray {
|
||||||
require(seckey.size == 32)
|
require(seckey.size == 32)
|
||||||
require(pubkey.size == 33 || pubkey.size == 65)
|
require(pubkey.size == 33 || pubkey.size == 65)
|
||||||
memScoped {
|
memScoped {
|
||||||
@ -214,7 +214,7 @@ public actual object Secp256k1 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public actual fun ecdsaRecover(sig: ByteArray, message: ByteArray, recid: Int, format: PubKeyFormat): ByteArray {
|
public override fun ecdsaRecover(sig: ByteArray, message: ByteArray, recid: Int, format: PubKeyFormat): ByteArray {
|
||||||
require(sig.size == 64)
|
require(sig.size == 64)
|
||||||
require(message.size == 32)
|
require(message.size == 32)
|
||||||
memScoped {
|
memScoped {
|
||||||
@ -224,11 +224,11 @@ public actual object Secp256k1 {
|
|||||||
val nMessage = toNat(message)
|
val nMessage = toNat(message)
|
||||||
val pubkey = alloc<secp256k1_pubkey>()
|
val pubkey = alloc<secp256k1_pubkey>()
|
||||||
secp256k1_ecdsa_recover(ctx, pubkey.ptr, rSig.ptr, nMessage).requireSuccess()
|
secp256k1_ecdsa_recover(ctx, pubkey.ptr, rSig.ptr, nMessage).requireSuccess()
|
||||||
return serializePubkey(pubkey, format.size)
|
return serializePubkey(pubkey, format.maxSize)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public actual fun randomize(seed: ByteArray): Boolean {
|
public override fun randomize(seed: ByteArray): Boolean {
|
||||||
require(seed.size == 32)
|
require(seed.size == 32)
|
||||||
memScoped {
|
memScoped {
|
||||||
val nSeed = toNat(seed)
|
val nSeed = toNat(seed)
|
||||||
@ -236,3 +236,5 @@ public actual object Secp256k1 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal actual fun getSecpk256k1(): Secp256k1 = Secp256k1Native
|
Loading…
x
Reference in New Issue
Block a user