Add compact2der() method

This commit is contained in:
sstone 2020-07-02 21:39:33 +02:00
parent 244673b04c
commit 08d1692932
7 changed files with 73 additions and 0 deletions

View File

@ -151,6 +151,14 @@ JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256
JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1ecdsa_1recover
(JNIEnv *, jclass, jlong, jbyteArray, jbyteArray, jint);
/*
* Class: fr_acinq_secp256k1_Secp256k1CFunctions
* Method: secp256k1_compact_to_der
* Signature: (J[B)[B
*/
JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1compact_1to_1der
(JNIEnv *, jclass, jlong, jbyteArray);
#ifdef __cplusplus
}
#endif

View File

@ -687,3 +687,38 @@ JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256
CHECKRESULT(!result, "secp256k1_ec_pubkey_serialize failed");
return jpubkey;
}
/*
* Class: fr_acinq_secp256k1_Secp256k1CFunctions
* Method: secp256k1_compact_to_der
* Signature: (J[B)[B
*/
JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1compact_1to_1der
(JNIEnv *penv, jclass clazz, jlong jctx, jbyteArray jsig)
{
secp256k1_context* ctx = (secp256k1_context *)jctx;
jbyte *sig;
secp256k1_ecdsa_signature signature;;
unsigned char der[73];
size_t size;
int result = 0;
if (jctx == 0) return 0;
if (jsig == NULL) return 0;
CHECKRESULT((*penv)->GetArrayLength(penv, jsig) != 64, "invalid signature size");
size = (*penv)->GetArrayLength(penv, jsig);
sig = (*penv)->GetByteArrayElements(penv, jsig, 0);
result = secp256k1_ecdsa_signature_parse_compact(ctx, &signature, (unsigned char*)sig);
(*penv)->ReleaseByteArrayElements(penv, jsig, sig, 0);
CHECKRESULT(!result, "secp256k1_ecdsa_signature_parse_compact failed");
size = 73;
result = secp256k1_ecdsa_signature_serialize_der(ctx, der, &size, &signature);
CHECKRESULT(!result, "secp256k1_ecdsa_signature_serialize_der failed");
jsig = (*penv)->NewByteArray(penv, size);
sig = (*penv)->GetByteArrayElements(penv, jsig, 0);
memcpy(sig, der, size);
(*penv)->ReleaseByteArrayElements(penv, jsig, sig, 0);
return jsig;
}

View File

@ -64,4 +64,6 @@ public class Secp256k1CFunctions {
public static native byte[] secp256k1_ecdh(long ctx, byte[] seckey, byte[] pubkey);
public static native byte[] secp256k1_ecdsa_recover(long ctx, byte[] sig, byte[] msg32, int recid);
public static native byte[] secp256k1_compact_to_der(long ctx, byte[] sig);
}

View File

@ -83,4 +83,8 @@ public object NativeSecp256k1 : Secp256k1 {
override fun ecdsaRecover(sig: ByteArray, message: ByteArray, recid: Int): ByteArray {
return Secp256k1CFunctions.secp256k1_ecdsa_recover(Secp256k1Context.getContext(), sig, message, recid)
}
override fun compact2der(sig: ByteArray): ByteArray {
return Secp256k1CFunctions.secp256k1_compact_to_der(Secp256k1Context.getContext(), sig)
}
}

View File

@ -52,6 +52,8 @@ public interface Secp256k1 {
public fun ecdsaRecover(sig: ByteArray, message: ByteArray, recid: Int): ByteArray
public fun compact2der(sig: ByteArray): ByteArray
public fun pubKeyCompress(pubkey: ByteArray) : ByteArray {
return when {
pubkey.size == 33 && (pubkey[0] == 2.toByte() || pubkey[0] == 3.toByte()) -> pubkey

View File

@ -215,6 +215,18 @@ public object Secp256k1Native : Secp256k1 {
return serializePubkey(pubkey)
}
}
public override fun compact2der(sig: ByteArray): ByteArray {
require(sig.size == 64)
memScoped {
val nSig = allocSignature(sig)
val natOutput = allocArray<UByteVar>(73)
val len = alloc<size_tVar>()
len.value = 73.convert()
secp256k1_ecdsa_signature_serialize_der(ctx, natOutput, len.ptr, nSig.ptr).requireSuccess("secp256k1_ecdsa_signature_serialize_der() failed")
return natOutput.readBytes(len.value.toInt())
}
}
}
internal actual fun getSecpk256k1(): Secp256k1 = Secp256k1Native

View File

@ -255,4 +255,14 @@ class Secp256k1Test {
val pub1: ByteArray = Secp256k1.ecdsaRecover(sig, data, 1)
assertTrue(pub.contentEquals(pub0) || pub.contentEquals(pub1), "testEcdsaRecover")
}
@Test
fun testCompactToDER() {
val sig: ByteArray = Hex.decode("182A108E1448DC8F1FB467D06A0F3BB8EA0533584CB954EF8DA112F1D60E39A21C66F36DA211C087F3AF88B50EDF4F9BDAA6CF5FD6817E74DCA34DB12390C6E9".toLowerCase()) //sha256hash of "testing"
val der: ByteArray = Secp256k1.compact2der(sig)
assertEquals(
"30440220182A108E1448DC8F1FB467D06A0F3BB8EA0533584CB954EF8DA112F1D60E39A202201C66F36DA211C087F3AF88B50EDF4F9BDAA6CF5FD6817E74DCA34DB12390C6E9",
Hex.encode(der).toUpperCase(),
)
}
}