Export Schnorr signature API (#32)

Implement Schnorr signatures (BIP 340)
This commit is contained in:
Fabrice Drouin
2021-11-23 17:38:46 +01:00
committed by GitHub
parent 5ee01ea526
commit ac7d4983d5
11 changed files with 232 additions and 6 deletions

View File

@@ -38,6 +38,24 @@ public interface Secp256k1 {
public fun sign(message: ByteArray, privkey: ByteArray): ByteArray
/**
* Verify a Schnorr signature.
*
* @param signature 64 bytes signature.
* @param message message signed.
* @param pubkey signer's x-only public key (32 bytes).
*/
public fun verifySchnorr(signature: ByteArray, data: ByteArray, pub: ByteArray): Boolean
/**
* Create a Schnorr signature.
*
* @param message message to sign.
* @param privkey signer's private key.
* @param auxrand32 32 bytes of fresh randomness (optional).
*/
public fun signSchnorr(data: ByteArray, sec: ByteArray, auxrand32: ByteArray?): ByteArray
/**
* Convert an ECDSA signature to a normalized lower-S form (bitcoin standardness rule).
* Returns the normalized signature and a boolean set to true if the input signature was not normalized.
*

View File

@@ -1,7 +1,7 @@
package = secp256k1
headers = secp256k1.h secp256k1_ecdh.h secp256k1_recovery.h
headerFilter = secp256k1/** secp256k1_ecdh.h secp256k1_recovery.h secp256k1.h
headers = secp256k1.h secp256k1_ecdh.h secp256k1_recovery.h secp256k1_extrakeys.h secp256k1_schnorrsig.h
headerFilter = secp256k1/** secp256k1_ecdh.h secp256k1_recovery.h secp256k1_extrakeys.h secp256k1_schnorrsig.h secp256k1.h
libraryPaths.linux = c/secp256k1/build/linux/
linkerOpts.linux = -L/usr/lib64 -L/usr/lib/x86_64-linux-gnu -L/usr/local/lib

View File

@@ -222,9 +222,41 @@ public object Secp256k1Native : Secp256k1 {
}
}
override fun verifySchnorr(signature: ByteArray, data: ByteArray, pub: ByteArray): Boolean {
require(signature.size == 64)
require(data.size == 32)
require(pub.size == 32)
memScoped {
val nPub = toNat(pub)
val pubkey = alloc<secp256k1_xonly_pubkey>()
secp256k1_xonly_pubkey_parse(ctx, pubkey.ptr, nPub).requireSuccess("secp256k1_xonly_pubkey_parse() failed")
val nData = toNat(data)
val nSig = toNat(signature)
return secp256k1_schnorrsig_verify(ctx, nSig, nData, 32, pubkey.ptr) == 1
}
}
override fun signSchnorr(data: ByteArray, sec: ByteArray, auxrand32: ByteArray?): ByteArray {
require(sec.size == 32)
require(data.size == 32)
auxrand32?.let { require(it.size == 32) }
memScoped {
val nSec = toNat(sec)
val nData = toNat(data)
val nAuxrand32 = auxrand32?.let { toNat(it) }
val nSig = allocArray<UByteVar>(64)
val keypair = alloc<secp256k1_keypair>()
secp256k1_keypair_create(ctx, keypair.ptr, nSec).requireSuccess("secp256k1_keypair_create() failed")
secp256k1_schnorrsig_sign(ctx, nSig, nData, keypair.ptr, nAuxrand32).requireSuccess("secp256k1_ecdsa_sign() failed")
return nSig.readBytes(64)
}
}
public override fun cleanup() {
secp256k1_context_destroy(ctx)
}
}
internal actual fun getSecpk256k1(): Secp256k1 = Secp256k1Native