Compare commits
5 Commits
frost
...
snapshot/i
Author | SHA1 | Date | |
---|---|---|---|
|
0364ec762e | ||
|
aadffabe42 | ||
|
8e17e7030a | ||
|
929e2cda40 | ||
|
41eac9273f |
@ -22,7 +22,7 @@ buildscript {
|
|||||||
|
|
||||||
allprojects {
|
allprojects {
|
||||||
group = "fr.acinq.secp256k1"
|
group = "fr.acinq.secp256k1"
|
||||||
version = "0.11.0"
|
version = "0.12.0-SNAPSHOT"
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
google()
|
google()
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -166,7 +166,17 @@ public interface Secp256k1 {
|
|||||||
|
|
||||||
internal expect fun getSecpk256k1(): Secp256k1
|
internal expect fun getSecpk256k1(): Secp256k1
|
||||||
|
|
||||||
public class Secp256k1Exception : RuntimeException {
|
public open class Secp256k1Exception : RuntimeException {
|
||||||
|
public constructor() : super()
|
||||||
|
public constructor(message: String?) : super(message)
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Secp256k1ErrorCallbackException : Secp256k1Exception {
|
||||||
|
public constructor() : super()
|
||||||
|
public constructor(message: String?) : super(message)
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Secp256k1IllegalCallbackException : Secp256k1Exception {
|
||||||
public constructor() : super()
|
public constructor() : super()
|
||||||
public constructor(message: String?) : super(message)
|
public constructor(message: String?) : super(message)
|
||||||
}
|
}
|
@ -4,15 +4,67 @@ import kotlinx.cinterop.*
|
|||||||
import platform.posix.size_tVar
|
import platform.posix.size_tVar
|
||||||
import secp256k1.*
|
import secp256k1.*
|
||||||
|
|
||||||
@OptIn(ExperimentalUnsignedTypes::class)
|
private typealias Secp256k1CallbackHandler = (String) -> Unit
|
||||||
|
|
||||||
|
@OptIn(ExperimentalStdlibApi::class)
|
||||||
|
private class CallbackHandler(ctx: CPointer<secp256k1_context>) : AutoCloseable {
|
||||||
|
var illegalCallBackMessage: String? = null
|
||||||
|
val illegalHandler: Secp256k1CallbackHandler = { x: String -> illegalCallBackMessage = x }
|
||||||
|
val illegalCallbackRef = StableRef.create(illegalHandler)
|
||||||
|
var errorCallBackMessage: String? = null
|
||||||
|
val errorHandler: Secp256k1CallbackHandler = { x: String -> errorCallBackMessage = x }
|
||||||
|
val errorCallbackRef = StableRef.create(errorHandler)
|
||||||
|
|
||||||
|
init {
|
||||||
|
secp256k1_context_set_error_callback(
|
||||||
|
ctx, staticCFunction { buffer: CPointer<ByteVar>?, data: COpaquePointer? ->
|
||||||
|
if (data != null) {
|
||||||
|
val callback = data.asStableRef<Secp256k1CallbackHandler>().get()
|
||||||
|
callback(buffer?.toKString() ?: "error callback triggered")
|
||||||
|
}
|
||||||
|
},
|
||||||
|
errorCallbackRef.asCPointer()
|
||||||
|
)
|
||||||
|
secp256k1_context_set_illegal_callback(
|
||||||
|
ctx, staticCFunction { buffer: CPointer<ByteVar>?, data: COpaquePointer? ->
|
||||||
|
if (data != null) {
|
||||||
|
val callback = data.asStableRef<Secp256k1CallbackHandler>().get()
|
||||||
|
callback(buffer?.toKString() ?: "illegal callback triggered")
|
||||||
|
}
|
||||||
|
},
|
||||||
|
illegalCallbackRef.asCPointer()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun checkForErrors() {
|
||||||
|
errorCallBackMessage?.let { throw Secp256k1ErrorCallbackException(it) }
|
||||||
|
illegalCallBackMessage?.let { throw Secp256k1IllegalCallbackException(it) }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun close() {
|
||||||
|
// StableRef instances have to be disposed of manually
|
||||||
|
illegalCallbackRef.dispose()
|
||||||
|
errorCallbackRef.dispose()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@OptIn(ExperimentalUnsignedTypes::class, ExperimentalStdlibApi::class)
|
||||||
public object Secp256k1Native : 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())
|
||||||
?: error("Could not create secp256k1 context")
|
?: error("Could not create secp256k1 context")
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun Int.requireSuccess(message: String): Int = if (this != 1) throw Secp256k1Exception(message) else this
|
private fun Int.requireSuccess(message: String): Int {
|
||||||
|
return if (this != 1) throw Secp256k1Exception(message) else this
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Int.requireSuccess(callbackHandler: CallbackHandler, message: String): Int {
|
||||||
|
callbackHandler.checkForErrors()
|
||||||
|
return if (this != 1) throw Secp256k1Exception(message) else this
|
||||||
|
}
|
||||||
|
|
||||||
private fun MemScope.allocSignature(input: ByteArray): secp256k1_ecdsa_signature {
|
private fun MemScope.allocSignature(input: ByteArray): secp256k1_ecdsa_signature {
|
||||||
val sig = alloc<secp256k1_ecdsa_signature>()
|
val sig = alloc<secp256k1_ecdsa_signature>()
|
||||||
@ -58,167 +110,209 @@ public object Secp256k1Native : Secp256k1 {
|
|||||||
public override fun verify(signature: ByteArray, message: ByteArray, pubkey: ByteArray): Boolean {
|
public override fun verify(signature: ByteArray, message: ByteArray, pubkey: ByteArray): Boolean {
|
||||||
require(message.size == 32)
|
require(message.size == 32)
|
||||||
require(pubkey.size == 33 || pubkey.size == 65)
|
require(pubkey.size == 33 || pubkey.size == 65)
|
||||||
memScoped {
|
CallbackHandler(ctx).use { callbackHandler ->
|
||||||
val nPubkey = allocPublicKey(pubkey)
|
memScoped {
|
||||||
val nMessage = toNat(message)
|
val nPubkey = allocPublicKey(pubkey)
|
||||||
val nSig = allocSignature(signature)
|
val nMessage = toNat(message)
|
||||||
return secp256k1_ecdsa_verify(ctx, nSig.ptr, nMessage, nPubkey.ptr) == 1
|
val nSig = allocSignature(signature)
|
||||||
|
val verify = secp256k1_ecdsa_verify(ctx, nSig.ptr, nMessage, nPubkey.ptr)
|
||||||
|
callbackHandler.checkForErrors()
|
||||||
|
return verify == 1
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override fun sign(message: ByteArray, privkey: ByteArray): ByteArray {
|
public override fun sign(message: ByteArray, privkey: ByteArray): ByteArray {
|
||||||
require(privkey.size == 32)
|
require(privkey.size == 32)
|
||||||
require(message.size == 32)
|
require(message.size == 32)
|
||||||
memScoped {
|
CallbackHandler(ctx).use { callbackHandler ->
|
||||||
val nPrivkey = toNat(privkey)
|
memScoped {
|
||||||
val nMessage = toNat(message)
|
val nPrivkey = toNat(privkey)
|
||||||
val nSig = alloc<secp256k1_ecdsa_signature>()
|
val nMessage = toNat(message)
|
||||||
secp256k1_ecdsa_sign(ctx, nSig.ptr, nMessage, nPrivkey, null, null).requireSuccess("secp256k1_ecdsa_sign() failed")
|
val nSig = alloc<secp256k1_ecdsa_signature>()
|
||||||
return serializeSignature(nSig)
|
secp256k1_ecdsa_sign(ctx, nSig.ptr, nMessage, nPrivkey, null, null).requireSuccess(callbackHandler, "secp256k1_ecdsa_sign() failed")
|
||||||
|
return serializeSignature(nSig)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override fun signatureNormalize(sig: ByteArray): Pair<ByteArray, Boolean> {
|
public override fun signatureNormalize(sig: ByteArray): Pair<ByteArray, Boolean> {
|
||||||
require(sig.size >= 64){ "invalid signature ${Hex.encode(sig)}" }
|
require(sig.size >= 64) { "invalid signature ${Hex.encode(sig)}" }
|
||||||
memScoped {
|
CallbackHandler(ctx).use { callbackHandler ->
|
||||||
val nSig = allocSignature(sig)
|
memScoped {
|
||||||
val isHighS = secp256k1_ecdsa_signature_normalize(ctx, nSig.ptr, nSig.ptr)
|
val nSig = allocSignature(sig)
|
||||||
return Pair(serializeSignature(nSig), isHighS == 1)
|
val isHighS = secp256k1_ecdsa_signature_normalize(ctx, nSig.ptr, nSig.ptr)
|
||||||
|
callbackHandler.checkForErrors()
|
||||||
|
return Pair(serializeSignature(nSig), isHighS == 1)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override fun secKeyVerify(privkey: ByteArray): Boolean {
|
public override fun secKeyVerify(privkey: ByteArray): Boolean {
|
||||||
if (privkey.size != 32) return false
|
if (privkey.size != 32) return false
|
||||||
memScoped {
|
CallbackHandler(ctx).use { callbackHandler ->
|
||||||
val nPrivkey = toNat(privkey)
|
memScoped {
|
||||||
return secp256k1_ec_seckey_verify(ctx, nPrivkey) == 1
|
val nPrivkey = toNat(privkey)
|
||||||
|
val result = secp256k1_ec_seckey_verify(ctx, nPrivkey) == 1
|
||||||
|
callbackHandler.checkForErrors()
|
||||||
|
return result
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override fun pubkeyCreate(privkey: ByteArray): ByteArray {
|
public override fun pubkeyCreate(privkey: ByteArray): ByteArray {
|
||||||
require(privkey.size == 32)
|
require(privkey.size == 32)
|
||||||
memScoped {
|
CallbackHandler(ctx).use { callbackHandler ->
|
||||||
val nPrivkey = toNat(privkey)
|
memScoped {
|
||||||
val nPubkey = alloc<secp256k1_pubkey>()
|
val nPrivkey = toNat(privkey)
|
||||||
secp256k1_ec_pubkey_create(ctx, nPubkey.ptr, nPrivkey).requireSuccess("secp256k1_ec_pubkey_create() failed")
|
val nPubkey = alloc<secp256k1_pubkey>()
|
||||||
return serializePubkey(nPubkey)
|
secp256k1_ec_pubkey_create(ctx, nPubkey.ptr, nPrivkey).requireSuccess(callbackHandler, "secp256k1_ec_pubkey_create() failed")
|
||||||
|
return serializePubkey(nPubkey)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override fun pubkeyParse(pubkey: ByteArray): ByteArray {
|
public override fun pubkeyParse(pubkey: ByteArray): ByteArray {
|
||||||
require(pubkey.size == 33 || pubkey.size == 65)
|
require(pubkey.size == 33 || pubkey.size == 65)
|
||||||
memScoped {
|
CallbackHandler(ctx).use { callbackHandler ->
|
||||||
val nPubkey = allocPublicKey(pubkey)
|
memScoped {
|
||||||
return serializePubkey(nPubkey)
|
val nPubkey = allocPublicKey(pubkey)
|
||||||
|
val result = serializePubkey(nPubkey)
|
||||||
|
callbackHandler.checkForErrors()
|
||||||
|
return result
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override fun privKeyNegate(privkey: ByteArray): ByteArray {
|
public override fun privKeyNegate(privkey: ByteArray): ByteArray {
|
||||||
require(privkey.size == 32)
|
require(privkey.size == 32)
|
||||||
memScoped {
|
CallbackHandler(ctx).use { callbackHandler ->
|
||||||
val negated = privkey.copyOf()
|
memScoped {
|
||||||
val negPriv = toNat(negated)
|
val negated = privkey.copyOf()
|
||||||
secp256k1_ec_seckey_negate(ctx, negPriv).requireSuccess("secp256k1_ec_seckey_negate() failed")
|
val negPriv = toNat(negated)
|
||||||
return negated
|
secp256k1_ec_seckey_negate(ctx, negPriv).requireSuccess(callbackHandler, "secp256k1_ec_seckey_negate() failed")
|
||||||
|
return negated
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override 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 {
|
CallbackHandler(ctx).use { callbackHandler ->
|
||||||
val added = privkey.copyOf()
|
memScoped {
|
||||||
val natAdd = toNat(added)
|
val added = privkey.copyOf()
|
||||||
val natTweak = toNat(tweak)
|
val natAdd = toNat(added)
|
||||||
secp256k1_ec_seckey_tweak_add(ctx, natAdd, natTweak).requireSuccess("secp256k1_ec_seckey_tweak_add() failed")
|
val natTweak = toNat(tweak)
|
||||||
return added
|
secp256k1_ec_seckey_tweak_add(ctx, natAdd, natTweak).requireSuccess(callbackHandler, "secp256k1_ec_seckey_tweak_add() failed")
|
||||||
|
return added
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override 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 {
|
CallbackHandler(ctx).use { callbackHandler ->
|
||||||
val multiplied = privkey.copyOf()
|
memScoped {
|
||||||
val natMul = toNat(multiplied)
|
val multiplied = privkey.copyOf()
|
||||||
val natTweak = toNat(tweak)
|
val natMul = toNat(multiplied)
|
||||||
secp256k1_ec_privkey_tweak_mul(ctx, natMul, natTweak).requireSuccess("secp256k1_ec_privkey_tweak_mul() failed")
|
val natTweak = toNat(tweak)
|
||||||
return multiplied
|
secp256k1_ec_privkey_tweak_mul(ctx, natMul, natTweak).requireSuccess(callbackHandler, "secp256k1_ec_privkey_tweak_mul() failed")
|
||||||
|
return multiplied
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override 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 {
|
CallbackHandler(ctx).use { callbackHandler ->
|
||||||
val nPubkey = allocPublicKey(pubkey)
|
memScoped {
|
||||||
secp256k1_ec_pubkey_negate(ctx, nPubkey.ptr).requireSuccess("secp256k1_ec_pubkey_negate() failed")
|
val nPubkey = allocPublicKey(pubkey)
|
||||||
return serializePubkey(nPubkey)
|
secp256k1_ec_pubkey_negate(ctx, nPubkey.ptr).requireSuccess(callbackHandler, "secp256k1_ec_pubkey_negate() failed")
|
||||||
|
return serializePubkey(nPubkey)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override 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 {
|
CallbackHandler(ctx).use { callbackHandler ->
|
||||||
val nPubkey = allocPublicKey(pubkey)
|
memScoped {
|
||||||
val nTweak = toNat(tweak)
|
val nPubkey = allocPublicKey(pubkey)
|
||||||
secp256k1_ec_pubkey_tweak_add(ctx, nPubkey.ptr, nTweak).requireSuccess("secp256k1_ec_pubkey_tweak_add() failed")
|
val nTweak = toNat(tweak)
|
||||||
return serializePubkey(nPubkey)
|
secp256k1_ec_pubkey_tweak_add(ctx, nPubkey.ptr, nTweak).requireSuccess(callbackHandler, "secp256k1_ec_pubkey_tweak_add() failed")
|
||||||
|
return serializePubkey(nPubkey)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override 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 {
|
CallbackHandler(ctx).use { callbackHandler ->
|
||||||
val nPubkey = allocPublicKey(pubkey)
|
memScoped {
|
||||||
val nTweak = toNat(tweak)
|
val nPubkey = allocPublicKey(pubkey)
|
||||||
secp256k1_ec_pubkey_tweak_mul(ctx, nPubkey.ptr, nTweak).requireSuccess("secp256k1_ec_pubkey_tweak_mul() failed")
|
val nTweak = toNat(tweak)
|
||||||
return serializePubkey(nPubkey)
|
secp256k1_ec_pubkey_tweak_mul(ctx, nPubkey.ptr, nTweak).requireSuccess(callbackHandler, "secp256k1_ec_pubkey_tweak_mul() failed")
|
||||||
|
return serializePubkey(nPubkey)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override fun pubKeyCombine(pubkeys: Array<ByteArray>): ByteArray {
|
public override fun pubKeyCombine(pubkeys: Array<ByteArray>): ByteArray {
|
||||||
pubkeys.forEach { require(it.size == 33 || it.size == 65) }
|
pubkeys.forEach { require(it.size == 33 || it.size == 65) }
|
||||||
memScoped {
|
CallbackHandler(ctx).use { callbackHandler ->
|
||||||
val nPubkeys = pubkeys.map { allocPublicKey(it).ptr }
|
memScoped {
|
||||||
val combined = alloc<secp256k1_pubkey>()
|
val nPubkeys = pubkeys.map { allocPublicKey(it).ptr }
|
||||||
secp256k1_ec_pubkey_combine(ctx, combined.ptr, nPubkeys.toCValues(), pubkeys.size.convert()).requireSuccess("secp256k1_ec_pubkey_combine() failed")
|
val combined = alloc<secp256k1_pubkey>()
|
||||||
return serializePubkey(combined)
|
secp256k1_ec_pubkey_combine(ctx, combined.ptr, nPubkeys.toCValues(), pubkeys.size.convert()).requireSuccess(callbackHandler, "secp256k1_ec_pubkey_combine() failed")
|
||||||
|
return serializePubkey(combined)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override fun ecdh(privkey: ByteArray, pubkey: ByteArray): ByteArray {
|
public override fun ecdh(privkey: ByteArray, pubkey: ByteArray): ByteArray {
|
||||||
require(privkey.size == 32)
|
require(privkey.size == 32)
|
||||||
require(pubkey.size == 33 || pubkey.size == 65)
|
require(pubkey.size == 33 || pubkey.size == 65)
|
||||||
memScoped {
|
CallbackHandler(ctx).use { callbackHandler ->
|
||||||
val nPubkey = allocPublicKey(pubkey)
|
memScoped {
|
||||||
val nPrivkey = toNat(privkey)
|
val nPubkey = allocPublicKey(pubkey)
|
||||||
val output = allocArray<UByteVar>(32)
|
val nPrivkey = toNat(privkey)
|
||||||
secp256k1_ecdh(ctx, output, nPubkey.ptr, nPrivkey, null, null).requireSuccess("secp256k1_ecdh() failed")
|
val output = allocArray<UByteVar>(32)
|
||||||
return output.readBytes(32)
|
secp256k1_ecdh(ctx, output, nPubkey.ptr, nPrivkey, null, null).requireSuccess(callbackHandler, "secp256k1_ecdh() failed")
|
||||||
|
return output.readBytes(32)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override fun ecdsaRecover(sig: ByteArray, message: ByteArray, recid: Int): ByteArray {
|
public override fun ecdsaRecover(sig: ByteArray, message: ByteArray, recid: Int): ByteArray {
|
||||||
require(sig.size == 64)
|
require(sig.size == 64)
|
||||||
require(message.size == 32)
|
require(message.size == 32)
|
||||||
memScoped {
|
// we do not check that recid is valid, which should trigger our illegal callback handler to throw a Secp256k1IllegalCallbackException
|
||||||
val nSig = toNat(sig)
|
// require(recid in 0..3)
|
||||||
val rSig = alloc<secp256k1_ecdsa_recoverable_signature>()
|
|
||||||
secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, rSig.ptr, nSig, recid).requireSuccess("secp256k1_ecdsa_recoverable_signature_parse_compact() failed")
|
CallbackHandler(ctx).use { callbackHandler ->
|
||||||
val nMessage = toNat(message)
|
memScoped {
|
||||||
val pubkey = alloc<secp256k1_pubkey>()
|
val nSig = toNat(sig)
|
||||||
secp256k1_ecdsa_recover(ctx, pubkey.ptr, rSig.ptr, nMessage).requireSuccess("secp256k1_ecdsa_recover() failed")
|
val rSig = alloc<secp256k1_ecdsa_recoverable_signature>()
|
||||||
return serializePubkey(pubkey)
|
secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, rSig.ptr, nSig, recid).requireSuccess(callbackHandler, "secp256k1_ecdsa_recoverable_signature_parse_compact() failed")
|
||||||
|
val nMessage = toNat(message)
|
||||||
|
val pubkey = alloc<secp256k1_pubkey>()
|
||||||
|
secp256k1_ecdsa_recover(ctx, pubkey.ptr, rSig.ptr, nMessage).requireSuccess(callbackHandler, "secp256k1_ecdsa_recover() failed")
|
||||||
|
return serializePubkey(pubkey)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override fun compact2der(sig: ByteArray): ByteArray {
|
public override fun compact2der(sig: ByteArray): ByteArray {
|
||||||
require(sig.size == 64)
|
require(sig.size == 64)
|
||||||
memScoped {
|
CallbackHandler(ctx).use { callbackHandler ->
|
||||||
val nSig = allocSignature(sig)
|
memScoped {
|
||||||
val natOutput = allocArray<UByteVar>(73)
|
val nSig = allocSignature(sig)
|
||||||
val len = alloc<size_tVar>()
|
val natOutput = allocArray<UByteVar>(73)
|
||||||
len.value = 73.convert()
|
val len = alloc<size_tVar>()
|
||||||
secp256k1_ecdsa_signature_serialize_der(ctx, natOutput, len.ptr, nSig.ptr).requireSuccess("secp256k1_ecdsa_signature_serialize_der() failed")
|
len.value = 73.convert()
|
||||||
return natOutput.readBytes(len.value.toInt())
|
secp256k1_ecdsa_signature_serialize_der(ctx, natOutput, len.ptr, nSig.ptr).requireSuccess(callbackHandler, "secp256k1_ecdsa_signature_serialize_der() failed")
|
||||||
|
return natOutput.readBytes(len.value.toInt())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -226,13 +320,15 @@ public object Secp256k1Native : Secp256k1 {
|
|||||||
require(signature.size == 64)
|
require(signature.size == 64)
|
||||||
require(data.size == 32)
|
require(data.size == 32)
|
||||||
require(pub.size == 32)
|
require(pub.size == 32)
|
||||||
memScoped {
|
CallbackHandler(ctx).use { callbackHandler ->
|
||||||
val nPub = toNat(pub)
|
memScoped {
|
||||||
val pubkey = alloc<secp256k1_xonly_pubkey>()
|
val nPub = toNat(pub)
|
||||||
secp256k1_xonly_pubkey_parse(ctx, pubkey.ptr, nPub).requireSuccess("secp256k1_xonly_pubkey_parse() failed")
|
val pubkey = alloc<secp256k1_xonly_pubkey>()
|
||||||
val nData = toNat(data)
|
secp256k1_xonly_pubkey_parse(ctx, pubkey.ptr, nPub).requireSuccess(callbackHandler, "secp256k1_xonly_pubkey_parse() failed")
|
||||||
val nSig = toNat(signature)
|
val nData = toNat(data)
|
||||||
return secp256k1_schnorrsig_verify(ctx, nSig, nData, 32, pubkey.ptr) == 1
|
val nSig = toNat(signature)
|
||||||
|
return secp256k1_schnorrsig_verify(ctx, nSig, nData, 32u, pubkey.ptr) == 1
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -240,15 +336,17 @@ public object Secp256k1Native : Secp256k1 {
|
|||||||
require(sec.size == 32)
|
require(sec.size == 32)
|
||||||
require(data.size == 32)
|
require(data.size == 32)
|
||||||
auxrand32?.let { require(it.size == 32) }
|
auxrand32?.let { require(it.size == 32) }
|
||||||
memScoped {
|
CallbackHandler(ctx).use { callbackHandler ->
|
||||||
val nSec = toNat(sec)
|
memScoped {
|
||||||
val nData = toNat(data)
|
val nSec = toNat(sec)
|
||||||
val nAuxrand32 = auxrand32?.let { toNat(it) }
|
val nData = toNat(data)
|
||||||
val nSig = allocArray<UByteVar>(64)
|
val nAuxrand32 = auxrand32?.let { toNat(it) }
|
||||||
val keypair = alloc<secp256k1_keypair>()
|
val nSig = allocArray<UByteVar>(64)
|
||||||
secp256k1_keypair_create(ctx, keypair.ptr, nSec).requireSuccess("secp256k1_keypair_create() failed")
|
val keypair = alloc<secp256k1_keypair>()
|
||||||
secp256k1_schnorrsig_sign32(ctx, nSig, nData, keypair.ptr, nAuxrand32).requireSuccess("secp256k1_ecdsa_sign() failed")
|
secp256k1_keypair_create(ctx, keypair.ptr, nSec).requireSuccess(callbackHandler, "secp256k1_keypair_create() failed")
|
||||||
return nSig.readBytes(64)
|
secp256k1_schnorrsig_sign32(ctx, nSig, nData, keypair.ptr, nAuxrand32).requireSuccess(callbackHandler, "secp256k1_ecdsa_sign() failed")
|
||||||
|
return nSig.readBytes(64)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -275,6 +275,11 @@ class Secp256k1Test {
|
|||||||
val pub0 = Secp256k1.ecdsaRecover(sig, message, 0)
|
val pub0 = Secp256k1.ecdsaRecover(sig, message, 0)
|
||||||
val pub1 = Secp256k1.ecdsaRecover(sig, message, 1)
|
val pub1 = Secp256k1.ecdsaRecover(sig, message, 1)
|
||||||
assertTrue(pub.contentEquals(pub0) || pub.contentEquals(pub1))
|
assertTrue(pub.contentEquals(pub0) || pub.contentEquals(pub1))
|
||||||
|
|
||||||
|
// this is a special case, ecdsaRecover explicitly does not check that recid is valid, which triggers our illegal callback handler
|
||||||
|
assertFailsWith(Secp256k1IllegalCallbackException::class) {
|
||||||
|
Secp256k1.ecdsaRecover(sig, message, 4)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
Loading…
x
Reference in New Issue
Block a user