Upgrade JNI interface (#1)
* Upgrade JNI interface * Input signatures can be DER or compact format, output signatures are always in compact format * Input public keys can be compressed or uncompressed, output public keys are always uncompressed * Name and parameters match libsecp256k1's * JNI implementation is now straightforward No more ByteBuffers Exceptions are thrown in case of failures * Update src/nativeMain/kotlin/fr/acinq/secp256k1/Secp256k1Native.kt * Add public key compression method Co-authored-by: Salomon BRYS <salomon.brys@gmail.com>
This commit is contained in:
parent
17dd83e476
commit
3ee2635d93
@ -1,7 +1,7 @@
|
||||
cmake_minimum_required(VERSION 3.10.0)
|
||||
|
||||
add_library( secp256k1-jni SHARED
|
||||
${CMAKE_CURRENT_LIST_DIR}/../../../c/src/org_bitcoin_Secp256k1CFunctions.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/../../../c/src/fr_acinq_secp256k1_Secp256k1CFunctions.c
|
||||
)
|
||||
|
||||
target_include_directories( secp256k1-jni
|
||||
|
@ -1,7 +1,7 @@
|
||||
package fr.acinq.secp256k1.jni
|
||||
|
||||
import fr.acinq.secp256k1.Secp256k1
|
||||
import org.bitcoin.NativeSecp256k1
|
||||
import fr.acinq.secp256k1.NativeSecp256k1
|
||||
|
||||
public object NativeSecp256k1Loader {
|
||||
|
||||
|
@ -29,7 +29,7 @@ fi
|
||||
|
||||
mkdir -p build/jni/$TARGET
|
||||
|
||||
$CC -shared $CC_OPTS -o build/jni/$TARGET/$OUTFILE c/src/org_bitcoin_Secp256k1CFunctions.c -Ic/headers/ -Ic/headers/java -Ic/headers/$JNI_HEADERS/ -I../native/secp256k1/ -lsecp256k1 -L../native/build/$TARGET/ $ADD_LIB
|
||||
$CC -shared $CC_OPTS -o build/jni/$TARGET/$OUTFILE c/src/fr_acinq_secp256k1_Secp256k1CFunctions.c -Ic/headers/ -Ic/headers/java -Ic/headers/$JNI_HEADERS/ -I../native/secp256k1/ -lsecp256k1 -L../native/build/$TARGET/ $ADD_LIB
|
||||
|
||||
[[ ! -z "$TO_UID" ]] && chown -R $TO_UID:$TO_UID .
|
||||
|
||||
|
157
jni/c/headers/java/fr_acinq_secp256k1_Secp256k1CFunctions.h
Normal file
157
jni/c/headers/java/fr_acinq_secp256k1_Secp256k1CFunctions.h
Normal file
@ -0,0 +1,157 @@
|
||||
/* DO NOT EDIT THIS FILE - it is machine generated */
|
||||
#include <jni.h>
|
||||
/* Header for class fr_acinq_secp256k1_Secp256k1CFunctions */
|
||||
|
||||
#ifndef _Included_fr_acinq_secp256k1_Secp256k1CFunctions
|
||||
#define _Included_fr_acinq_secp256k1_Secp256k1CFunctions
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
/*
|
||||
* Class: fr_acinq_secp256k1_Secp256k1CFunctions
|
||||
* Method: secp256k1_context_create
|
||||
* Signature: (I)J
|
||||
*/
|
||||
JNIEXPORT jlong JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1context_1create
|
||||
(JNIEnv *, jclass, jint);
|
||||
|
||||
/*
|
||||
* Class: fr_acinq_secp256k1_Secp256k1CFunctions
|
||||
* Method: secp256k1_context_destroy
|
||||
* Signature: (J)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1context_1destroy
|
||||
(JNIEnv *, jclass, jlong);
|
||||
|
||||
/*
|
||||
* Class: fr_acinq_secp256k1_Secp256k1CFunctions
|
||||
* Method: secp256k1_ec_seckey_verify
|
||||
* Signature: (J[B)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1ec_1seckey_1verify
|
||||
(JNIEnv *, jclass, jlong, jbyteArray);
|
||||
|
||||
/*
|
||||
* Class: fr_acinq_secp256k1_Secp256k1CFunctions
|
||||
* Method: secp256k1_ec_pubkey_parse
|
||||
* Signature: (J[B)[B
|
||||
*/
|
||||
JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1ec_1pubkey_1parse
|
||||
(JNIEnv *, jclass, jlong, jbyteArray);
|
||||
|
||||
/*
|
||||
* Class: fr_acinq_secp256k1_Secp256k1CFunctions
|
||||
* Method: secp256k1_ec_pubkey_create
|
||||
* Signature: (J[B)[B
|
||||
*/
|
||||
JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1ec_1pubkey_1create
|
||||
(JNIEnv *, jclass, jlong, jbyteArray);
|
||||
|
||||
/*
|
||||
* Class: fr_acinq_secp256k1_Secp256k1CFunctions
|
||||
* Method: secp256k1_ecdsa_sign
|
||||
* Signature: (J[B[B)[B
|
||||
*/
|
||||
JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1ecdsa_1sign
|
||||
(JNIEnv *, jclass, jlong, jbyteArray, jbyteArray);
|
||||
|
||||
/*
|
||||
* Class: fr_acinq_secp256k1_Secp256k1CFunctions
|
||||
* Method: secp256k1_ecdsa_verify
|
||||
* Signature: (J[B[B[B)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1ecdsa_1verify
|
||||
(JNIEnv *, jclass, jlong, jbyteArray, jbyteArray, jbyteArray);
|
||||
|
||||
/*
|
||||
* Class: fr_acinq_secp256k1_Secp256k1CFunctions
|
||||
* Method: secp256k1_ecdsa_signature_normalize
|
||||
* Signature: (J[B[B)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1ecdsa_1signature_1normalize
|
||||
(JNIEnv *, jclass, jlong, jbyteArray, jbyteArray);
|
||||
|
||||
/*
|
||||
* Class: fr_acinq_secp256k1_Secp256k1CFunctions
|
||||
* Method: secp256k1_ec_privkey_negate
|
||||
* Signature: (J[B)[B
|
||||
*/
|
||||
JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1ec_1privkey_1negate
|
||||
(JNIEnv *, jclass, jlong, jbyteArray);
|
||||
|
||||
/*
|
||||
* Class: fr_acinq_secp256k1_Secp256k1CFunctions
|
||||
* Method: secp256k1_ec_pubkey_negate
|
||||
* Signature: (J[B)[B
|
||||
*/
|
||||
JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1ec_1pubkey_1negate
|
||||
(JNIEnv *, jclass, jlong, jbyteArray);
|
||||
|
||||
/*
|
||||
* Class: fr_acinq_secp256k1_Secp256k1CFunctions
|
||||
* Method: secp256k1_ec_privkey_tweak_add
|
||||
* Signature: (J[B[B)[B
|
||||
*/
|
||||
JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1ec_1privkey_1tweak_1add
|
||||
(JNIEnv *, jclass, jlong, jbyteArray, jbyteArray);
|
||||
|
||||
/*
|
||||
* Class: fr_acinq_secp256k1_Secp256k1CFunctions
|
||||
* Method: secp256k1_ec_pubkey_tweak_add
|
||||
* Signature: (J[B[B)[B
|
||||
*/
|
||||
JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1ec_1pubkey_1tweak_1add
|
||||
(JNIEnv *, jclass, jlong, jbyteArray, jbyteArray);
|
||||
|
||||
/*
|
||||
* Class: fr_acinq_secp256k1_Secp256k1CFunctions
|
||||
* Method: secp256k1_ec_privkey_tweak_mul
|
||||
* Signature: (J[B[B)[B
|
||||
*/
|
||||
JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1ec_1privkey_1tweak_1mul
|
||||
(JNIEnv *, jclass, jlong, jbyteArray, jbyteArray);
|
||||
|
||||
/*
|
||||
* Class: fr_acinq_secp256k1_Secp256k1CFunctions
|
||||
* Method: secp256k1_ec_pubkey_tweak_mul
|
||||
* Signature: (J[B[B)[B
|
||||
*/
|
||||
JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1ec_1pubkey_1tweak_1mul
|
||||
(JNIEnv *, jclass, jlong, jbyteArray, jbyteArray);
|
||||
|
||||
/*
|
||||
* Class: fr_acinq_secp256k1_Secp256k1CFunctions
|
||||
* Method: secp256k1_ec_pubkey_add
|
||||
* Signature: (J[B[B)[B
|
||||
*/
|
||||
JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1ec_1pubkey_1add
|
||||
(JNIEnv *, jclass, jlong, jbyteArray, jbyteArray);
|
||||
|
||||
/*
|
||||
* Class: fr_acinq_secp256k1_Secp256k1CFunctions
|
||||
* Method: secp256k1_ec_pubkey_combine
|
||||
* Signature: (J[[B)[B
|
||||
*/
|
||||
JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1ec_1pubkey_1combine
|
||||
(JNIEnv *, jclass, jlong, jobjectArray);
|
||||
|
||||
/*
|
||||
* Class: fr_acinq_secp256k1_Secp256k1CFunctions
|
||||
* Method: secp256k1_ecdh
|
||||
* Signature: (J[B[B)[B
|
||||
*/
|
||||
JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1ecdh
|
||||
(JNIEnv *, jclass, jlong, jbyteArray, jbyteArray);
|
||||
|
||||
/*
|
||||
* Class: fr_acinq_secp256k1_Secp256k1CFunctions
|
||||
* Method: secp256k1_ecdsa_recover
|
||||
* Signature: (J[B[BI)[B
|
||||
*/
|
||||
JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1ecdsa_1recover
|
||||
(JNIEnv *, jclass, jlong, jbyteArray, jbyteArray, jint);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
@ -1,157 +0,0 @@
|
||||
/* DO NOT EDIT THIS FILE - it is machine generated */
|
||||
#include <jni.h>
|
||||
/* Header for class org_bitcoin_Secp256k1CFunctions */
|
||||
|
||||
#ifndef _Included_org_bitcoin_Secp256k1CFunctions
|
||||
#define _Included_org_bitcoin_Secp256k1CFunctions
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
/*
|
||||
* Class: org_bitcoin_Secp256k1CFunctions
|
||||
* Method: secp256k1_init_context
|
||||
* Signature: ()J
|
||||
*/
|
||||
JNIEXPORT jlong JNICALL Java_org_bitcoin_Secp256k1CFunctions_secp256k1_1init_1context
|
||||
(JNIEnv *, jclass);
|
||||
|
||||
/*
|
||||
* Class: org_bitcoin_Secp256k1CFunctions
|
||||
* Method: secp256k1_context_randomize
|
||||
* Signature: (Ljava/nio/ByteBuffer;J)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL Java_org_bitcoin_Secp256k1CFunctions_secp256k1_1context_1randomize
|
||||
(JNIEnv *, jclass, jobject, jlong);
|
||||
|
||||
/*
|
||||
* Class: org_bitcoin_Secp256k1CFunctions
|
||||
* Method: secp256k1_privkey_negate
|
||||
* Signature: (Ljava/nio/ByteBuffer;J)[[B
|
||||
*/
|
||||
JNIEXPORT jobjectArray JNICALL Java_org_bitcoin_Secp256k1CFunctions_secp256k1_1privkey_1negate
|
||||
(JNIEnv *, jclass, jobject, jlong);
|
||||
|
||||
/*
|
||||
* Class: org_bitcoin_Secp256k1CFunctions
|
||||
* Method: secp256k1_privkey_tweak_add
|
||||
* Signature: (Ljava/nio/ByteBuffer;J)[[B
|
||||
*/
|
||||
JNIEXPORT jobjectArray JNICALL Java_org_bitcoin_Secp256k1CFunctions_secp256k1_1privkey_1tweak_1add
|
||||
(JNIEnv *, jclass, jobject, jlong);
|
||||
|
||||
/*
|
||||
* Class: org_bitcoin_Secp256k1CFunctions
|
||||
* Method: secp256k1_privkey_tweak_mul
|
||||
* Signature: (Ljava/nio/ByteBuffer;J)[[B
|
||||
*/
|
||||
JNIEXPORT jobjectArray JNICALL Java_org_bitcoin_Secp256k1CFunctions_secp256k1_1privkey_1tweak_1mul
|
||||
(JNIEnv *, jclass, jobject, jlong);
|
||||
|
||||
/*
|
||||
* Class: org_bitcoin_Secp256k1CFunctions
|
||||
* Method: secp256k1_pubkey_negate
|
||||
* Signature: (Ljava/nio/ByteBuffer;JI)[[B
|
||||
*/
|
||||
JNIEXPORT jobjectArray JNICALL Java_org_bitcoin_Secp256k1CFunctions_secp256k1_1pubkey_1negate
|
||||
(JNIEnv *, jclass, jobject, jlong, jint);
|
||||
|
||||
/*
|
||||
* Class: org_bitcoin_Secp256k1CFunctions
|
||||
* Method: secp256k1_pubkey_tweak_add
|
||||
* Signature: (Ljava/nio/ByteBuffer;JI)[[B
|
||||
*/
|
||||
JNIEXPORT jobjectArray JNICALL Java_org_bitcoin_Secp256k1CFunctions_secp256k1_1pubkey_1tweak_1add
|
||||
(JNIEnv *, jclass, jobject, jlong, jint);
|
||||
|
||||
/*
|
||||
* Class: org_bitcoin_Secp256k1CFunctions
|
||||
* Method: secp256k1_pubkey_tweak_mul
|
||||
* Signature: (Ljava/nio/ByteBuffer;JI)[[B
|
||||
*/
|
||||
JNIEXPORT jobjectArray JNICALL Java_org_bitcoin_Secp256k1CFunctions_secp256k1_1pubkey_1tweak_1mul
|
||||
(JNIEnv *, jclass, jobject, jlong, jint);
|
||||
|
||||
/*
|
||||
* Class: org_bitcoin_Secp256k1CFunctions
|
||||
* Method: secp256k1_destroy_context
|
||||
* Signature: (J)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_org_bitcoin_Secp256k1CFunctions_secp256k1_1destroy_1context
|
||||
(JNIEnv *, jclass, jlong);
|
||||
|
||||
/*
|
||||
* Class: org_bitcoin_Secp256k1CFunctions
|
||||
* Method: secp256k1_ecdsa_verify
|
||||
* Signature: (Ljava/nio/ByteBuffer;JII)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL Java_org_bitcoin_Secp256k1CFunctions_secp256k1_1ecdsa_1verify
|
||||
(JNIEnv *, jclass, jobject, jlong, jint, jint);
|
||||
|
||||
/*
|
||||
* Class: org_bitcoin_Secp256k1CFunctions
|
||||
* Method: secp256k1_ecdsa_sign
|
||||
* Signature: (Ljava/nio/ByteBuffer;ZJ)[[B
|
||||
*/
|
||||
JNIEXPORT jobjectArray JNICALL Java_org_bitcoin_Secp256k1CFunctions_secp256k1_1ecdsa_1sign
|
||||
(JNIEnv *, jclass, jobject, jboolean, jlong);
|
||||
|
||||
/*
|
||||
* Class: org_bitcoin_Secp256k1CFunctions
|
||||
* Method: secp256k1_ecdsa_normalize
|
||||
* Signature: (Ljava/nio/ByteBuffer;IZJ)[[B
|
||||
*/
|
||||
JNIEXPORT jobjectArray JNICALL Java_org_bitcoin_Secp256k1CFunctions_secp256k1_1ecdsa_1normalize
|
||||
(JNIEnv *, jclass, jobject, jint, jboolean, jlong);
|
||||
|
||||
/*
|
||||
* Class: org_bitcoin_Secp256k1CFunctions
|
||||
* Method: secp256k1_ec_seckey_verify
|
||||
* Signature: (Ljava/nio/ByteBuffer;J)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL Java_org_bitcoin_Secp256k1CFunctions_secp256k1_1ec_1seckey_1verify
|
||||
(JNIEnv *, jclass, jobject, jlong);
|
||||
|
||||
/*
|
||||
* Class: org_bitcoin_Secp256k1CFunctions
|
||||
* Method: secp256k1_ec_pubkey_create
|
||||
* Signature: (Ljava/nio/ByteBuffer;ZJ)[[B
|
||||
*/
|
||||
JNIEXPORT jobjectArray JNICALL Java_org_bitcoin_Secp256k1CFunctions_secp256k1_1ec_1pubkey_1create
|
||||
(JNIEnv *, jclass, jobject, jboolean, jlong);
|
||||
|
||||
/*
|
||||
* Class: org_bitcoin_Secp256k1CFunctions
|
||||
* Method: secp256k1_ec_pubkey_parse
|
||||
* Signature: (Ljava/nio/ByteBuffer;JIZ)[[B
|
||||
*/
|
||||
JNIEXPORT jobjectArray JNICALL Java_org_bitcoin_Secp256k1CFunctions_secp256k1_1ec_1pubkey_1parse
|
||||
(JNIEnv *, jclass, jobject, jlong, jint, jboolean);
|
||||
|
||||
/*
|
||||
* Class: org_bitcoin_Secp256k1CFunctions
|
||||
* Method: secp256k1_ec_pubkey_add
|
||||
* Signature: (Ljava/nio/ByteBuffer;JII)[[B
|
||||
*/
|
||||
JNIEXPORT jobjectArray JNICALL Java_org_bitcoin_Secp256k1CFunctions_secp256k1_1ec_1pubkey_1add
|
||||
(JNIEnv *, jclass, jobject, jlong, jint, jint);
|
||||
|
||||
/*
|
||||
* Class: org_bitcoin_Secp256k1CFunctions
|
||||
* Method: secp256k1_ecdh
|
||||
* Signature: (Ljava/nio/ByteBuffer;JI)[[B
|
||||
*/
|
||||
JNIEXPORT jobjectArray JNICALL Java_org_bitcoin_Secp256k1CFunctions_secp256k1_1ecdh
|
||||
(JNIEnv *, jclass, jobject, jlong, jint);
|
||||
|
||||
/*
|
||||
* Class: org_bitcoin_Secp256k1CFunctions
|
||||
* Method: secp256k1_ecdsa_recover
|
||||
* Signature: (Ljava/nio/ByteBuffer;JIZ)[[B
|
||||
*/
|
||||
JNIEXPORT jobjectArray JNICALL Java_org_bitcoin_Secp256k1CFunctions_secp256k1_1ecdsa_1recover
|
||||
(JNIEnv *, jclass, jobject, jlong, jint, jboolean);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
689
jni/c/src/fr_acinq_secp256k1_Secp256k1CFunctions.c
Normal file
689
jni/c/src/fr_acinq_secp256k1_Secp256k1CFunctions.c
Normal file
@ -0,0 +1,689 @@
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "include/secp256k1.h"
|
||||
#include "include/secp256k1_ecdh.h"
|
||||
#include "include/secp256k1_recovery.h"
|
||||
#include "fr_acinq_secp256k1_Secp256k1CFunctions.h"
|
||||
|
||||
#define SIG_FORMAT_UNKNOWN 0
|
||||
#define SIG_FORMAT_COMPACT 1
|
||||
#define SIG_FORMAT_DER 2
|
||||
|
||||
void JNI_ThrowByName(JNIEnv *penv, const char* name, const char* msg)
|
||||
{
|
||||
jclass cls = (*penv)->FindClass(penv, name);
|
||||
if (cls != NULL) {
|
||||
(*penv)->ThrowNew(penv, cls, msg);
|
||||
(*penv)->DeleteLocalRef(penv, cls);
|
||||
}
|
||||
}
|
||||
|
||||
#define CHECKRESULT(errorcheck, message) { \
|
||||
if (errorcheck) { \
|
||||
JNI_ThrowByName(penv, "fr/acinq/secp256k1/Secp256k1Exception", message); \
|
||||
return 0; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define CHECKRESULT1(errorcheck, message, dosomething) { \
|
||||
if (errorcheck) { \
|
||||
dosomething; \
|
||||
JNI_ThrowByName(penv, "fr/acinq/secp256k1/Secp256k1Exception", message); \
|
||||
return 0; \
|
||||
} \
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: fr_acinq_bitcoin_Secp256k1Bindings
|
||||
* Method: secp256k1_context_create
|
||||
* Signature: (I)J
|
||||
*/
|
||||
JNIEXPORT jlong JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1context_1create
|
||||
(JNIEnv *penv, jclass clazz, jint flags)
|
||||
{
|
||||
return (jlong) secp256k1_context_create(flags);
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: fr_acinq_bitcoin_Secp256k1Bindings
|
||||
* Method: secp256k1_context_destroy
|
||||
* Signature: (J)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1context_1destroy
|
||||
(JNIEnv *penv, jclass clazz, jlong ctx)
|
||||
{
|
||||
if (ctx != 0) {
|
||||
secp256k1_context_destroy((secp256k1_context*)ctx);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: fr_acinq_secp256k1_Secp256k1CFunctions
|
||||
* Method: secp256k1_ec_seckey_verify
|
||||
* Signature: (J[B)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1ec_1seckey_1verify
|
||||
(JNIEnv *penv, jclass clazz, jlong jctx, jbyteArray jseckey)
|
||||
{
|
||||
secp256k1_context* ctx = (secp256k1_context *)jctx;
|
||||
jbyte *seckey;
|
||||
int result = 0;
|
||||
|
||||
if (jctx == 0) return 0;
|
||||
if (jseckey == NULL) return 0;
|
||||
CHECKRESULT((*penv)->GetArrayLength(penv, jseckey) != 32, "secret key must be 32 bytes");
|
||||
seckey = (*penv)->GetByteArrayElements(penv, jseckey, 0);
|
||||
result = secp256k1_ec_seckey_verify(ctx, (unsigned char*)seckey);
|
||||
(*penv)->ReleaseByteArrayElements(penv, jseckey, seckey, 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: fr_acinq_bitcoin_Secp256k1Bindings
|
||||
* Method: secp256k1_ec_pubkey_parse
|
||||
* Signature: (J[B)[B
|
||||
*/
|
||||
JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1ec_1pubkey_1parse
|
||||
(JNIEnv *penv, jclass clazz, jlong jctx, jbyteArray jpubkey)
|
||||
{
|
||||
secp256k1_context* ctx = (secp256k1_context *)jctx;
|
||||
jbyte *pubkeyBytes;
|
||||
secp256k1_pubkey pubkey;
|
||||
size_t size;
|
||||
int result = 0;
|
||||
|
||||
if (jctx == 0) return 0;
|
||||
if (jpubkey == NULL) return 0;
|
||||
|
||||
size = (*penv)->GetArrayLength(penv, jpubkey);
|
||||
CHECKRESULT((size != 33) && (size != 65), "invalid public key size");
|
||||
|
||||
pubkeyBytes = (*penv)->GetByteArrayElements(penv, jpubkey, 0);
|
||||
result = secp256k1_ec_pubkey_parse(ctx, &pubkey, (unsigned char*) pubkeyBytes, size);
|
||||
(*penv)->ReleaseByteArrayElements(penv, jpubkey, pubkeyBytes, 0);
|
||||
CHECKRESULT(!result, "secp256k1_ec_pubkey_parse failed");
|
||||
|
||||
size = 65;
|
||||
jpubkey = (*penv)->NewByteArray(penv, 65);
|
||||
pubkeyBytes = (*penv)->GetByteArrayElements(penv, jpubkey, 0);
|
||||
result = secp256k1_ec_pubkey_serialize(ctx, (unsigned char*) pubkeyBytes, &size, &pubkey, SECP256K1_EC_UNCOMPRESSED);
|
||||
(*penv)->ReleaseByteArrayElements(penv, jpubkey, pubkeyBytes, 0);
|
||||
CHECKRESULT(!result, "secp256k1_ec_pubkey_serialize failed");
|
||||
return jpubkey;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: fr_acinq_bitcoin_Secp256k1Bindings
|
||||
* Method: secp256k1_ec_pubkey_create
|
||||
* Signature: (J[B)[B
|
||||
*/
|
||||
JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1ec_1pubkey_1create
|
||||
(JNIEnv *penv, jclass clazz, jlong jctx, jbyteArray jseckey)
|
||||
{
|
||||
secp256k1_context* ctx = (secp256k1_context *)jctx;
|
||||
jbyte *seckey, *pubkey;
|
||||
secp256k1_pubkey pub;
|
||||
int result = 0;
|
||||
size_t len;
|
||||
jbyteArray jpubkey = 0;
|
||||
|
||||
if (jseckey == NULL) return NULL;
|
||||
if (jctx == 0) return NULL;
|
||||
|
||||
CHECKRESULT((*penv)->GetArrayLength(penv, jseckey) != 32, "secret key must be 32 bytes");
|
||||
seckey = (*penv)->GetByteArrayElements(penv, jseckey, 0);
|
||||
jpubkey = (*penv)->NewByteArray(penv, 65);
|
||||
pubkey = (*penv)->GetByteArrayElements(penv, jpubkey, 0);
|
||||
result = secp256k1_ec_pubkey_create(ctx, &pub, (unsigned char*)seckey);
|
||||
(*penv)->ReleaseByteArrayElements(penv, jseckey, seckey, 0);
|
||||
(*penv)->ReleaseByteArrayElements(penv, jpubkey, pubkey, 0);
|
||||
CHECKRESULT(!result, "secp256k1_ec_pubkey_create failed");
|
||||
jpubkey = (*penv)->NewByteArray(penv, 65);
|
||||
pubkey = (*penv)->GetByteArrayElements(penv, jpubkey, 0);
|
||||
len = 65;
|
||||
result = secp256k1_ec_pubkey_serialize(ctx, (unsigned char*)pubkey, &len, &pub, SECP256K1_EC_UNCOMPRESSED);
|
||||
(*penv)->ReleaseByteArrayElements(penv, jpubkey, pubkey, 0);
|
||||
CHECKRESULT(!result, "secp256k1_ec_pubkey_serialize failed");
|
||||
return jpubkey;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: fr_acinq_bitcoin_Secp256k1Bindings
|
||||
* Method: secp256k1_ecdsa_sign
|
||||
* Signature: (J[B[B)[B
|
||||
*/
|
||||
JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1ecdsa_1sign
|
||||
(JNIEnv *penv, jclass clazz, jlong jctx, jbyteArray jmsg, jbyteArray jseckey)
|
||||
{
|
||||
secp256k1_context* ctx = (secp256k1_context *)jctx;
|
||||
jbyte *seckey, *msg, *sig;
|
||||
secp256k1_ecdsa_signature signature;
|
||||
int result = 0;
|
||||
jbyteArray jsig;
|
||||
|
||||
if (jctx == 0) return NULL;
|
||||
if (jmsg == NULL) return NULL;
|
||||
if (jseckey == NULL) return NULL;
|
||||
|
||||
CHECKRESULT((*penv)->GetArrayLength(penv, jseckey) != 32, "secret key must be 32 bytes");
|
||||
CHECKRESULT((*penv)->GetArrayLength(penv, jmsg) != 32, "message key must be 32 bytes");
|
||||
seckey = (*penv)->GetByteArrayElements(penv, jseckey, 0);
|
||||
msg = (*penv)->GetByteArrayElements(penv, jmsg, 0);
|
||||
|
||||
result = secp256k1_ecdsa_sign(ctx, &signature, (unsigned char*)msg, (unsigned char*)seckey, NULL, NULL);
|
||||
(*penv)->ReleaseByteArrayElements(penv, jseckey, seckey, 0);
|
||||
(*penv)->ReleaseByteArrayElements(penv, jmsg, msg, 0);
|
||||
CHECKRESULT(!result, "secp256k1_ecdsa_sign failed");
|
||||
|
||||
jsig = (*penv)->NewByteArray(penv, 64);
|
||||
sig = (*penv)->GetByteArrayElements(penv, jsig, 0);
|
||||
result = secp256k1_ecdsa_signature_serialize_compact(ctx, (unsigned char*)sig, &signature);
|
||||
(*penv)->ReleaseByteArrayElements(penv, jsig, sig, 0);
|
||||
CHECKRESULT(!result, "secp256k1_ecdsa_signature_serialize_compact failed");
|
||||
return jsig;
|
||||
}
|
||||
|
||||
int GetSignatureFormat(size_t size)
|
||||
{
|
||||
switch(size) {
|
||||
case 64:
|
||||
return SIG_FORMAT_COMPACT;
|
||||
break;
|
||||
case 70:
|
||||
case 71:
|
||||
case 72:
|
||||
case 73:
|
||||
return SIG_FORMAT_DER;
|
||||
break;
|
||||
default: return SIG_FORMAT_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: fr_acinq_bitcoin_Secp256k1Bindings
|
||||
* Method: secp256k1_ecdsa_verify
|
||||
* Signature: (J[B[B[B)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1ecdsa_1verify
|
||||
(JNIEnv *penv, jclass clazz, jlong jctx, jbyteArray jsig, jbyteArray jmsg, jbyteArray jpubkey)
|
||||
{
|
||||
secp256k1_context* ctx = (secp256k1_context *)jctx;
|
||||
jbyte *pub, *msg, *sig;
|
||||
secp256k1_ecdsa_signature signature;
|
||||
secp256k1_pubkey pubkey;
|
||||
size_t sigSize, pubSize;
|
||||
int result = 0;
|
||||
|
||||
if (jctx == 0) return 0;
|
||||
if (jsig == NULL) return 0;
|
||||
if (jmsg == NULL) return 0;
|
||||
if (jpubkey == NULL) return 0;
|
||||
|
||||
sigSize = (*penv)->GetArrayLength(penv, jsig);
|
||||
int sigFormat = GetSignatureFormat(sigSize);
|
||||
CHECKRESULT(sigFormat == SIG_FORMAT_UNKNOWN, "invalid signature size");
|
||||
|
||||
pubSize = (*penv)->GetArrayLength(penv, jpubkey);
|
||||
CHECKRESULT((pubSize != 33) && (pubSize != 65), "invalid public key size");
|
||||
|
||||
CHECKRESULT((*penv)->GetArrayLength(penv, jmsg) != 32, "message must be 32 bytes");
|
||||
|
||||
sig = (*penv)->GetByteArrayElements(penv, jsig, 0);
|
||||
switch(sigFormat) {
|
||||
case SIG_FORMAT_COMPACT:
|
||||
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");
|
||||
break;
|
||||
case SIG_FORMAT_DER:
|
||||
result = secp256k1_ecdsa_signature_parse_der(ctx, &signature, (unsigned char*)sig, sigSize);
|
||||
(*penv)->ReleaseByteArrayElements(penv, jsig, sig, 0);
|
||||
CHECKRESULT(!result, "secp256k1_ecdsa_signature_parse_der failed");
|
||||
break;
|
||||
}
|
||||
|
||||
pub = (*penv)->GetByteArrayElements(penv, jpubkey, 0);
|
||||
result = secp256k1_ec_pubkey_parse(ctx, &pubkey, (unsigned char*)pub, pubSize);
|
||||
(*penv)->ReleaseByteArrayElements(penv, jpubkey, pub, 0);
|
||||
CHECKRESULT(!result, "secp256k1_ec_pubkey_parse failed");
|
||||
|
||||
msg = (*penv)->GetByteArrayElements(penv, jmsg, 0);
|
||||
result = secp256k1_ecdsa_verify(ctx, &signature, (unsigned char*)msg, &pubkey);
|
||||
(*penv)->ReleaseByteArrayElements(penv, jmsg, msg, 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: fr_acinq_bitcoin_Secp256k1Bindings
|
||||
* Method: secp256k1_ecdsa_signature_normalize
|
||||
* Signature: (J[B[B)I
|
||||
*/
|
||||
JNIEXPORT jint JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1ecdsa_1signature_1normalize
|
||||
(JNIEnv *penv, jclass clazz, jlong jctx, jbyteArray jsigin, jbyteArray jsigout)
|
||||
{
|
||||
secp256k1_context* ctx = (secp256k1_context *)jctx;
|
||||
jbyte *sig;
|
||||
secp256k1_ecdsa_signature signature_in, signature_out;
|
||||
size_t size;
|
||||
int result = 0;
|
||||
int return_value = 0;
|
||||
int sigFormat = SIG_FORMAT_UNKNOWN;
|
||||
|
||||
if (jctx == 0) return 0;
|
||||
if (jsigin == NULL) return 0;
|
||||
if (jsigout == NULL) return 0;
|
||||
|
||||
size = (*penv)->GetArrayLength(penv, jsigin);
|
||||
sigFormat = GetSignatureFormat(size);
|
||||
CHECKRESULT(sigFormat == SIG_FORMAT_UNKNOWN, "invalid signature size");
|
||||
CHECKRESULT((*penv)->GetArrayLength(penv, jsigout) != 64, "output signature length must be 64 bytes");
|
||||
|
||||
sig = (*penv)->GetByteArrayElements(penv, jsigin, 0);
|
||||
switch(sigFormat) {
|
||||
case SIG_FORMAT_COMPACT:
|
||||
result = secp256k1_ecdsa_signature_parse_compact(ctx, &signature_in, (unsigned char*)sig);
|
||||
(*penv)->ReleaseByteArrayElements(penv, jsigin, sig, 0);
|
||||
CHECKRESULT(!result, "secp256k1_ecdsa_signature_parse_compact failed");
|
||||
break;
|
||||
case SIG_FORMAT_DER:
|
||||
result = secp256k1_ecdsa_signature_parse_der(ctx, &signature_in, (unsigned char*)sig, size);
|
||||
(*penv)->ReleaseByteArrayElements(penv, jsigin, sig, 0);
|
||||
CHECKRESULT(!result, "secp256k1_ecdsa_signature_parse_der failed");
|
||||
break;
|
||||
}
|
||||
return_value = secp256k1_ecdsa_signature_normalize(ctx, &signature_out, &signature_in);
|
||||
sig = (*penv)->GetByteArrayElements(penv, jsigout, 0);
|
||||
result = secp256k1_ecdsa_signature_serialize_compact(ctx, (unsigned char*)sig, &signature_out);
|
||||
(*penv)->ReleaseByteArrayElements(penv, jsigout, sig, 0);
|
||||
CHECKRESULT(!result, "secp256k1_ecdsa_signature_serialize_compact failed");
|
||||
|
||||
return return_value;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: fr_acinq_bitcoin_Secp256k1Bindings
|
||||
* Method: secp256k1_ec_privkey_negate
|
||||
* Signature: (J[B)[B
|
||||
*/
|
||||
JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1ec_1privkey_1negate
|
||||
(JNIEnv *penv, jclass clazz, jlong jctx, jbyteArray jseckey)
|
||||
{
|
||||
secp256k1_context* ctx = (secp256k1_context *)jctx;
|
||||
jbyte *seckey;
|
||||
int result = 0;
|
||||
|
||||
if (jctx == 0) return 0;
|
||||
if (jseckey == NULL) return 0;
|
||||
CHECKRESULT((*penv)->GetArrayLength(penv, jseckey) != 32, "secret key must be 32 bytes");
|
||||
seckey = (*penv)->GetByteArrayElements(penv, jseckey, 0);
|
||||
result = secp256k1_ec_privkey_negate(ctx, (unsigned char*)seckey);
|
||||
(*penv)->ReleaseByteArrayElements(penv, jseckey, seckey, 0);
|
||||
CHECKRESULT(!result, "secp256k1_ec_privkey_negate failed");
|
||||
return jseckey;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: fr_acinq_bitcoin_Secp256k1Bindings
|
||||
* Method: secp256k1_ec_pubkey_negate
|
||||
* Signature: (J[B)[B
|
||||
*/
|
||||
JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1ec_1pubkey_1negate
|
||||
(JNIEnv *penv, jclass clazz, jlong jctx, jbyteArray jpubkey)
|
||||
{
|
||||
secp256k1_context* ctx = (secp256k1_context *)jctx;
|
||||
jbyte *pub;
|
||||
secp256k1_pubkey pubkey;
|
||||
size_t size;
|
||||
int result = 0;
|
||||
|
||||
if (jctx == 0) return 0;
|
||||
if (jpubkey == NULL) return 0;
|
||||
|
||||
size = (*penv)->GetArrayLength(penv, jpubkey);
|
||||
CHECKRESULT((size != 33) && (size != 65), "invalid public key size");
|
||||
pub = (*penv)->GetByteArrayElements(penv, jpubkey, 0);
|
||||
result = secp256k1_ec_pubkey_parse(ctx, &pubkey, (unsigned char*)pub, size);
|
||||
(*penv)->ReleaseByteArrayElements(penv, jpubkey, pub, 0);
|
||||
CHECKRESULT(!result, "secp256k1_ec_pubkey_parse failed");
|
||||
|
||||
result = secp256k1_ec_pubkey_negate(ctx, &pubkey);
|
||||
CHECKRESULT(!result, "secp256k1_ec_pubkey_negate failed");
|
||||
|
||||
size = 65;
|
||||
jpubkey = (*penv)->NewByteArray(penv, 65);
|
||||
pub = (*penv)->GetByteArrayElements(penv, jpubkey, 0);
|
||||
result = secp256k1_ec_pubkey_serialize(ctx, (unsigned char*)pub, &size, &pubkey, SECP256K1_EC_UNCOMPRESSED);
|
||||
(*penv)->ReleaseByteArrayElements(penv, jpubkey, pub, 0);
|
||||
CHECKRESULT(!result, "secp256k1_ec_pubkey_serialize failed");
|
||||
return jpubkey;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: fr_acinq_bitcoin_Secp256k1Bindings
|
||||
* Method: secp256k1_ec_privkey_tweak_add
|
||||
* Signature: (J[B[B)[B
|
||||
*/
|
||||
JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1ec_1privkey_1tweak_1add
|
||||
(JNIEnv *penv, jclass clazz, jlong jctx, jbyteArray jseckey, jbyteArray jtweak)
|
||||
{
|
||||
secp256k1_context* ctx = (secp256k1_context *)jctx;
|
||||
jbyte *seckey, *tweak;
|
||||
int result = 0;
|
||||
|
||||
if (jctx == 0) return NULL;
|
||||
if (jseckey == NULL) return NULL;
|
||||
if (jtweak == NULL) return NULL;
|
||||
|
||||
CHECKRESULT((*penv)->GetArrayLength(penv, jseckey) != 32, "secret key must be 32 bytes");
|
||||
CHECKRESULT((*penv)->GetArrayLength(penv, jtweak) != 32, "tweak must be 32 bytes");
|
||||
seckey = (*penv)->GetByteArrayElements(penv, jseckey, 0);
|
||||
tweak = (*penv)->GetByteArrayElements(penv, jtweak, 0);
|
||||
result = secp256k1_ec_privkey_tweak_add(ctx, (unsigned char*)seckey, (unsigned char*)tweak);
|
||||
(*penv)->ReleaseByteArrayElements(penv, jseckey, seckey, 0);
|
||||
(*penv)->ReleaseByteArrayElements(penv, jtweak, tweak, 0);
|
||||
CHECKRESULT(!result, "secp256k1_ec_privkey_tweak_add failed");
|
||||
return jseckey;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: fr_acinq_bitcoin_Secp256k1Bindings
|
||||
* Method: secp256k1_ec_pubkey_tweak_add
|
||||
* Signature: (J[B[B)[B
|
||||
*/
|
||||
JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1ec_1pubkey_1tweak_1add
|
||||
(JNIEnv *penv, jclass clazz, jlong jctx, jbyteArray jpubkey, jbyteArray jtweak)
|
||||
{
|
||||
secp256k1_context* ctx = (secp256k1_context *)jctx;
|
||||
jbyte *pub, *tweak;
|
||||
secp256k1_pubkey pubkey;
|
||||
size_t size;
|
||||
int result = 0;
|
||||
|
||||
if (jctx == 0) return NULL;
|
||||
if (jpubkey == NULL) return NULL;
|
||||
if (jtweak == NULL) return NULL;
|
||||
|
||||
size = (*penv)->GetArrayLength(penv, jpubkey);
|
||||
CHECKRESULT((size != 33) && (size != 65), "invalid public key size");
|
||||
CHECKRESULT((*penv)->GetArrayLength(penv, jtweak) != 32, "tweak must be 32 bytes");
|
||||
|
||||
pub = (*penv)->GetByteArrayElements(penv, jpubkey, 0);
|
||||
result = secp256k1_ec_pubkey_parse(ctx, &pubkey, (unsigned char*)pub, size);
|
||||
(*penv)->ReleaseByteArrayElements(penv, jpubkey, pub, 0);
|
||||
CHECKRESULT(!result, "secp256k1_ec_pubkey_parse failed");
|
||||
|
||||
tweak = (*penv)->GetByteArrayElements(penv, jtweak, 0);
|
||||
result = secp256k1_ec_pubkey_tweak_add(ctx, &pubkey, (unsigned char*)tweak);
|
||||
(*penv)->ReleaseByteArrayElements(penv, jtweak, tweak, 0);
|
||||
CHECKRESULT(!result, "secp256k1_ec_pubkey_tweak_add failed");
|
||||
|
||||
size = 65;
|
||||
jpubkey = (*penv)->NewByteArray(penv, 65);
|
||||
pub = (*penv)->GetByteArrayElements(penv, jpubkey, 0);
|
||||
result = secp256k1_ec_pubkey_serialize(ctx, (unsigned char*)pub, &size, &pubkey, SECP256K1_EC_UNCOMPRESSED);
|
||||
(*penv)->ReleaseByteArrayElements(penv, jpubkey, pub, 0);
|
||||
CHECKRESULT(!result, "secp256k1_ec_pubkey_serialize failed");
|
||||
return jpubkey;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: fr_acinq_bitcoin_Secp256k1Bindings
|
||||
* Method: secp256k1_ec_privkey_tweak_mul
|
||||
* Signature: (J[B[B)[B
|
||||
*/
|
||||
JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1ec_1privkey_1tweak_1mul
|
||||
(JNIEnv *penv, jclass clazz, jlong jctx, jbyteArray jseckey, jbyteArray jtweak)
|
||||
{
|
||||
secp256k1_context* ctx = (secp256k1_context *)jctx;
|
||||
jbyte *seckey, *tweak;
|
||||
int result = 0;
|
||||
|
||||
if (jctx == 0) return NULL;
|
||||
if (jseckey == NULL) return NULL;
|
||||
if (jtweak == NULL) return NULL;
|
||||
|
||||
CHECKRESULT((*penv)->GetArrayLength(penv, jseckey) != 32, "secret key must be 32 bytes");
|
||||
CHECKRESULT((*penv)->GetArrayLength(penv, jtweak) != 32, "tweak must be 32 bytes");
|
||||
seckey = (*penv)->GetByteArrayElements(penv, jseckey, 0);
|
||||
tweak = (*penv)->GetByteArrayElements(penv, jtweak, 0);
|
||||
result = secp256k1_ec_privkey_tweak_mul(ctx, (unsigned char*)seckey, (unsigned char*)tweak);
|
||||
CHECKRESULT(!result, "secp256k1_ec_privkey_tweak_mul failed");
|
||||
(*penv)->ReleaseByteArrayElements(penv, jseckey, seckey, 0);
|
||||
(*penv)->ReleaseByteArrayElements(penv, jtweak, tweak, 0);
|
||||
return jseckey;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: fr_acinq_bitcoin_Secp256k1Bindings
|
||||
* Method: secp256k1_ec_pubkey_tweak_mul
|
||||
* Signature: (J[B[B)[B
|
||||
*/
|
||||
JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1ec_1pubkey_1tweak_1mul
|
||||
(JNIEnv *penv, jclass clazz, jlong jctx, jbyteArray jpubkey, jbyteArray jtweak)
|
||||
{
|
||||
secp256k1_context* ctx = (secp256k1_context *)jctx;
|
||||
jbyte *pub, *tweak;
|
||||
secp256k1_pubkey pubkey;
|
||||
size_t size;
|
||||
int result = 0;
|
||||
|
||||
if (jctx == 0) return NULL;
|
||||
if (jpubkey == NULL) return NULL;
|
||||
if (jtweak == NULL) return NULL;
|
||||
|
||||
size = (*penv)->GetArrayLength(penv, jpubkey);
|
||||
CHECKRESULT((size != 33) && (size != 65), "invalid public key size");
|
||||
CHECKRESULT((*penv)->GetArrayLength(penv, jtweak) != 32, "tweak must be 32 bytes");
|
||||
pub = (*penv)->GetByteArrayElements(penv, jpubkey, 0);
|
||||
result = secp256k1_ec_pubkey_parse(ctx, &pubkey, (unsigned char*)pub, size);
|
||||
(*penv)->ReleaseByteArrayElements(penv, jpubkey, pub, 0);
|
||||
CHECKRESULT(!result, "secp256k1_ec_pubkey_parse failed");
|
||||
|
||||
tweak = (*penv)->GetByteArrayElements(penv, jtweak, 0);
|
||||
result = secp256k1_ec_pubkey_tweak_mul(ctx, &pubkey, (unsigned char*)tweak);
|
||||
(*penv)->ReleaseByteArrayElements(penv, jtweak, tweak, 0);
|
||||
CHECKRESULT(!result, "secp256k1_ec_pubkey_tweak_mul failed");
|
||||
|
||||
size = 65;
|
||||
jpubkey = (*penv)->NewByteArray(penv, 65);
|
||||
pub = (*penv)->GetByteArrayElements(penv, jpubkey, 0);
|
||||
result = secp256k1_ec_pubkey_serialize(ctx, (unsigned char*)pub, &size, &pubkey, SECP256K1_EC_UNCOMPRESSED);
|
||||
(*penv)->ReleaseByteArrayElements(penv, jpubkey, pub, 0);
|
||||
CHECKRESULT(!result, "secp256k1_ec_pubkey_serialize failed");
|
||||
return jpubkey;
|
||||
}
|
||||
|
||||
void free_pubkeys(secp256k1_pubkey **pubkeys, size_t count)
|
||||
{
|
||||
size_t i;
|
||||
for(i = 0; i < count; i++) {
|
||||
if (pubkeys[i] != NULL) free(pubkeys[i]);
|
||||
}
|
||||
free(pubkeys);
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: fr_acinq_bitcoin_Secp256k1Bindings
|
||||
* Method: secp256k1_ec_pubkey_add
|
||||
* Signature: (J[B[B)[B
|
||||
*/
|
||||
JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1ec_1pubkey_1add
|
||||
(JNIEnv *penv, jclass clazz, jlong jctx, jbyteArray jpubkey1, jbyteArray jpubkey2)
|
||||
{
|
||||
secp256k1_context* ctx = (secp256k1_context *)jctx;
|
||||
jbyte *pub1, *pub2;
|
||||
secp256k1_pubkey pubkey1, pubkey2, combined;
|
||||
secp256k1_pubkey const *pubkeys[2] = { &pubkey1, &pubkey2 };
|
||||
size_t size = 0;
|
||||
int result = 0;
|
||||
|
||||
if (jctx == 0) return NULL;
|
||||
if (jpubkey1 == NULL) return NULL;
|
||||
if (jpubkey2 == NULL) return NULL;
|
||||
|
||||
size = (*penv)->GetArrayLength(penv, jpubkey1);
|
||||
CHECKRESULT((size != 33) && (size != 65), "invalid public key size");
|
||||
pub1 = (*penv)->GetByteArrayElements(penv, jpubkey1, 0);
|
||||
result = secp256k1_ec_pubkey_parse(ctx, &pubkey1, (unsigned char*)pub1, size);
|
||||
(*penv)->ReleaseByteArrayElements(penv, jpubkey1, pub1, 0);
|
||||
CHECKRESULT(!result, "secp256k1_ec_pubkey_parse failed");
|
||||
|
||||
size = (*penv)->GetArrayLength(penv, jpubkey2);
|
||||
CHECKRESULT((size != 33) && (size != 65), "invalid public key size");
|
||||
pub2 = (*penv)->GetByteArrayElements(penv, jpubkey2, 0);
|
||||
result = secp256k1_ec_pubkey_parse(ctx, &pubkey2, (unsigned char*)pub2, size);
|
||||
(*penv)->ReleaseByteArrayElements(penv, jpubkey2, pub2, 0);
|
||||
CHECKRESULT(!result, "secp256k1_ec_pubkey_parse failed");
|
||||
|
||||
result = secp256k1_ec_pubkey_combine(ctx, &combined, pubkeys, 2);
|
||||
CHECKRESULT(!result, "secp256k1_ec_pubkey_combine failed");
|
||||
|
||||
size = 65;
|
||||
jpubkey1 = (*penv)->NewByteArray(penv, 65);
|
||||
pub1 = (*penv)->GetByteArrayElements(penv, jpubkey1, 0);
|
||||
result = secp256k1_ec_pubkey_serialize(ctx, (unsigned char*)pub1, &size, &combined, SECP256K1_EC_UNCOMPRESSED);
|
||||
(*penv)->ReleaseByteArrayElements(penv, jpubkey1, pub1, 0);
|
||||
CHECKRESULT(!result, "secp256k1_ec_pubkey_serialize failed");
|
||||
return jpubkey1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: fr_acinq_bitcoin_Secp256k1Bindings
|
||||
* Method: secp256k1_ec_pubkey_combine
|
||||
* Signature: (J[[B)[B
|
||||
*/
|
||||
JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1ec_1pubkey_1combine
|
||||
(JNIEnv *penv, jclass clazz, jlong jctx, jobjectArray jpubkeys)
|
||||
{
|
||||
secp256k1_context* ctx = (secp256k1_context *)jctx;
|
||||
jbyte *pub;
|
||||
secp256k1_pubkey **pubkeys;
|
||||
secp256k1_pubkey combined;
|
||||
jbyteArray jpubkey;
|
||||
size_t size, count;
|
||||
size_t i;
|
||||
int result = 0;
|
||||
|
||||
if (jctx == 0) return NULL;
|
||||
if (jpubkeys == NULL) return NULL;
|
||||
|
||||
count = (*penv)->GetArrayLength(penv, jpubkeys);
|
||||
pubkeys = calloc(count, sizeof(secp256k1_pubkey*));
|
||||
|
||||
for(i = 0; i < count; i++) {
|
||||
pubkeys[i] = calloc(1, sizeof(secp256k1_pubkey));
|
||||
jpubkey = (jbyteArray) (*penv)->GetObjectArrayElement(penv, jpubkeys, i);
|
||||
size = (*penv)->GetArrayLength(penv, jpubkey);
|
||||
CHECKRESULT1((size != 33) && (size != 65), "invalid public key size", free_pubkeys(pubkeys, count));
|
||||
pub = (*penv)->GetByteArrayElements(penv, jpubkey, 0);
|
||||
result = secp256k1_ec_pubkey_parse(ctx, pubkeys[i], (unsigned char*)pub, size);
|
||||
(*penv)->ReleaseByteArrayElements(penv, jpubkey, pub, 0);
|
||||
CHECKRESULT1(!result, "secp256k1_ec_pubkey_parse failed", free_pubkeys(pubkeys, count));
|
||||
}
|
||||
result = secp256k1_ec_pubkey_combine(ctx, &combined, (const secp256k1_pubkey * const *)pubkeys, count);
|
||||
free_pubkeys(pubkeys, count);
|
||||
CHECKRESULT(!result, "secp256k1_ec_pubkey_combine failed");
|
||||
|
||||
size = 65;
|
||||
jpubkey = (*penv)->NewByteArray(penv, 65);
|
||||
pub = (*penv)->GetByteArrayElements(penv, jpubkey, 0);
|
||||
result = secp256k1_ec_pubkey_serialize(ctx, (unsigned char*)pub, &size, &combined, SECP256K1_EC_UNCOMPRESSED);
|
||||
(*penv)->ReleaseByteArrayElements(penv, jpubkey, pub, 0);
|
||||
CHECKRESULT(!result, "secp256k1_ec_pubkey_serialize failed");
|
||||
return jpubkey;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: fr_acinq_bitcoin_Secp256k1Bindings
|
||||
* Method: secp256k1_ecdh
|
||||
* Signature: (J[B[B)[B
|
||||
*/
|
||||
JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1ecdh
|
||||
(JNIEnv *penv, jclass clazz, jlong jctx, jbyteArray jseckey, jbyteArray jpubkey)
|
||||
{
|
||||
secp256k1_context* ctx = (secp256k1_context *)jctx;
|
||||
jbyte* seckeyBytes, *pubkeyBytes, *output;
|
||||
secp256k1_pubkey pubkey;
|
||||
jbyteArray joutput;
|
||||
size_t size;
|
||||
int result;
|
||||
|
||||
if (jctx == 0) return NULL;
|
||||
if (jseckey == NULL) return NULL;
|
||||
if (jpubkey == NULL) return NULL;
|
||||
|
||||
CHECKRESULT((*penv)->GetArrayLength(penv, jseckey) != 32, "invalid private key size");
|
||||
|
||||
size = (*penv)->GetArrayLength(penv, jpubkey);
|
||||
CHECKRESULT((size != 33) && (size != 65), "invalid public key size");
|
||||
pubkeyBytes = (*penv)->GetByteArrayElements(penv, jpubkey, 0);
|
||||
result = secp256k1_ec_pubkey_parse(ctx, &pubkey, (unsigned char*)pubkeyBytes, size);
|
||||
(*penv)->ReleaseByteArrayElements(penv, jpubkey, pubkeyBytes, 0);
|
||||
CHECKRESULT(!result, "secp256k1_ec_pubkey_parse failed");
|
||||
|
||||
seckeyBytes = (*penv)->GetByteArrayElements(penv, jseckey, 0);
|
||||
joutput = (*penv)->NewByteArray(penv, 32);
|
||||
output = (*penv)->GetByteArrayElements(penv, joutput, 0);
|
||||
result = secp256k1_ecdh(ctx, (unsigned char*)output, &pubkey, (unsigned char*)seckeyBytes, NULL, NULL);
|
||||
(*penv)->ReleaseByteArrayElements(penv, joutput, output, 0);
|
||||
(*penv)->ReleaseByteArrayElements(penv, jseckey, seckeyBytes, 0);
|
||||
return joutput;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: fr_acinq_bitcoin_Secp256k1Bindings
|
||||
* Method: secp256k1_ecdsa_recover
|
||||
* Signature: (J[B[BI)[B
|
||||
*/
|
||||
JNIEXPORT jbyteArray JNICALL Java_fr_acinq_secp256k1_Secp256k1CFunctions_secp256k1_1ecdsa_1recover
|
||||
(JNIEnv *penv, jclass clazz, jlong jctx, jbyteArray jsig, jbyteArray jmsg, jint recid)
|
||||
{
|
||||
secp256k1_context* ctx = (secp256k1_context *)jctx;
|
||||
jbyte* sig, *msg, *pub;
|
||||
jbyteArray jpubkey;
|
||||
secp256k1_pubkey pubkey;
|
||||
secp256k1_ecdsa_recoverable_signature signature;
|
||||
secp256k1_ecdsa_signature dummy;
|
||||
unsigned char dummyBytes[64];
|
||||
size_t sigSize, size;
|
||||
int result;
|
||||
|
||||
if (jctx == 0) return NULL;
|
||||
if (jsig == NULL) return NULL;
|
||||
if (jmsg == NULL) return NULL;
|
||||
|
||||
sigSize = (*penv)->GetArrayLength(penv, jsig);
|
||||
int sigFormat = GetSignatureFormat(sigSize);
|
||||
CHECKRESULT(sigFormat == SIG_FORMAT_UNKNOWN, "invalid signature size");
|
||||
CHECKRESULT((*penv)->GetArrayLength(penv, jmsg) != 32, "message must be 32 bytes");
|
||||
sig = (*penv)->GetByteArrayElements(penv, jsig, 0);
|
||||
switch(sigFormat) {
|
||||
case SIG_FORMAT_COMPACT:
|
||||
result = secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &signature, (unsigned char*)sig, recid);
|
||||
(*penv)->ReleaseByteArrayElements(penv, jsig, sig, 0);
|
||||
CHECKRESULT(!result, "secp256k1_ecdsa_recoverable_signature_parse_compact failed");
|
||||
break;
|
||||
case SIG_FORMAT_DER:
|
||||
result = secp256k1_ecdsa_signature_parse_der(ctx, &dummy, (unsigned char*)sig, sigSize);
|
||||
(*penv)->ReleaseByteArrayElements(penv, jsig, sig, 0);
|
||||
CHECKRESULT(!result, "secp256k1_ecdsa_signature_parse_der failed");
|
||||
result = secp256k1_ecdsa_signature_serialize_compact(ctx, dummyBytes, &dummy);
|
||||
CHECKRESULT(!result, "secp256k1_ecdsa_signature_serialize_compact failed");
|
||||
result = secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &signature, dummyBytes, recid);
|
||||
CHECKRESULT(!result, "secp256k1_ecdsa_recoverable_signature_parse_compact failed");
|
||||
break;
|
||||
}
|
||||
msg = (*penv)->GetByteArrayElements(penv, jmsg, 0);
|
||||
result = secp256k1_ecdsa_recover(ctx, &pubkey, &signature, (unsigned char*)msg);
|
||||
(*penv)->ReleaseByteArrayElements(penv, jmsg, msg, 0);
|
||||
CHECKRESULT(!result, "secp256k1_ecdsa_recover failed");
|
||||
|
||||
size = 65;
|
||||
jpubkey = (*penv)->NewByteArray(penv, 65);
|
||||
pub = (*penv)->GetByteArrayElements(penv, jpubkey, 0);
|
||||
result = secp256k1_ec_pubkey_serialize(ctx, (unsigned char*)pub, &size, &pubkey, SECP256K1_EC_UNCOMPRESSED);
|
||||
(*penv)->ReleaseByteArrayElements(penv, jpubkey, pub, 0);
|
||||
CHECKRESULT(!result, "secp256k1_ec_pubkey_serialize failed");
|
||||
return jpubkey;
|
||||
}
|
@ -1,658 +0,0 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include "org_bitcoin_Secp256k1CFunctions.h"
|
||||
#include "include/secp256k1.h"
|
||||
#include "include/secp256k1_ecdh.h"
|
||||
#include "include/secp256k1_recovery.h"
|
||||
|
||||
|
||||
SECP256K1_API jlong JNICALL Java_org_bitcoin_Secp256k1CFunctions_secp256k1_1init_1context
|
||||
(JNIEnv* env, jclass classObject)
|
||||
{
|
||||
secp256k1_context *ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);
|
||||
|
||||
(void)classObject;(void)env;
|
||||
|
||||
return (uintptr_t)ctx;
|
||||
}
|
||||
|
||||
SECP256K1_API jlong JNICALL Java_org_bitcoin_Secp256k1CFunctions_secp256k1_1ctx_1clone
|
||||
(JNIEnv* env, jclass classObject, jlong ctx_l)
|
||||
{
|
||||
const secp256k1_context *ctx = (secp256k1_context*)(uintptr_t)ctx_l;
|
||||
|
||||
jlong ctx_clone_l = (uintptr_t) secp256k1_context_clone(ctx);
|
||||
|
||||
(void)classObject;(void)env;
|
||||
|
||||
return ctx_clone_l;
|
||||
|
||||
}
|
||||
|
||||
SECP256K1_API jint JNICALL Java_org_bitcoin_Secp256k1CFunctions_secp256k1_1context_1randomize
|
||||
(JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l)
|
||||
{
|
||||
secp256k1_context *ctx = (secp256k1_context*)(uintptr_t)ctx_l;
|
||||
|
||||
const unsigned char* seed = (unsigned char*) (*env)->GetDirectBufferAddress(env, byteBufferObject);
|
||||
|
||||
(void)classObject;
|
||||
|
||||
return secp256k1_context_randomize(ctx, seed);
|
||||
|
||||
}
|
||||
|
||||
SECP256K1_API void JNICALL Java_org_bitcoin_Secp256k1CFunctions_secp256k1_1destroy_1context
|
||||
(JNIEnv* env, jclass classObject, jlong ctx_l)
|
||||
{
|
||||
secp256k1_context *ctx = (secp256k1_context*)(uintptr_t)ctx_l;
|
||||
|
||||
secp256k1_context_destroy(ctx);
|
||||
|
||||
(void)classObject;(void)env;
|
||||
}
|
||||
|
||||
SECP256K1_API jint JNICALL Java_org_bitcoin_Secp256k1CFunctions_secp256k1_1ecdsa_1verify
|
||||
(JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l, jint siglen, jint publen)
|
||||
{
|
||||
secp256k1_context *ctx = (secp256k1_context*)(uintptr_t)ctx_l;
|
||||
|
||||
unsigned char* data = (unsigned char*) (*env)->GetDirectBufferAddress(env, byteBufferObject);
|
||||
const unsigned char* sigdata = { (unsigned char*) (data + 32) };
|
||||
const unsigned char* pubdata = { (unsigned char*) (data + siglen + 32) };
|
||||
|
||||
secp256k1_ecdsa_signature sig;
|
||||
secp256k1_pubkey pubkey;
|
||||
|
||||
int ret = 0;
|
||||
if (siglen == 64) {
|
||||
ret = secp256k1_ecdsa_signature_parse_compact(ctx, &sig, sigdata);
|
||||
} else {
|
||||
ret = secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigdata, siglen);
|
||||
}
|
||||
|
||||
if( ret ) {
|
||||
ret = secp256k1_ec_pubkey_parse(ctx, &pubkey, pubdata, publen);
|
||||
|
||||
if( ret ) {
|
||||
ret = secp256k1_ecdsa_verify(ctx, &sig, data, &pubkey);
|
||||
}
|
||||
}
|
||||
|
||||
(void)classObject;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_Secp256k1CFunctions_secp256k1_1ecdsa_1sign
|
||||
(JNIEnv* env, jclass classObject, jobject byteBufferObject, jboolean compact, jlong ctx_l)
|
||||
{
|
||||
secp256k1_context *ctx = (secp256k1_context*)(uintptr_t)ctx_l;
|
||||
unsigned char* data = (unsigned char*) (*env)->GetDirectBufferAddress(env, byteBufferObject);
|
||||
unsigned char* secKey = (unsigned char*) (data + 32);
|
||||
|
||||
jobjectArray retArray;
|
||||
jbyteArray sigArray, intsByteArray;
|
||||
unsigned char intsarray[2];
|
||||
|
||||
secp256k1_ecdsa_signature sig;
|
||||
|
||||
int ret = secp256k1_ecdsa_sign(ctx, &sig, data, secKey, NULL, NULL);
|
||||
|
||||
unsigned char outputSer[72];
|
||||
size_t outputLen = compact ? 64 : 72;
|
||||
|
||||
if( ret ) {
|
||||
if (compact) {
|
||||
int ret2 = secp256k1_ecdsa_signature_serialize_compact(ctx, outputSer, &sig ); (void)ret2;
|
||||
} else {
|
||||
int ret2 = secp256k1_ecdsa_signature_serialize_der(ctx, outputSer, &outputLen, &sig ); (void)ret2;
|
||||
}
|
||||
}
|
||||
|
||||
intsarray[0] = outputLen;
|
||||
intsarray[1] = ret;
|
||||
|
||||
retArray = (*env)->NewObjectArray(env, 2,
|
||||
(*env)->FindClass(env, "[B"),
|
||||
(*env)->NewByteArray(env, 1));
|
||||
|
||||
sigArray = (*env)->NewByteArray(env, outputLen);
|
||||
(*env)->SetByteArrayRegion(env, sigArray, 0, outputLen, (jbyte*)outputSer);
|
||||
(*env)->SetObjectArrayElement(env, retArray, 0, sigArray);
|
||||
|
||||
intsByteArray = (*env)->NewByteArray(env, 2);
|
||||
(*env)->SetByteArrayRegion(env, intsByteArray, 0, 2, (jbyte*)intsarray);
|
||||
(*env)->SetObjectArrayElement(env, retArray, 1, intsByteArray);
|
||||
|
||||
(void)classObject;
|
||||
|
||||
return retArray;
|
||||
}
|
||||
|
||||
SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_Secp256k1CFunctions_secp256k1_1ecdsa_1normalize
|
||||
(JNIEnv* env, jclass classObject, jobject byteBufferObject, jint siglen, jboolean compact, jlong ctx_l)
|
||||
{
|
||||
secp256k1_context *ctx = (secp256k1_context*)(uintptr_t)ctx_l;
|
||||
unsigned char* sigdata = (unsigned char*) (*env)->GetDirectBufferAddress(env, byteBufferObject);
|
||||
|
||||
jobjectArray retArray;
|
||||
jbyteArray sigArray, intsByteArray;
|
||||
unsigned char intsarray[3];
|
||||
|
||||
secp256k1_ecdsa_signature sig;
|
||||
|
||||
int ret = 0;
|
||||
if (siglen == 64) {
|
||||
ret = secp256k1_ecdsa_signature_parse_compact(ctx, &sig, sigdata);
|
||||
} else {
|
||||
ret = secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigdata, siglen);
|
||||
}
|
||||
|
||||
int ret2 = 0;
|
||||
if (ret) {
|
||||
ret2 = secp256k1_ecdsa_signature_normalize(ctx, &sig, &sig);
|
||||
}
|
||||
|
||||
unsigned char outputSer[72];
|
||||
size_t outputLen = compact ? 64 : 72;
|
||||
|
||||
if( ret ) {
|
||||
if (compact) {
|
||||
int ret3 = secp256k1_ecdsa_signature_serialize_compact(ctx, outputSer, &sig ); (void)ret3;
|
||||
} else {
|
||||
int ret3 = secp256k1_ecdsa_signature_serialize_der(ctx, outputSer, &outputLen, &sig ); (void)ret3;
|
||||
}
|
||||
}
|
||||
|
||||
intsarray[0] = outputLen;
|
||||
intsarray[1] = ret;
|
||||
intsarray[2] = ret2;
|
||||
|
||||
retArray = (*env)->NewObjectArray(env, 2,
|
||||
(*env)->FindClass(env, "[B"),
|
||||
(*env)->NewByteArray(env, 1));
|
||||
|
||||
sigArray = (*env)->NewByteArray(env, outputLen);
|
||||
(*env)->SetByteArrayRegion(env, sigArray, 0, outputLen, (jbyte*)outputSer);
|
||||
(*env)->SetObjectArrayElement(env, retArray, 0, sigArray);
|
||||
|
||||
intsByteArray = (*env)->NewByteArray(env, 3);
|
||||
(*env)->SetByteArrayRegion(env, intsByteArray, 0, 3, (jbyte*)intsarray);
|
||||
(*env)->SetObjectArrayElement(env, retArray, 1, intsByteArray);
|
||||
|
||||
(void)classObject;
|
||||
|
||||
return retArray;
|
||||
|
||||
}
|
||||
|
||||
SECP256K1_API jint JNICALL Java_org_bitcoin_Secp256k1CFunctions_secp256k1_1ec_1seckey_1verify
|
||||
(JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l)
|
||||
{
|
||||
secp256k1_context *ctx = (secp256k1_context*)(uintptr_t)ctx_l;
|
||||
unsigned char* secKey = (unsigned char*) (*env)->GetDirectBufferAddress(env, byteBufferObject);
|
||||
|
||||
(void)classObject;
|
||||
|
||||
return secp256k1_ec_seckey_verify(ctx, secKey);
|
||||
}
|
||||
|
||||
SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_Secp256k1CFunctions_secp256k1_1ec_1pubkey_1create
|
||||
(JNIEnv* env, jclass classObject, jobject byteBufferObject, jboolean compressed, jlong ctx_l)
|
||||
{
|
||||
secp256k1_context *ctx = (secp256k1_context*)(uintptr_t)ctx_l;
|
||||
const unsigned char* secKey = (unsigned char*) (*env)->GetDirectBufferAddress(env, byteBufferObject);
|
||||
|
||||
secp256k1_pubkey pubkey;
|
||||
|
||||
jobjectArray retArray;
|
||||
jbyteArray pubkeyArray, intsByteArray;
|
||||
unsigned char intsarray[2];
|
||||
|
||||
int ret = secp256k1_ec_pubkey_create(ctx, &pubkey, secKey);
|
||||
|
||||
unsigned char outputSer[65];
|
||||
size_t outputLen = compressed ? 33 : 65;
|
||||
|
||||
if( ret ) {
|
||||
int ret2 = secp256k1_ec_pubkey_serialize(ctx,outputSer, &outputLen, &pubkey, compressed ? SECP256K1_EC_COMPRESSED : SECP256K1_EC_UNCOMPRESSED );(void)ret2;
|
||||
}
|
||||
|
||||
intsarray[0] = outputLen;
|
||||
intsarray[1] = ret;
|
||||
|
||||
retArray = (*env)->NewObjectArray(env, 2,
|
||||
(*env)->FindClass(env, "[B"),
|
||||
(*env)->NewByteArray(env, 1));
|
||||
|
||||
pubkeyArray = (*env)->NewByteArray(env, outputLen);
|
||||
(*env)->SetByteArrayRegion(env, pubkeyArray, 0, outputLen, (jbyte*)outputSer);
|
||||
(*env)->SetObjectArrayElement(env, retArray, 0, pubkeyArray);
|
||||
|
||||
intsByteArray = (*env)->NewByteArray(env, 2);
|
||||
(*env)->SetByteArrayRegion(env, intsByteArray, 0, 2, (jbyte*)intsarray);
|
||||
(*env)->SetObjectArrayElement(env, retArray, 1, intsByteArray);
|
||||
|
||||
(void)classObject;
|
||||
|
||||
return retArray;
|
||||
}
|
||||
|
||||
SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_Secp256k1CFunctions_secp256k1_1ec_1pubkey_1parse
|
||||
(JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l, jint inputlen, jboolean compressed)
|
||||
{
|
||||
secp256k1_context *ctx = (secp256k1_context*)(uintptr_t)ctx_l;
|
||||
const unsigned char* pubkeydata = (unsigned char*) (*env)->GetDirectBufferAddress(env, byteBufferObject);
|
||||
|
||||
secp256k1_pubkey pubkey;
|
||||
|
||||
jobjectArray retArray;
|
||||
jbyteArray pubkeyArray, intsByteArray;
|
||||
unsigned char intsarray[2];
|
||||
|
||||
int ret = secp256k1_ec_pubkey_parse(ctx, &pubkey, pubkeydata, inputlen);
|
||||
|
||||
unsigned char outputSer[65];
|
||||
size_t outputLen = compressed ? 33 : 65;
|
||||
|
||||
if( ret ) {
|
||||
int ret2 = secp256k1_ec_pubkey_serialize(ctx,outputSer, &outputLen, &pubkey, compressed ? SECP256K1_EC_COMPRESSED : SECP256K1_EC_UNCOMPRESSED );(void)ret2;
|
||||
}
|
||||
|
||||
intsarray[0] = outputLen;
|
||||
intsarray[1] = ret;
|
||||
|
||||
retArray = (*env)->NewObjectArray(env, 2,
|
||||
(*env)->FindClass(env, "[B"),
|
||||
(*env)->NewByteArray(env, 1));
|
||||
|
||||
pubkeyArray = (*env)->NewByteArray(env, outputLen);
|
||||
(*env)->SetByteArrayRegion(env, pubkeyArray, 0, outputLen, (jbyte*)outputSer);
|
||||
(*env)->SetObjectArrayElement(env, retArray, 0, pubkeyArray);
|
||||
|
||||
intsByteArray = (*env)->NewByteArray(env, 2);
|
||||
(*env)->SetByteArrayRegion(env, intsByteArray, 0, 2, (jbyte*)intsarray);
|
||||
(*env)->SetObjectArrayElement(env, retArray, 1, intsByteArray);
|
||||
|
||||
(void)classObject;
|
||||
|
||||
return retArray;
|
||||
}
|
||||
|
||||
SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_Secp256k1CFunctions_secp256k1_1privkey_1negate
|
||||
(JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l)
|
||||
{
|
||||
secp256k1_context *ctx = (secp256k1_context*)(uintptr_t)ctx_l;
|
||||
unsigned char* privkey = (unsigned char*) (*env)->GetDirectBufferAddress(env, byteBufferObject);
|
||||
|
||||
jobjectArray retArray;
|
||||
jbyteArray privArray, intsByteArray;
|
||||
unsigned char intsarray[2];
|
||||
|
||||
int privkeylen = 32;
|
||||
|
||||
int ret = secp256k1_ec_privkey_negate(ctx, privkey);
|
||||
|
||||
intsarray[0] = privkeylen;
|
||||
intsarray[1] = ret;
|
||||
|
||||
retArray = (*env)->NewObjectArray(env, 2,
|
||||
(*env)->FindClass(env, "[B"),
|
||||
(*env)->NewByteArray(env, 1));
|
||||
|
||||
privArray = (*env)->NewByteArray(env, privkeylen);
|
||||
(*env)->SetByteArrayRegion(env, privArray, 0, privkeylen, (jbyte*)privkey);
|
||||
(*env)->SetObjectArrayElement(env, retArray, 0, privArray);
|
||||
|
||||
intsByteArray = (*env)->NewByteArray(env, 2);
|
||||
(*env)->SetByteArrayRegion(env, intsByteArray, 0, 2, (jbyte*)intsarray);
|
||||
(*env)->SetObjectArrayElement(env, retArray, 1, intsByteArray);
|
||||
|
||||
(void)classObject;
|
||||
|
||||
return retArray;
|
||||
}
|
||||
|
||||
SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_Secp256k1CFunctions_secp256k1_1privkey_1tweak_1add
|
||||
(JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l)
|
||||
{
|
||||
secp256k1_context *ctx = (secp256k1_context*)(uintptr_t)ctx_l;
|
||||
unsigned char* privkey = (unsigned char*) (*env)->GetDirectBufferAddress(env, byteBufferObject);
|
||||
const unsigned char* tweak = (unsigned char*) (privkey + 32);
|
||||
|
||||
jobjectArray retArray;
|
||||
jbyteArray privArray, intsByteArray;
|
||||
unsigned char intsarray[2];
|
||||
|
||||
int privkeylen = 32;
|
||||
|
||||
int ret = secp256k1_ec_privkey_tweak_add(ctx, privkey, tweak);
|
||||
|
||||
intsarray[0] = privkeylen;
|
||||
intsarray[1] = ret;
|
||||
|
||||
retArray = (*env)->NewObjectArray(env, 2,
|
||||
(*env)->FindClass(env, "[B"),
|
||||
(*env)->NewByteArray(env, 1));
|
||||
|
||||
privArray = (*env)->NewByteArray(env, privkeylen);
|
||||
(*env)->SetByteArrayRegion(env, privArray, 0, privkeylen, (jbyte*)privkey);
|
||||
(*env)->SetObjectArrayElement(env, retArray, 0, privArray);
|
||||
|
||||
intsByteArray = (*env)->NewByteArray(env, 2);
|
||||
(*env)->SetByteArrayRegion(env, intsByteArray, 0, 2, (jbyte*)intsarray);
|
||||
(*env)->SetObjectArrayElement(env, retArray, 1, intsByteArray);
|
||||
|
||||
(void)classObject;
|
||||
|
||||
return retArray;
|
||||
}
|
||||
|
||||
SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_Secp256k1CFunctions_secp256k1_1privkey_1tweak_1mul
|
||||
(JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l)
|
||||
{
|
||||
secp256k1_context *ctx = (secp256k1_context*)(uintptr_t)ctx_l;
|
||||
unsigned char* privkey = (unsigned char*) (*env)->GetDirectBufferAddress(env, byteBufferObject);
|
||||
const unsigned char* tweak = (unsigned char*) (privkey + 32);
|
||||
|
||||
jobjectArray retArray;
|
||||
jbyteArray privArray, intsByteArray;
|
||||
unsigned char intsarray[2];
|
||||
|
||||
int privkeylen = 32;
|
||||
|
||||
int ret = secp256k1_ec_privkey_tweak_mul(ctx, privkey, tweak);
|
||||
|
||||
intsarray[0] = privkeylen;
|
||||
intsarray[1] = ret;
|
||||
|
||||
retArray = (*env)->NewObjectArray(env, 2,
|
||||
(*env)->FindClass(env, "[B"),
|
||||
(*env)->NewByteArray(env, 1));
|
||||
|
||||
privArray = (*env)->NewByteArray(env, privkeylen);
|
||||
(*env)->SetByteArrayRegion(env, privArray, 0, privkeylen, (jbyte*)privkey);
|
||||
(*env)->SetObjectArrayElement(env, retArray, 0, privArray);
|
||||
|
||||
intsByteArray = (*env)->NewByteArray(env, 2);
|
||||
(*env)->SetByteArrayRegion(env, intsByteArray, 0, 2, (jbyte*)intsarray);
|
||||
(*env)->SetObjectArrayElement(env, retArray, 1, intsByteArray);
|
||||
|
||||
(void)classObject;
|
||||
|
||||
return retArray;
|
||||
}
|
||||
|
||||
JNIEXPORT jobjectArray JNICALL Java_org_bitcoin_Secp256k1CFunctions_secp256k1_1pubkey_1negate
|
||||
(JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l, jint publen)
|
||||
{
|
||||
secp256k1_context *ctx = (secp256k1_context*)(uintptr_t)ctx_l;
|
||||
unsigned char* pkey = (*env)->GetDirectBufferAddress(env, byteBufferObject);
|
||||
|
||||
jobjectArray retArray;
|
||||
jbyteArray pubArray, intsByteArray;
|
||||
unsigned char intsarray[2];
|
||||
unsigned char outputSer[65];
|
||||
size_t outputLen = publen;
|
||||
|
||||
secp256k1_pubkey pubkey;
|
||||
int ret = secp256k1_ec_pubkey_parse(ctx, &pubkey, pkey, publen);
|
||||
|
||||
if( ret ) {
|
||||
ret = secp256k1_ec_pubkey_negate(ctx, &pubkey);
|
||||
}
|
||||
|
||||
if( ret ) {
|
||||
int ret2 = secp256k1_ec_pubkey_serialize(ctx,outputSer, &outputLen, &pubkey, publen == 33 ? SECP256K1_EC_COMPRESSED : SECP256K1_EC_UNCOMPRESSED );(void)ret2;
|
||||
}
|
||||
|
||||
intsarray[0] = outputLen;
|
||||
intsarray[1] = ret;
|
||||
|
||||
retArray = (*env)->NewObjectArray(env, 2,
|
||||
(*env)->FindClass(env, "[B"),
|
||||
(*env)->NewByteArray(env, 1));
|
||||
|
||||
pubArray = (*env)->NewByteArray(env, outputLen);
|
||||
(*env)->SetByteArrayRegion(env, pubArray, 0, outputLen, (jbyte*)outputSer);
|
||||
(*env)->SetObjectArrayElement(env, retArray, 0, pubArray);
|
||||
|
||||
intsByteArray = (*env)->NewByteArray(env, 2);
|
||||
(*env)->SetByteArrayRegion(env, intsByteArray, 0, 2, (jbyte*)intsarray);
|
||||
(*env)->SetObjectArrayElement(env, retArray, 1, intsByteArray);
|
||||
|
||||
(void)classObject;
|
||||
|
||||
return retArray;
|
||||
}
|
||||
|
||||
SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_Secp256k1CFunctions_secp256k1_1pubkey_1tweak_1add
|
||||
(JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l, jint publen)
|
||||
{
|
||||
secp256k1_context *ctx = (secp256k1_context*)(uintptr_t)ctx_l;
|
||||
/* secp256k1_pubkey* pubkey = (secp256k1_pubkey*) (*env)->GetDirectBufferAddress(env, byteBufferObject);*/
|
||||
unsigned char* pkey = (*env)->GetDirectBufferAddress(env, byteBufferObject);
|
||||
const unsigned char* tweak = (unsigned char*) (pkey + publen);
|
||||
|
||||
jobjectArray retArray;
|
||||
jbyteArray pubArray, intsByteArray;
|
||||
unsigned char intsarray[2];
|
||||
unsigned char outputSer[65];
|
||||
size_t outputLen = publen;
|
||||
|
||||
secp256k1_pubkey pubkey;
|
||||
int ret = secp256k1_ec_pubkey_parse(ctx, &pubkey, pkey, publen);
|
||||
|
||||
if( ret ) {
|
||||
ret = secp256k1_ec_pubkey_tweak_add(ctx, &pubkey, tweak);
|
||||
}
|
||||
|
||||
if( ret ) {
|
||||
int ret2 = secp256k1_ec_pubkey_serialize(ctx,outputSer, &outputLen, &pubkey, publen == 33 ? SECP256K1_EC_COMPRESSED : SECP256K1_EC_UNCOMPRESSED);(void)ret2;
|
||||
}
|
||||
|
||||
intsarray[0] = outputLen;
|
||||
intsarray[1] = ret;
|
||||
|
||||
retArray = (*env)->NewObjectArray(env, 2,
|
||||
(*env)->FindClass(env, "[B"),
|
||||
(*env)->NewByteArray(env, 1));
|
||||
|
||||
pubArray = (*env)->NewByteArray(env, outputLen);
|
||||
(*env)->SetByteArrayRegion(env, pubArray, 0, outputLen, (jbyte*)outputSer);
|
||||
(*env)->SetObjectArrayElement(env, retArray, 0, pubArray);
|
||||
|
||||
intsByteArray = (*env)->NewByteArray(env, 2);
|
||||
(*env)->SetByteArrayRegion(env, intsByteArray, 0, 2, (jbyte*)intsarray);
|
||||
(*env)->SetObjectArrayElement(env, retArray, 1, intsByteArray);
|
||||
|
||||
(void)classObject;
|
||||
|
||||
return retArray;
|
||||
}
|
||||
|
||||
SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_Secp256k1CFunctions_secp256k1_1pubkey_1tweak_1mul
|
||||
(JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l, jint publen)
|
||||
{
|
||||
secp256k1_context *ctx = (secp256k1_context*)(uintptr_t)ctx_l;
|
||||
unsigned char* pkey = (*env)->GetDirectBufferAddress(env, byteBufferObject);
|
||||
const unsigned char* tweak = (unsigned char*) (pkey + publen);
|
||||
|
||||
jobjectArray retArray;
|
||||
jbyteArray pubArray, intsByteArray;
|
||||
unsigned char intsarray[2];
|
||||
unsigned char outputSer[65];
|
||||
size_t outputLen = publen;
|
||||
|
||||
secp256k1_pubkey pubkey;
|
||||
int ret = secp256k1_ec_pubkey_parse(ctx, &pubkey, pkey, publen);
|
||||
|
||||
if ( ret ) {
|
||||
ret = secp256k1_ec_pubkey_tweak_mul(ctx, &pubkey, tweak);
|
||||
}
|
||||
|
||||
if( ret ) {
|
||||
int ret2 = secp256k1_ec_pubkey_serialize(ctx,outputSer, &outputLen, &pubkey, publen == 33 ? SECP256K1_EC_COMPRESSED : SECP256K1_EC_UNCOMPRESSED);(void)ret2;
|
||||
}
|
||||
|
||||
intsarray[0] = outputLen;
|
||||
intsarray[1] = ret;
|
||||
|
||||
retArray = (*env)->NewObjectArray(env, 2,
|
||||
(*env)->FindClass(env, "[B"),
|
||||
(*env)->NewByteArray(env, 1));
|
||||
|
||||
pubArray = (*env)->NewByteArray(env, outputLen);
|
||||
(*env)->SetByteArrayRegion(env, pubArray, 0, outputLen, (jbyte*)outputSer);
|
||||
(*env)->SetObjectArrayElement(env, retArray, 0, pubArray);
|
||||
|
||||
intsByteArray = (*env)->NewByteArray(env, 2);
|
||||
(*env)->SetByteArrayRegion(env, intsByteArray, 0, 2, (jbyte*)intsarray);
|
||||
(*env)->SetObjectArrayElement(env, retArray, 1, intsByteArray);
|
||||
|
||||
(void)classObject;
|
||||
|
||||
return retArray;
|
||||
}
|
||||
|
||||
JNIEXPORT jobjectArray JNICALL Java_org_bitcoin_Secp256k1CFunctions_secp256k1_1ec_1pubkey_1add
|
||||
(JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l, jint publen1, jint publen2)
|
||||
{
|
||||
secp256k1_context *ctx = (secp256k1_context*)(uintptr_t)ctx_l;
|
||||
const unsigned char* pubdata1 = (*env)->GetDirectBufferAddress(env, byteBufferObject);
|
||||
const unsigned char* pubdata2 = (const unsigned char*) (pubdata1 + publen1);
|
||||
jobjectArray retArray;
|
||||
jbyteArray pubArray, intsByteArray;
|
||||
unsigned char intsarray[2];
|
||||
secp256k1_pubkey pubkey1, pubkey2;
|
||||
const secp256k1_pubkey *pubkeys[2];
|
||||
unsigned char outputSer[65];
|
||||
size_t outputLen = publen1;
|
||||
|
||||
int ret = secp256k1_ec_pubkey_parse(ctx, &pubkey1, pubdata1, publen1);
|
||||
if (ret) {
|
||||
ret = secp256k1_ec_pubkey_parse(ctx, &pubkey2, pubdata2, publen2);
|
||||
}
|
||||
secp256k1_pubkey result;
|
||||
if (ret) {
|
||||
pubkeys[0] = &pubkey1;
|
||||
pubkeys[1] = &pubkey2;
|
||||
ret = secp256k1_ec_pubkey_combine(ctx, &result, pubkeys, 2);
|
||||
}
|
||||
if (ret) {
|
||||
ret = secp256k1_ec_pubkey_serialize(ctx, outputSer, &outputLen, &result, publen1 == 33 ? SECP256K1_EC_COMPRESSED : SECP256K1_EC_UNCOMPRESSED );
|
||||
}
|
||||
intsarray[0] = outputLen;
|
||||
intsarray[1] = ret;
|
||||
|
||||
retArray = (*env)->NewObjectArray(env, 2,
|
||||
(*env)->FindClass(env, "[B"),
|
||||
(*env)->NewByteArray(env, 1));
|
||||
|
||||
pubArray = (*env)->NewByteArray(env, outputLen);
|
||||
(*env)->SetByteArrayRegion(env, pubArray, 0, outputLen, (jbyte*)outputSer);
|
||||
(*env)->SetObjectArrayElement(env, retArray, 0, pubArray);
|
||||
|
||||
intsByteArray = (*env)->NewByteArray(env, 2);
|
||||
(*env)->SetByteArrayRegion(env, intsByteArray, 0, 2, (jbyte*)intsarray);
|
||||
(*env)->SetObjectArrayElement(env, retArray, 1, intsByteArray);
|
||||
|
||||
(void)classObject;
|
||||
|
||||
return retArray;
|
||||
}
|
||||
|
||||
SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_Secp256k1CFunctions_secp256k1_1ecdh
|
||||
(JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l, jint publen)
|
||||
{
|
||||
secp256k1_context *ctx = (secp256k1_context*)(uintptr_t)ctx_l;
|
||||
const unsigned char* secdata = (*env)->GetDirectBufferAddress(env, byteBufferObject);
|
||||
const unsigned char* pubdata = (const unsigned char*) (secdata + 32);
|
||||
|
||||
jobjectArray retArray;
|
||||
jbyteArray outArray, intsByteArray;
|
||||
unsigned char intsarray[1];
|
||||
secp256k1_pubkey pubkey;
|
||||
unsigned char nonce_res[32];
|
||||
size_t outputLen = 32;
|
||||
|
||||
int ret = secp256k1_ec_pubkey_parse(ctx, &pubkey, pubdata, publen);
|
||||
|
||||
if (ret) {
|
||||
ret = secp256k1_ecdh(
|
||||
ctx,
|
||||
nonce_res,
|
||||
&pubkey,
|
||||
secdata,
|
||||
NULL,
|
||||
NULL
|
||||
);
|
||||
}
|
||||
|
||||
intsarray[0] = ret;
|
||||
|
||||
retArray = (*env)->NewObjectArray(env, 2,
|
||||
(*env)->FindClass(env, "[B"),
|
||||
(*env)->NewByteArray(env, 1));
|
||||
|
||||
outArray = (*env)->NewByteArray(env, outputLen);
|
||||
(*env)->SetByteArrayRegion(env, outArray, 0, 32, (jbyte*)nonce_res);
|
||||
(*env)->SetObjectArrayElement(env, retArray, 0, outArray);
|
||||
|
||||
intsByteArray = (*env)->NewByteArray(env, 1);
|
||||
(*env)->SetByteArrayRegion(env, intsByteArray, 0, 1, (jbyte*)intsarray);
|
||||
(*env)->SetObjectArrayElement(env, retArray, 1, intsByteArray);
|
||||
|
||||
(void)classObject;
|
||||
|
||||
return retArray;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: org_bitcoin_NativeSecp256k1
|
||||
* Method: secp256k1_ecdsa_recover
|
||||
* Signature: (Ljava/nio/ByteBuffer;JI)[[B
|
||||
*/
|
||||
JNIEXPORT jobjectArray JNICALL Java_org_bitcoin_Secp256k1CFunctions_secp256k1_1ecdsa_1recover
|
||||
(JNIEnv *env, jclass classObject, jobject byteBufferObject, jlong ctx_l, jint recid, jboolean compressed)
|
||||
{
|
||||
secp256k1_context *ctx = (secp256k1_context*)(uintptr_t)ctx_l;
|
||||
const unsigned char* sigdata = (*env)->GetDirectBufferAddress(env, byteBufferObject);
|
||||
const unsigned char* msgdata = (const unsigned char*)(sigdata + 64);
|
||||
secp256k1_ecdsa_recoverable_signature sig;
|
||||
secp256k1_pubkey pub;
|
||||
unsigned char outputSer[65];
|
||||
size_t outputLen = compressed ? 33 : 65;
|
||||
jobjectArray retArray;
|
||||
jbyteArray pubArray, intsByteArray;
|
||||
unsigned char intsarray[1];
|
||||
|
||||
int ret = secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &sig, sigdata, recid);
|
||||
if (ret) {
|
||||
ret = secp256k1_ecdsa_recover(ctx, &pub, &sig, msgdata);
|
||||
if (ret) {
|
||||
ret = secp256k1_ec_pubkey_serialize(ctx, outputSer, &outputLen, &pub, compressed ? SECP256K1_EC_COMPRESSED : SECP256K1_EC_UNCOMPRESSED );
|
||||
}
|
||||
}
|
||||
|
||||
intsarray[0] = ret;
|
||||
|
||||
retArray = (*env)->NewObjectArray(env, 2,
|
||||
(*env)->FindClass(env, "[B"),
|
||||
(*env)->NewByteArray(env, 1));
|
||||
|
||||
pubArray = (*env)->NewByteArray(env, outputLen);
|
||||
(*env)->SetByteArrayRegion(env, pubArray, 0, outputLen, (jbyte*)outputSer);
|
||||
(*env)->SetObjectArrayElement(env, retArray, 0, pubArray);
|
||||
|
||||
intsByteArray = (*env)->NewByteArray(env, 1);
|
||||
(*env)->SetByteArrayRegion(env, intsByteArray, 0, 1, (jbyte*)intsarray);
|
||||
(*env)->SetObjectArrayElement(env, retArray, 1, intsByteArray);
|
||||
|
||||
(void)classObject;
|
||||
|
||||
return retArray;
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
package fr.acinq.secp256k1.jni
|
||||
|
||||
import fr.acinq.secp256k1.Secp256k1
|
||||
import org.bitcoin.NativeSecp256k1
|
||||
import fr.acinq.secp256k1.NativeSecp256k1
|
||||
import java.io.*
|
||||
import java.util.*
|
||||
|
||||
|
@ -0,0 +1,67 @@
|
||||
package fr.acinq.secp256k1;
|
||||
|
||||
public class Secp256k1CFunctions {
|
||||
/**
|
||||
* All flags' lower 8 bits indicate what they're for. Do not use directly.
|
||||
*/
|
||||
public static int SECP256K1_FLAGS_TYPE_MASK = ((1 << 8) - 1);
|
||||
public static int SECP256K1_FLAGS_TYPE_CONTEXT = (1 << 0);
|
||||
public static int SECP256K1_FLAGS_TYPE_COMPRESSION = (1 << 1);
|
||||
|
||||
/**
|
||||
* The higher bits contain the actual data. Do not use directly.
|
||||
*/
|
||||
public static int SECP256K1_FLAGS_BIT_CONTEXT_VERIFY = (1 << 8);
|
||||
public static int SECP256K1_FLAGS_BIT_CONTEXT_SIGN = (1 << 9);
|
||||
public static int SECP256K1_FLAGS_BIT_COMPRESSION = (1 << 8);
|
||||
|
||||
/**
|
||||
* Flags to pass to secp256k1_context_create, secp256k1_context_preallocated_size, and
|
||||
* secp256k1_context_preallocated_create.
|
||||
*/
|
||||
public static int SECP256K1_CONTEXT_VERIFY = (SECP256K1_FLAGS_TYPE_CONTEXT | SECP256K1_FLAGS_BIT_CONTEXT_VERIFY);
|
||||
public static int SECP256K1_CONTEXT_SIGN = (SECP256K1_FLAGS_TYPE_CONTEXT | SECP256K1_FLAGS_BIT_CONTEXT_SIGN);
|
||||
public static int SECP256K1_CONTEXT_NONE = (SECP256K1_FLAGS_TYPE_CONTEXT);
|
||||
|
||||
/**
|
||||
* Flag to pass to secp256k1_ec_pubkey_serialize.
|
||||
*/
|
||||
public static int SECP256K1_EC_COMPRESSED = (SECP256K1_FLAGS_TYPE_COMPRESSION | SECP256K1_FLAGS_BIT_COMPRESSION);
|
||||
public static int SECP256K1_EC_UNCOMPRESSED = (SECP256K1_FLAGS_TYPE_COMPRESSION);
|
||||
|
||||
public static native long secp256k1_context_create(int flags);
|
||||
|
||||
public static native void secp256k1_context_destroy(long ctx);
|
||||
|
||||
public static native int secp256k1_ec_seckey_verify(long ctx, byte[] seckey);
|
||||
|
||||
public static native byte[] secp256k1_ec_pubkey_parse(long ctx, byte[] pubkey);
|
||||
|
||||
public static native byte[] secp256k1_ec_pubkey_create(long ctx, byte[] seckey);
|
||||
|
||||
public static native byte[] secp256k1_ecdsa_sign(long ctx, byte[] msg, byte[] seckey);
|
||||
|
||||
public static native int secp256k1_ecdsa_verify(long ctx, byte[] sig, byte[] msg, byte[] pubkey);
|
||||
|
||||
public static native int secp256k1_ecdsa_signature_normalize(long ctx, byte[] sigin, byte[] sigout);
|
||||
|
||||
public static native byte[] secp256k1_ec_privkey_negate(long ctx, byte[] privkey);
|
||||
|
||||
public static native byte[] secp256k1_ec_pubkey_negate(long ctx, byte[] pubkey);
|
||||
|
||||
public static native byte[] secp256k1_ec_privkey_tweak_add(long ctx, byte[] seckey, byte[] tweak);
|
||||
|
||||
public static native byte[] secp256k1_ec_pubkey_tweak_add(long ctx, byte[] pubkey, byte[] tweak);
|
||||
|
||||
public static native byte[] secp256k1_ec_privkey_tweak_mul(long ctx, byte[] seckey, byte[] tweak);
|
||||
|
||||
public static native byte[] secp256k1_ec_pubkey_tweak_mul(long ctx, byte[] pubkey, byte[] tweak);
|
||||
|
||||
public static native byte[] secp256k1_ec_pubkey_add(long ctx, byte[] pubkey1, byte[] pubkey2);
|
||||
|
||||
public static native byte[] secp256k1_ec_pubkey_combine(long ctx, byte[][] pubkeys);
|
||||
|
||||
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);
|
||||
}
|
@ -1,24 +0,0 @@
|
||||
package org.bitcoin;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
public class Secp256k1CFunctions {
|
||||
static native long secp256k1_init_context();
|
||||
static native int secp256k1_context_randomize(ByteBuffer byteBuff, long context);
|
||||
static native byte[][] secp256k1_privkey_negate(ByteBuffer byteBuff, long context);
|
||||
static native byte[][] secp256k1_privkey_tweak_add(ByteBuffer byteBuff, long context);
|
||||
static native byte[][] secp256k1_privkey_tweak_mul(ByteBuffer byteBuff, long context);
|
||||
static native byte[][] secp256k1_pubkey_negate(ByteBuffer byteBuff, long context, int pubLen);
|
||||
static native byte[][] secp256k1_pubkey_tweak_add(ByteBuffer byteBuff, long context, int pubLen);
|
||||
static native byte[][] secp256k1_pubkey_tweak_mul(ByteBuffer byteBuff, long context, int pubLen);
|
||||
static native void secp256k1_destroy_context(long context);
|
||||
static native int secp256k1_ecdsa_verify(ByteBuffer byteBuff, long context, int sigLen, int pubLen);
|
||||
static native byte[][] secp256k1_ecdsa_sign(ByteBuffer byteBuff, boolean compact, long context);
|
||||
static native byte[][] secp256k1_ecdsa_normalize(ByteBuffer byteBuff, int sigLen, boolean compact, long context);
|
||||
static native int secp256k1_ec_seckey_verify(ByteBuffer byteBuff, long context);
|
||||
static native byte[][] secp256k1_ec_pubkey_create(ByteBuffer byteBuff, boolean compressed, long context);
|
||||
static native byte[][] secp256k1_ec_pubkey_parse(ByteBuffer byteBuff, long context, int inputLen, boolean compressed);
|
||||
static native byte[][] secp256k1_ec_pubkey_add(ByteBuffer byteBuff, long context, int lent1, int len2);
|
||||
static native byte[][] secp256k1_ecdh(ByteBuffer byteBuff, long context, int inputLen);
|
||||
static native byte[][] secp256k1_ecdsa_recover(ByteBuffer byteBuff, long context, int recid, boolean compressed);
|
||||
}
|
86
jni/src/main/kotlin/fr/acinq/secp256k1/NativeSecp256k1.kt
Normal file
86
jni/src/main/kotlin/fr/acinq/secp256k1/NativeSecp256k1.kt
Normal file
@ -0,0 +1,86 @@
|
||||
/*
|
||||
* 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 fr.acinq.secp256k1
|
||||
|
||||
public object NativeSecp256k1 : Secp256k1 {
|
||||
override fun verify(signature: ByteArray, data: ByteArray, pub: ByteArray): Boolean {
|
||||
return Secp256k1CFunctions.secp256k1_ecdsa_verify(Secp256k1Context.getContext(), signature, data, pub) == 1
|
||||
}
|
||||
|
||||
override fun sign(data: ByteArray, sec: ByteArray): ByteArray {
|
||||
return Secp256k1CFunctions.secp256k1_ecdsa_sign(Secp256k1Context.getContext(), data, sec)
|
||||
}
|
||||
|
||||
override fun signatureNormalize(sig: ByteArray): Pair<ByteArray, Boolean> {
|
||||
val sigout = ByteArray(64)
|
||||
val result = Secp256k1CFunctions.secp256k1_ecdsa_signature_normalize(Secp256k1Context.getContext(), sig, sigout)
|
||||
return Pair(sigout, result == 1)
|
||||
}
|
||||
|
||||
override fun secKeyVerify(seckey: ByteArray): Boolean {
|
||||
val result = Secp256k1CFunctions.secp256k1_ec_seckey_verify(Secp256k1Context.getContext(), seckey);
|
||||
return result == 1;
|
||||
}
|
||||
|
||||
override fun pubkeyCreate(seckey: ByteArray): ByteArray {
|
||||
return Secp256k1CFunctions.secp256k1_ec_pubkey_create(Secp256k1Context.getContext(), seckey)
|
||||
}
|
||||
|
||||
override fun pubkeyParse(pubkey: ByteArray): ByteArray {
|
||||
return Secp256k1CFunctions.secp256k1_ec_pubkey_parse(Secp256k1Context.getContext(), pubkey)
|
||||
}
|
||||
|
||||
override fun cleanup() {
|
||||
return Secp256k1CFunctions.secp256k1_context_destroy(Secp256k1Context.getContext())
|
||||
}
|
||||
|
||||
override fun privKeyNegate(privkey: ByteArray): ByteArray {
|
||||
return Secp256k1CFunctions.secp256k1_ec_privkey_negate(Secp256k1Context.getContext(), privkey)
|
||||
}
|
||||
|
||||
override fun privKeyTweakMul(privkey: ByteArray, tweak: ByteArray): ByteArray {
|
||||
return Secp256k1CFunctions.secp256k1_ec_privkey_tweak_mul(Secp256k1Context.getContext(), privkey, tweak)
|
||||
}
|
||||
|
||||
override fun privKeyTweakAdd(privkey: ByteArray, tweak: ByteArray): ByteArray {
|
||||
return Secp256k1CFunctions.secp256k1_ec_privkey_tweak_add(Secp256k1Context.getContext(), privkey, tweak)
|
||||
}
|
||||
|
||||
override fun pubKeyNegate(pubkey: ByteArray): ByteArray {
|
||||
return Secp256k1CFunctions.secp256k1_ec_pubkey_negate(Secp256k1Context.getContext(), pubkey)
|
||||
}
|
||||
|
||||
override fun pubKeyTweakAdd(pubkey: ByteArray, tweak: ByteArray): ByteArray {
|
||||
return Secp256k1CFunctions.secp256k1_ec_pubkey_tweak_add(Secp256k1Context.getContext(), pubkey, tweak)
|
||||
}
|
||||
|
||||
override fun pubKeyTweakMul(pubkey: ByteArray, tweak: ByteArray): ByteArray {
|
||||
return Secp256k1CFunctions.secp256k1_ec_pubkey_tweak_mul(Secp256k1Context.getContext(), pubkey, tweak)
|
||||
}
|
||||
|
||||
override fun pubKeyAdd(pubkey1: ByteArray, pubkey2: ByteArray): ByteArray {
|
||||
return Secp256k1CFunctions.secp256k1_ec_pubkey_add(Secp256k1Context.getContext(), pubkey1, pubkey2)
|
||||
}
|
||||
|
||||
override fun ecdh(seckey: ByteArray, pubkey: ByteArray): ByteArray {
|
||||
return Secp256k1CFunctions.secp256k1_ecdh(Secp256k1Context.getContext(), seckey, pubkey)
|
||||
}
|
||||
|
||||
override fun ecdsaRecover(sig: ByteArray, message: ByteArray, recid: Int): ByteArray {
|
||||
return Secp256k1CFunctions.secp256k1_ecdsa_recover(Secp256k1Context.getContext(), sig, message, recid)
|
||||
}
|
||||
}
|
@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.bitcoin
|
||||
package fr.acinq.secp256k1
|
||||
|
||||
import java.lang.Exception
|
||||
|
@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.bitcoin
|
||||
package fr.acinq.secp256k1
|
||||
|
||||
/**
|
||||
* This class holds the context reference used in native methods
|
||||
@ -31,6 +31,6 @@ public object Secp256k1Context {
|
||||
|
||||
init { //static initializer
|
||||
isEnabled = true
|
||||
context = Secp256k1CFunctions.secp256k1_init_context()
|
||||
context = Secp256k1CFunctions.secp256k1_context_create(Secp256k1CFunctions.SECP256K1_CONTEXT_SIGN or Secp256k1CFunctions.SECP256K1_CONTEXT_VERIFY)
|
||||
}
|
||||
}
|
@ -1,533 +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 fr.acinq.secp256k1.PubKeyFormat
|
||||
import fr.acinq.secp256k1.Secp256k1
|
||||
import fr.acinq.secp256k1.SigFormat
|
||||
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 : Secp256k1 {
|
||||
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
|
||||
*/
|
||||
@Throws(AssertFailException::class)
|
||||
override 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 {
|
||||
Secp256k1CFunctions.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
|
||||
*/
|
||||
@Throws(AssertFailException::class)
|
||||
override fun sign(data: ByteArray, sec: ByteArray, format: SigFormat): ByteArray {
|
||||
require(data.size == 32 && sec.size <= 32)
|
||||
val byteBuff = pack(data, sec)
|
||||
val retByteArray: Array<ByteArray>
|
||||
r.lock()
|
||||
retByteArray = try {
|
||||
Secp256k1CFunctions.secp256k1_ecdsa_sign(
|
||||
byteBuff,
|
||||
format == SigFormat.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
|
||||
}
|
||||
|
||||
@Throws(AssertFailException::class)
|
||||
override fun signatureNormalize(sig: ByteArray, format: SigFormat): Pair<ByteArray, Boolean> {
|
||||
require(sig.size == 64 || sig.size in 70..73)
|
||||
val byteBuff = pack(sig)
|
||||
val retByteArray: Array<ByteArray>
|
||||
r.lock()
|
||||
retByteArray = try {
|
||||
Secp256k1CFunctions.secp256k1_ecdsa_normalize(
|
||||
byteBuff,
|
||||
sig.size,
|
||||
format == SigFormat.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
|
||||
*/
|
||||
override fun secKeyVerify(seckey: ByteArray): Boolean {
|
||||
require(seckey.size == 32)
|
||||
val byteBuff = pack(seckey)
|
||||
r.lock()
|
||||
return try {
|
||||
Secp256k1CFunctions.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
|
||||
@Throws(AssertFailException::class)
|
||||
override fun computePubkey(seckey: ByteArray, format: PubKeyFormat): ByteArray {
|
||||
require(seckey.size == 32)
|
||||
val byteBuff = pack(seckey)
|
||||
val retByteArray: Array<ByteArray>
|
||||
r.lock()
|
||||
retByteArray = try {
|
||||
Secp256k1CFunctions.secp256k1_ec_pubkey_create(
|
||||
byteBuff,
|
||||
format == PubKeyFormat.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
|
||||
*/
|
||||
@Throws(AssertFailException::class)
|
||||
override fun parsePubkey(pubkey: ByteArray, format: PubKeyFormat): ByteArray {
|
||||
require(pubkey.size == 33 || pubkey.size == 65)
|
||||
val byteBuff = pack(pubkey)
|
||||
val retByteArray: Array<ByteArray>
|
||||
r.lock()
|
||||
retByteArray = try {
|
||||
Secp256k1CFunctions.secp256k1_ec_pubkey_parse(
|
||||
byteBuff,
|
||||
Secp256k1Context.getContext(),
|
||||
pubkey.size,
|
||||
format == PubKeyFormat.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,
|
||||
format.maxSize,
|
||||
"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.
|
||||
*/
|
||||
@Synchronized
|
||||
override fun cleanup() {
|
||||
w.lock()
|
||||
try {
|
||||
Secp256k1CFunctions.secp256k1_destroy_context(Secp256k1Context.getContext())
|
||||
} finally {
|
||||
w.unlock()
|
||||
}
|
||||
}
|
||||
|
||||
@Throws(AssertFailException::class)
|
||||
override fun privKeyNegate(privkey: ByteArray): ByteArray {
|
||||
require(privkey.size == 32)
|
||||
val byteBuff = pack(privkey)
|
||||
val retByteArray: Array<ByteArray>
|
||||
r.lock()
|
||||
retByteArray = try {
|
||||
Secp256k1CFunctions.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
|
||||
*/
|
||||
@Throws(AssertFailException::class)
|
||||
override fun privKeyTweakMul(privkey: ByteArray, tweak: ByteArray): ByteArray {
|
||||
require(privkey.size == 32)
|
||||
val byteBuff = pack(privkey, tweak)
|
||||
val retByteArray: Array<ByteArray>
|
||||
r.lock()
|
||||
retByteArray = try {
|
||||
Secp256k1CFunctions.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
|
||||
*/
|
||||
@Throws(AssertFailException::class)
|
||||
override fun privKeyTweakAdd(privkey: ByteArray, tweak: ByteArray): ByteArray {
|
||||
require(privkey.size == 32)
|
||||
val byteBuff = pack(privkey, tweak)
|
||||
val retByteArray: Array<ByteArray>
|
||||
r.lock()
|
||||
retByteArray = try {
|
||||
Secp256k1CFunctions.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
|
||||
}
|
||||
|
||||
@Throws(AssertFailException::class)
|
||||
override fun pubKeyNegate(pubkey: ByteArray): ByteArray {
|
||||
require(pubkey.size == 33 || pubkey.size == 65)
|
||||
val byteBuff = pack(pubkey)
|
||||
val retByteArray: Array<ByteArray>
|
||||
r.lock()
|
||||
retByteArray = try {
|
||||
Secp256k1CFunctions.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
|
||||
*/
|
||||
@Throws(AssertFailException::class)
|
||||
override 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 {
|
||||
Secp256k1CFunctions.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
|
||||
*/
|
||||
@Throws(AssertFailException::class)
|
||||
override 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 {
|
||||
Secp256k1CFunctions.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
|
||||
}
|
||||
|
||||
@Throws(AssertFailException::class)
|
||||
override 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 {
|
||||
Secp256k1CFunctions.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
|
||||
*/
|
||||
@Throws(AssertFailException::class)
|
||||
override 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 {
|
||||
Secp256k1CFunctions.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
|
||||
}
|
||||
|
||||
@Throws(AssertFailException::class)
|
||||
override fun ecdsaRecover(sig: ByteArray, message: ByteArray, recid: Int, format: PubKeyFormat): ByteArray {
|
||||
require(sig.size == 64)
|
||||
require(message.size == 32)
|
||||
val byteBuff = pack(sig, message)
|
||||
val retByteArray: Array<ByteArray>
|
||||
r.lock()
|
||||
retByteArray = try {
|
||||
Secp256k1CFunctions.secp256k1_ecdsa_recover(
|
||||
byteBuff,
|
||||
Secp256k1Context.getContext(),
|
||||
recid,
|
||||
format == PubKeyFormat.COMPRESSED
|
||||
)
|
||||
} finally {
|
||||
r.unlock()
|
||||
}
|
||||
val resArr = retByteArray[0]
|
||||
val retVal = BigInteger(byteArrayOf(retByteArray[1][0])).toInt()
|
||||
NativeSecp256k1Util.assertEquals(
|
||||
resArr.size,
|
||||
format.maxSize,
|
||||
"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
|
||||
*/
|
||||
@Synchronized
|
||||
@Throws(AssertFailException::class)
|
||||
override fun randomize(seed: ByteArray): Boolean {
|
||||
require(seed.size == 32)
|
||||
val byteBuff = pack(seed)
|
||||
w.lock()
|
||||
return try {
|
||||
Secp256k1CFunctions.secp256k1_context_randomize(
|
||||
byteBuff,
|
||||
Secp256k1Context.getContext()
|
||||
) == 1
|
||||
} finally {
|
||||
w.unlock()
|
||||
}
|
||||
}
|
||||
}
|
@ -18,23 +18,19 @@ package fr.acinq.secp256k1
|
||||
|
||||
import kotlin.jvm.JvmStatic
|
||||
|
||||
public enum class SigFormat(public val maxSize: Int) { COMPACT(64), DER(72) }
|
||||
|
||||
public enum class PubKeyFormat(public val maxSize: Int) { COMPRESSED(33), UNCOMPRESSED(65) }
|
||||
|
||||
public interface Secp256k1 {
|
||||
|
||||
public fun verify(data: ByteArray, signature: ByteArray, pub: ByteArray): Boolean
|
||||
public fun verify(signature: ByteArray, data: ByteArray, pub: ByteArray): Boolean
|
||||
|
||||
public fun sign(data: ByteArray, sec: ByteArray, format: SigFormat): ByteArray
|
||||
public fun sign(data: ByteArray, sec: ByteArray): ByteArray
|
||||
|
||||
public fun signatureNormalize(sig: ByteArray, format: SigFormat): Pair<ByteArray, Boolean>
|
||||
public fun signatureNormalize(sig: ByteArray): Pair<ByteArray, Boolean>
|
||||
|
||||
public fun secKeyVerify(seckey: ByteArray): Boolean
|
||||
|
||||
public fun computePubkey(seckey: ByteArray, format: PubKeyFormat): ByteArray
|
||||
public fun pubkeyCreate(seckey: ByteArray): ByteArray
|
||||
|
||||
public fun parsePubkey(pubkey: ByteArray, format: PubKeyFormat): ByteArray
|
||||
public fun pubkeyParse(pubkey: ByteArray): ByteArray
|
||||
|
||||
public fun cleanup()
|
||||
|
||||
@ -52,11 +48,21 @@ public interface Secp256k1 {
|
||||
|
||||
public fun pubKeyAdd(pubkey1: ByteArray, pubkey2: ByteArray): ByteArray
|
||||
|
||||
public fun createECDHSecret(seckey: ByteArray, pubkey: ByteArray): ByteArray
|
||||
public fun ecdh(seckey: ByteArray, pubkey: ByteArray): ByteArray
|
||||
|
||||
public fun ecdsaRecover(sig: ByteArray, message: ByteArray, recid: Int, format: PubKeyFormat): ByteArray
|
||||
public fun ecdsaRecover(sig: ByteArray, message: ByteArray, recid: Int): ByteArray
|
||||
|
||||
public fun randomize(seed: ByteArray): Boolean
|
||||
public fun pubKeyCompress(pubkey: ByteArray) : ByteArray {
|
||||
return when {
|
||||
pubkey.size == 33 && (pubkey[0] == 2.toByte() || pubkey[0] == 3.toByte()) -> pubkey
|
||||
pubkey.size == 65 && pubkey[0] == 4.toByte() -> {
|
||||
val pub1 = pubkey.copyOf(33)
|
||||
pub1[0] = if (pubkey.last() % 2 == 0) 2.toByte() else 3.toByte()
|
||||
pub1
|
||||
}
|
||||
else -> throw RuntimeException("invalid public key")
|
||||
}
|
||||
}
|
||||
|
||||
public companion object : Secp256k1 by getSecpk256k1() {
|
||||
@JvmStatic public fun get(): Secp256k1 = this
|
||||
@ -64,3 +70,8 @@ public interface Secp256k1 {
|
||||
}
|
||||
|
||||
internal expect fun getSecpk256k1(): Secp256k1
|
||||
|
||||
public class Secp256k1Exception : RuntimeException {
|
||||
public constructor() : super() {}
|
||||
public constructor(message: String?) : super(message) {}
|
||||
}
|
@ -12,7 +12,7 @@ public object Secp256k1Native : Secp256k1 {
|
||||
?: error("Could not create segp256k1 context")
|
||||
}
|
||||
|
||||
private fun Int.requireSuccess() = require(this == 1) { "secp256k1 native function call failed" }
|
||||
private fun Int.requireSuccess(message: String): Int = if (this != 1) throw Secp256k1Exception(message) else this
|
||||
|
||||
private fun MemScope.allocSignature(input: ByteArray): secp256k1_ecdsa_signature {
|
||||
val sig = alloc<secp256k1_ecdsa_signature>()
|
||||
@ -21,40 +21,30 @@ public object Secp256k1Native : Secp256k1 {
|
||||
val result = when (input.size) {
|
||||
64 -> secp256k1_ecdsa_signature_parse_compact(ctx, sig.ptr, nativeBytes)
|
||||
in 70..73 -> secp256k1_ecdsa_signature_parse_der(ctx, sig.ptr, nativeBytes, input.size.convert())
|
||||
else -> error("Unknown signature format")
|
||||
else -> throw Secp256k1Exception("Unknown signature format")
|
||||
}
|
||||
require(result == 1) { "cannot parse signature (size = ${input.size} sig = ${Hex.encode(input)}" }
|
||||
result.requireSuccess("cannot parse signature (size = ${input.size} sig = ${Hex.encode(input)}")
|
||||
return sig
|
||||
}
|
||||
|
||||
private fun MemScope.serializeSignature(signature: secp256k1_ecdsa_signature, format: SigFormat): ByteArray {
|
||||
val natOutput = allocArray<UByteVar>(format.maxSize)
|
||||
when (format) {
|
||||
SigFormat.DER -> {
|
||||
val outputLen = alloc<size_tVar>()
|
||||
outputLen.value = 72.convert()
|
||||
secp256k1_ecdsa_signature_serialize_der(ctx, natOutput, outputLen.ptr, signature.ptr).requireSuccess()
|
||||
return natOutput.readBytes(outputLen.value.toInt())
|
||||
}
|
||||
SigFormat.COMPACT -> {
|
||||
secp256k1_ecdsa_signature_serialize_compact(ctx, natOutput, signature.ptr).requireSuccess()
|
||||
return natOutput.readBytes(64)
|
||||
}
|
||||
}
|
||||
private fun MemScope.serializeSignature(signature: secp256k1_ecdsa_signature): ByteArray {
|
||||
val natOutput = allocArray<UByteVar>(64)
|
||||
secp256k1_ecdsa_signature_serialize_compact(ctx, natOutput, signature.ptr).requireSuccess("secp256k1_ecdsa_signature_serialize_compact() failed")
|
||||
return natOutput.readBytes(64)
|
||||
}
|
||||
|
||||
private fun MemScope.allocPublicKey(pubkey: ByteArray): secp256k1_pubkey {
|
||||
val natPub = toNat(pubkey)
|
||||
val pub = alloc<secp256k1_pubkey>()
|
||||
secp256k1_ec_pubkey_parse(ctx, pub.ptr, natPub, pubkey.size.convert()).requireSuccess()
|
||||
secp256k1_ec_pubkey_parse(ctx, pub.ptr, natPub, pubkey.size.convert()).requireSuccess("secp256k1_ec_pubkey_parse() failed")
|
||||
return pub
|
||||
}
|
||||
|
||||
private fun MemScope.serializePubkey(pubkey: secp256k1_pubkey, len: Int): ByteArray {
|
||||
val serialized = allocArray<UByteVar>(len)
|
||||
private fun MemScope.serializePubkey(pubkey: secp256k1_pubkey): ByteArray {
|
||||
val serialized = allocArray<UByteVar>(65)
|
||||
val outputLen = alloc<size_tVar>()
|
||||
outputLen.value = len.convert()
|
||||
secp256k1_ec_pubkey_serialize(ctx, serialized, outputLen.ptr, pubkey.ptr, (if (len == 33) SECP256K1_EC_COMPRESSED else SECP256K1_EC_UNCOMPRESSED).convert()).requireSuccess()
|
||||
outputLen.value = 65.convert()
|
||||
secp256k1_ec_pubkey_serialize(ctx, serialized, outputLen.ptr, pubkey.ptr, SECP256K1_EC_UNCOMPRESSED.convert()).requireSuccess("secp256k1_ec_pubkey_serialize() failed")
|
||||
return serialized.readBytes(outputLen.value.convert())
|
||||
}
|
||||
|
||||
@ -65,7 +55,7 @@ public object Secp256k1Native : Secp256k1 {
|
||||
return pinned.addressOf(0)
|
||||
}
|
||||
|
||||
public override fun verify(data: ByteArray, signature: ByteArray, pub: ByteArray): Boolean {
|
||||
public override fun verify(signature: ByteArray, data: ByteArray, pub: ByteArray): Boolean {
|
||||
require(data.size == 32)
|
||||
require(pub.size == 33 || pub.size == 65)
|
||||
memScoped {
|
||||
@ -76,25 +66,24 @@ public object Secp256k1Native : Secp256k1 {
|
||||
}
|
||||
}
|
||||
|
||||
public override fun sign(data: ByteArray, sec: ByteArray, format: SigFormat): ByteArray {
|
||||
public override fun sign(data: ByteArray, sec: ByteArray): ByteArray {
|
||||
require(sec.size == 32)
|
||||
require(data.size == 32)
|
||||
memScoped {
|
||||
val nSec = toNat(sec)
|
||||
val nData = toNat(data)
|
||||
val nSig = alloc<secp256k1_ecdsa_signature>()
|
||||
val result = secp256k1_ecdsa_sign(ctx, nSig.ptr, nData, nSec, null, null)
|
||||
if (result == 0) return ByteArray(0)
|
||||
return serializeSignature(nSig, format)
|
||||
secp256k1_ecdsa_sign(ctx, nSig.ptr, nData, nSec, null, null).requireSuccess("secp256k1_ecdsa_sign() failed")
|
||||
return serializeSignature(nSig)
|
||||
}
|
||||
}
|
||||
|
||||
public override fun signatureNormalize(sig: ByteArray, format: SigFormat): Pair<ByteArray, Boolean> {
|
||||
public override fun signatureNormalize(sig: ByteArray): Pair<ByteArray, Boolean> {
|
||||
require(sig.size == 64 || sig.size in 70..73)
|
||||
memScoped {
|
||||
val nSig = allocSignature(sig)
|
||||
val isHighS = secp256k1_ecdsa_signature_normalize(ctx, nSig.ptr, nSig.ptr)
|
||||
return Pair(serializeSignature(nSig, format), isHighS == 1)
|
||||
return Pair(serializeSignature(nSig), isHighS == 1)
|
||||
}
|
||||
}
|
||||
|
||||
@ -106,22 +95,21 @@ public object Secp256k1Native : Secp256k1 {
|
||||
}
|
||||
}
|
||||
|
||||
public override fun computePubkey(seckey: ByteArray, format: PubKeyFormat): ByteArray {
|
||||
public override fun pubkeyCreate(seckey: ByteArray): ByteArray {
|
||||
require(seckey.size == 32)
|
||||
memScoped {
|
||||
val nSec = toNat(seckey)
|
||||
val nPubkey = alloc<secp256k1_pubkey>()
|
||||
val result = secp256k1_ec_pubkey_create(ctx, nPubkey.ptr, nSec)
|
||||
if (result == 0) return ByteArray(0)
|
||||
return serializePubkey(nPubkey, format.maxSize)
|
||||
secp256k1_ec_pubkey_create(ctx, nPubkey.ptr, nSec).requireSuccess("secp256k1_ec_pubkey_create() failed")
|
||||
return serializePubkey(nPubkey)
|
||||
}
|
||||
}
|
||||
|
||||
public override fun parsePubkey(pubkey: ByteArray, format: PubKeyFormat): ByteArray {
|
||||
public override fun pubkeyParse(pubkey: ByteArray): ByteArray {
|
||||
require(pubkey.size == 33 || pubkey.size == 65)
|
||||
memScoped {
|
||||
val nPubkey = allocPublicKey(pubkey)
|
||||
return serializePubkey(nPubkey, format.maxSize)
|
||||
return serializePubkey(nPubkey)
|
||||
}
|
||||
}
|
||||
|
||||
@ -134,7 +122,7 @@ public object Secp256k1Native : Secp256k1 {
|
||||
memScoped {
|
||||
val negated = privkey.copyOf()
|
||||
val negPriv = toNat(negated)
|
||||
secp256k1_ec_privkey_negate(ctx, negPriv).requireSuccess()
|
||||
secp256k1_ec_privkey_negate(ctx, negPriv).requireSuccess("secp256k1_ec_privkey_negate() failed")
|
||||
return negated
|
||||
}
|
||||
}
|
||||
@ -145,7 +133,7 @@ public object Secp256k1Native : Secp256k1 {
|
||||
val multiplied = privkey.copyOf()
|
||||
val natMul = toNat(multiplied)
|
||||
val natTweak = toNat(tweak)
|
||||
secp256k1_ec_privkey_tweak_mul(ctx, natMul, natTweak).requireSuccess()
|
||||
secp256k1_ec_privkey_tweak_mul(ctx, natMul, natTweak).requireSuccess("secp256k1_ec_privkey_tweak_mul() failed")
|
||||
return multiplied
|
||||
}
|
||||
}
|
||||
@ -156,7 +144,7 @@ public object Secp256k1Native : Secp256k1 {
|
||||
val added = privkey.copyOf()
|
||||
val natAdd = toNat(added)
|
||||
val natTweak = toNat(tweak)
|
||||
secp256k1_ec_privkey_tweak_add(ctx, natAdd, natTweak).requireSuccess()
|
||||
secp256k1_ec_privkey_tweak_add(ctx, natAdd, natTweak).requireSuccess("secp256k1_ec_privkey_tweak_add() failed")
|
||||
return added
|
||||
}
|
||||
}
|
||||
@ -165,8 +153,8 @@ public object Secp256k1Native : Secp256k1 {
|
||||
require(pubkey.size == 33 || pubkey.size == 65)
|
||||
memScoped {
|
||||
val nPubkey = allocPublicKey(pubkey)
|
||||
secp256k1_ec_pubkey_negate(ctx, nPubkey.ptr).requireSuccess()
|
||||
return serializePubkey(nPubkey, pubkey.size)
|
||||
secp256k1_ec_pubkey_negate(ctx, nPubkey.ptr).requireSuccess("secp256k1_ec_pubkey_negate() failed")
|
||||
return serializePubkey(nPubkey)
|
||||
}
|
||||
}
|
||||
|
||||
@ -175,8 +163,8 @@ public object Secp256k1Native : Secp256k1 {
|
||||
memScoped {
|
||||
val nPubkey = allocPublicKey(pubkey)
|
||||
val nTweak = toNat(tweak)
|
||||
secp256k1_ec_pubkey_tweak_add(ctx, nPubkey.ptr, nTweak).requireSuccess()
|
||||
return serializePubkey(nPubkey, pubkey.size)
|
||||
secp256k1_ec_pubkey_tweak_add(ctx, nPubkey.ptr, nTweak).requireSuccess("secp256k1_ec_pubkey_tweak_add() failed")
|
||||
return serializePubkey(nPubkey)
|
||||
}
|
||||
}
|
||||
|
||||
@ -185,8 +173,8 @@ public object Secp256k1Native : Secp256k1 {
|
||||
memScoped {
|
||||
val nPubkey = allocPublicKey(pubkey)
|
||||
val nTweak = toNat(tweak)
|
||||
secp256k1_ec_pubkey_tweak_mul(ctx, nPubkey.ptr, nTweak).requireSuccess()
|
||||
return serializePubkey(nPubkey, pubkey.size)
|
||||
secp256k1_ec_pubkey_tweak_mul(ctx, nPubkey.ptr, nTweak).requireSuccess("secp256k1_ec_pubkey_tweak_mul() failed")
|
||||
return serializePubkey(nPubkey)
|
||||
}
|
||||
}
|
||||
|
||||
@ -197,42 +185,34 @@ public object Secp256k1Native : Secp256k1 {
|
||||
val nPubkey1 = allocPublicKey(pubkey1)
|
||||
val nPubkey2 = allocPublicKey(pubkey2)
|
||||
val combined = alloc<secp256k1_pubkey>()
|
||||
secp256k1_ec_pubkey_combine(ctx, combined.ptr, cValuesOf(nPubkey1.ptr, nPubkey2.ptr), 2.convert()).requireSuccess()
|
||||
return serializePubkey(combined, pubkey1.size)
|
||||
secp256k1_ec_pubkey_combine(ctx, combined.ptr, cValuesOf(nPubkey1.ptr, nPubkey2.ptr), 2.convert()).requireSuccess("secp256k1_ec_pubkey_combine() failed")
|
||||
return serializePubkey(combined)
|
||||
}
|
||||
}
|
||||
|
||||
public override fun createECDHSecret(seckey: ByteArray, pubkey: ByteArray): ByteArray {
|
||||
public override fun ecdh(seckey: ByteArray, pubkey: ByteArray): ByteArray {
|
||||
require(seckey.size == 32)
|
||||
require(pubkey.size == 33 || pubkey.size == 65)
|
||||
memScoped {
|
||||
val nPubkey = allocPublicKey(pubkey)
|
||||
val nSeckey = toNat(seckey)
|
||||
val output = allocArray<UByteVar>(32)
|
||||
secp256k1_ecdh(ctx, output, nPubkey.ptr, nSeckey, null, null).requireSuccess()
|
||||
secp256k1_ecdh(ctx, output, nPubkey.ptr, nSeckey, null, null).requireSuccess("secp256k1_ecdh() failed")
|
||||
return output.readBytes(32)
|
||||
}
|
||||
}
|
||||
|
||||
public override fun ecdsaRecover(sig: ByteArray, message: ByteArray, recid: Int, format: PubKeyFormat): ByteArray {
|
||||
public override fun ecdsaRecover(sig: ByteArray, message: ByteArray, recid: Int): ByteArray {
|
||||
require(sig.size == 64)
|
||||
require(message.size == 32)
|
||||
memScoped {
|
||||
val nSig = toNat(sig)
|
||||
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(ctx, rSig.ptr, nSig, recid).requireSuccess("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()
|
||||
return serializePubkey(pubkey, format.maxSize)
|
||||
}
|
||||
}
|
||||
|
||||
public override fun randomize(seed: ByteArray): Boolean {
|
||||
require(seed.size == 32)
|
||||
memScoped {
|
||||
val nSeed = toNat(seed)
|
||||
return secp256k1_context_randomize(ctx, nSeed) == 1
|
||||
secp256k1_ecdsa_recover(ctx, pubkey.ptr, rSig.ptr, nMessage).requireSuccess("secp256k1_ecdsa_recover() failed")
|
||||
return serializePubkey(pubkey)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,6 @@
|
||||
package fr.acinq.secp256k1
|
||||
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertFalse
|
||||
import kotlin.test.assertTrue
|
||||
import kotlin.test.*
|
||||
|
||||
|
||||
/**
|
||||
@ -11,67 +8,50 @@ import kotlin.test.assertTrue
|
||||
*/
|
||||
class Secp256k1Test {
|
||||
//TODO improve comments/add more tests
|
||||
/**
|
||||
* This tests verify() for a valid signature
|
||||
*/
|
||||
|
||||
@Test
|
||||
fun testVerifyPos() {
|
||||
var result: Boolean
|
||||
val data: ByteArray = Hex.decode("CF80CD8AED482D5D1527D7DC72FCEFF84E6326592848447D2DC0B0E87DFC9A90".toLowerCase()) //sha256hash of "testing"
|
||||
val sig: ByteArray = Hex.decode("3044022079BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F817980220294F14E883B3F525B5367756C2A11EF6CF84B730B36C17CB0C56F0AAB2C98589".toLowerCase())
|
||||
val pub: ByteArray = Hex.decode("040A629506E1B65CD9D2E0BA9C75DF9C4FED0DB16DC9625ED14397F0AFC836FAE595DC53F8B0EFE61E703075BD9B143BAC75EC0E19F82A2208CAEB32BE53414C40".toLowerCase())
|
||||
result = Secp256k1.verify(data, sig, pub)
|
||||
result = Secp256k1.verify(sig, data, pub)
|
||||
assertTrue(result, "testVerifyPos")
|
||||
val sigCompact: ByteArray = Hex.decode("79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798294F14E883B3F525B5367756C2A11EF6CF84B730B36C17CB0C56F0AAB2C98589".toLowerCase())
|
||||
result = Secp256k1.verify(data, sigCompact, pub)
|
||||
result = Secp256k1.verify(sigCompact, data, pub)
|
||||
assertTrue(result, "testVerifyPos")
|
||||
}
|
||||
|
||||
/**
|
||||
* This tests verify() for a non-valid signature
|
||||
*/
|
||||
@Test
|
||||
fun testVerifyNeg() {
|
||||
var result: Boolean
|
||||
val data: ByteArray = Hex.decode("CF80CD8AED482D5D1527D7DC72FCEFF84E6326592848447D2DC0B0E87DFC9A91".toLowerCase()) //sha256hash of "testing"
|
||||
val sig: ByteArray = Hex.decode("3044022079BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F817980220294F14E883B3F525B5367756C2A11EF6CF84B730B36C17CB0C56F0AAB2C98589".toLowerCase())
|
||||
val pub: ByteArray = Hex.decode("040A629506E1B65CD9D2E0BA9C75DF9C4FED0DB16DC9625ED14397F0AFC836FAE595DC53F8B0EFE61E703075BD9B143BAC75EC0E19F82A2208CAEB32BE53414C40".toLowerCase())
|
||||
result = Secp256k1.verify(data, sig, pub)
|
||||
//System.out.println(" TEST " + new BigInteger(1, resultbytes).toString(16));
|
||||
result = Secp256k1.verify(sig, data, pub)
|
||||
assertFalse(result, "testVerifyNeg")
|
||||
}
|
||||
|
||||
/**
|
||||
* This tests secret key verify() for a valid secretkey
|
||||
*/
|
||||
@Test
|
||||
fun testSecKeyVerifyPos() {
|
||||
var result: Boolean
|
||||
val sec: ByteArray = Hex.decode("67E56582298859DDAE725F972992A07C6C4FB9F62A8FFF58CE3CA926A1063530".toLowerCase())
|
||||
result = Secp256k1.secKeyVerify(sec)
|
||||
//System.out.println(" TEST " + new BigInteger(1, resultbytes).toString(16));
|
||||
assertTrue(result, "testSecKeyVerifyPos")
|
||||
}
|
||||
|
||||
/**
|
||||
* This tests secret key verify() for an invalid secretkey
|
||||
*/
|
||||
@Test
|
||||
fun testSecKeyVerifyNeg() {
|
||||
var result: Boolean
|
||||
val sec: ByteArray = Hex.decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF".toLowerCase())
|
||||
result = Secp256k1.secKeyVerify(sec)
|
||||
//System.out.println(" TEST " + new BigInteger(1, resultbytes).toString(16));
|
||||
assertFalse(result, "testSecKeyVerifyNeg")
|
||||
}
|
||||
|
||||
/**
|
||||
* This tests public key create() for a valid secretkey
|
||||
*/
|
||||
@Test
|
||||
fun testPubKeyCreatePos() {
|
||||
val sec: ByteArray = Hex.decode("67E56582298859DDAE725F972992A07C6C4FB9F62A8FFF58CE3CA926A1063530".toLowerCase())
|
||||
val resultArr: ByteArray = Secp256k1.computePubkey(sec, PubKeyFormat.UNCOMPRESSED)
|
||||
val resultArr: ByteArray = Secp256k1.pubkeyCreate(sec)
|
||||
val pubkeyString: String = Hex.encode(resultArr).toUpperCase()
|
||||
assertEquals(
|
||||
"04C591A8FF19AC9C4E4E5793673B83123437E975285E7B442F4EE2654DFFCA5E2D2103ED494718C697AC9AEBCFD19612E224DB46661011863ED2FC54E71861E2A6",
|
||||
@ -80,21 +60,25 @@ class Secp256k1Test {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* This tests public key create() for a invalid secretkey
|
||||
*/
|
||||
@Test
|
||||
fun testPubKeyCreateNeg() {
|
||||
val sec: ByteArray = Hex.decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF".toLowerCase())
|
||||
val resultArr: ByteArray = Secp256k1.computePubkey(sec, PubKeyFormat.UNCOMPRESSED)
|
||||
val pubkeyString: String = Hex.encode(resultArr).toUpperCase()
|
||||
assertEquals("", pubkeyString, "testPubKeyCreateNeg")
|
||||
assertFailsWith<Secp256k1Exception> {
|
||||
Secp256k1.pubkeyCreate(sec)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testPubkeyCompress() {
|
||||
val pub = Hex.decode("04C591A8FF19AC9C4E4E5793673B83123437E975285E7B442F4EE2654DFFCA5E2D2103ED494718C697AC9AEBCFD19612E224DB46661011863ED2FC54E71861E2A6")
|
||||
val compressed = Secp256k1.pubKeyCompress(pub)
|
||||
assertEquals("02C591A8FF19AC9C4E4E5793673B83123437E975285E7B442F4EE2654DFFCA5E2D", Hex.encode(compressed).toUpperCase())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testPubKeyNegatePos() {
|
||||
val sec: ByteArray = Hex.decode("67E56582298859DDAE725F972992A07C6C4FB9F62A8FFF58CE3CA926A1063530".toLowerCase())
|
||||
val pubkey: ByteArray = Secp256k1.computePubkey(sec, PubKeyFormat.UNCOMPRESSED)
|
||||
val pubkey: ByteArray = Secp256k1.pubkeyCreate(sec)
|
||||
val pubkeyString: String = Hex.encode(pubkey).toUpperCase()
|
||||
assertEquals(
|
||||
"04C591A8FF19AC9C4E4E5793673B83123437E975285E7B442F4EE2654DFFCA5E2D2103ED494718C697AC9AEBCFD19612E224DB46661011863ED2FC54E71861E2A6",
|
||||
@ -110,13 +94,10 @@ class Secp256k1Test {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* This tests public key create() for a valid secretkey
|
||||
*/
|
||||
@Test
|
||||
fun testPubKeyParse() {
|
||||
val pub: ByteArray = Hex.decode("02C591A8FF19AC9C4E4E5793673B83123437E975285E7B442F4EE2654DFFCA5E2D".toLowerCase())
|
||||
val resultArr: ByteArray = Secp256k1.parsePubkey(pub, PubKeyFormat.UNCOMPRESSED)
|
||||
val resultArr: ByteArray = Secp256k1.pubkeyParse(pub)
|
||||
val pubkeyString: String = Hex.encode(resultArr).toUpperCase()
|
||||
assertEquals(
|
||||
"04C591A8FF19AC9C4E4E5793673B83123437E975285E7B442F4EE2654DFFCA5E2D2103ED494718C697AC9AEBCFD19612E224DB46661011863ED2FC54E71861E2A6",
|
||||
@ -138,17 +119,14 @@ class Secp256k1Test {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* This tests sign() for a valid secretkey
|
||||
*/
|
||||
@Test
|
||||
fun testSignPos() {
|
||||
val data: ByteArray = Hex.decode("CF80CD8AED482D5D1527D7DC72FCEFF84E6326592848447D2DC0B0E87DFC9A90".toLowerCase()) //sha256hash of "testing"
|
||||
val sec: ByteArray = Hex.decode("67E56582298859DDAE725F972992A07C6C4FB9F62A8FFF58CE3CA926A1063530".toLowerCase())
|
||||
val resultArr: ByteArray = Secp256k1.sign(data, sec, SigFormat.DER)
|
||||
val resultArr: ByteArray = Secp256k1.sign(data, sec)
|
||||
val sigString: String = Hex.encode(resultArr).toUpperCase()
|
||||
assertEquals(
|
||||
"30440220182A108E1448DC8F1FB467D06A0F3BB8EA0533584CB954EF8DA112F1D60E39A202201C66F36DA211C087F3AF88B50EDF4F9BDAA6CF5FD6817E74DCA34DB12390C6E9",
|
||||
"182A108E1448DC8F1FB467D06A0F3BB8EA0533584CB954EF8DA112F1D60E39A21C66F36DA211C087F3AF88B50EDF4F9BDAA6CF5FD6817E74DCA34DB12390C6E9",
|
||||
sigString,
|
||||
"testSignPos"
|
||||
)
|
||||
@ -157,7 +135,7 @@ class Secp256k1Test {
|
||||
@Test
|
||||
fun testSignatureNormalize() {
|
||||
val data: ByteArray = Hex.decode("30440220182A108E1448DC8F1FB467D06A0F3BB8EA0533584CB954EF8DA112F1D60E39A202201C66F36DA211C087F3AF88B50EDF4F9BDAA6CF5FD6817E74DCA34DB12390C6E9".toLowerCase())
|
||||
val (resultArr, isHighS) = Secp256k1.signatureNormalize(data, SigFormat.COMPACT)
|
||||
val (resultArr, isHighS) = Secp256k1.signatureNormalize(data)
|
||||
val sigString: String = Hex.encode(resultArr).toUpperCase()
|
||||
assertEquals(
|
||||
"182A108E1448DC8F1FB467D06A0F3BB8EA0533584CB954EF8DA112F1D60E39A21C66F36DA211C087F3AF88B50EDF4F9BDAA6CF5FD6817E74DCA34DB12390C6E9",
|
||||
@ -167,30 +145,26 @@ class Secp256k1Test {
|
||||
assertFalse(isHighS, "isHighS")
|
||||
}
|
||||
|
||||
/**
|
||||
* This tests sign() for a invalid secretkey
|
||||
*/
|
||||
@Test
|
||||
fun testSignNeg() {
|
||||
val data: ByteArray = Hex.decode("CF80CD8AED482D5D1527D7DC72FCEFF84E6326592848447D2DC0B0E87DFC9A90".toLowerCase()) //sha256hash of "testing"
|
||||
val sec: ByteArray = Hex.decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF".toLowerCase())
|
||||
val resultArr: ByteArray = Secp256k1.sign(data, sec, SigFormat.DER)
|
||||
val sigString: String = Hex.encode(resultArr)
|
||||
assertEquals("", sigString, "testSignNeg")
|
||||
assertFailsWith<Secp256k1Exception> {
|
||||
Secp256k1.sign(data, sec)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testSignCompactPos() {
|
||||
val data: ByteArray = Hex.decode("CF80CD8AED482D5D1527D7DC72FCEFF84E6326592848447D2DC0B0E87DFC9A90".toLowerCase()) //sha256hash of "testing"
|
||||
val sec: ByteArray = Hex.decode("67E56582298859DDAE725F972992A07C6C4FB9F62A8FFF58CE3CA926A1063530".toLowerCase())
|
||||
val resultArr: ByteArray = Secp256k1.sign(data, sec, SigFormat.COMPACT)
|
||||
val resultArr: ByteArray = Secp256k1.sign(data, sec)
|
||||
val sigString: String = Hex.encode(resultArr).toUpperCase()
|
||||
assertEquals(
|
||||
"182A108E1448DC8F1FB467D06A0F3BB8EA0533584CB954EF8DA112F1D60E39A21C66F36DA211C087F3AF88B50EDF4F9BDAA6CF5FD6817E74DCA34DB12390C6E9",
|
||||
sigString,
|
||||
"testSignCompactPos"
|
||||
)
|
||||
//assertEquals( sigString, "30 44 02 20 182A108E1448DC8F1FB467D06A0F3BB8EA0533584CB954EF8DA112F1D60E39A2 02 20 1C66F36DA211C087F3AF88B50EDF4F9BDAA6CF5FD6817E74DCA34DB12390C6E9" , "testSignPos");
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -206,9 +180,6 @@ class Secp256k1Test {
|
||||
assertTrue(sec.contentEquals(sec2))
|
||||
}
|
||||
|
||||
/**
|
||||
* This tests private key tweak-add
|
||||
*/
|
||||
@Test
|
||||
fun testPrivKeyTweakAdd_1() {
|
||||
val sec: ByteArray = Hex.decode("67E56582298859DDAE725F972992A07C6C4FB9F62A8FFF58CE3CA926A1063530".toLowerCase())
|
||||
@ -222,9 +193,6 @@ class Secp256k1Test {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* This tests private key tweak-mul
|
||||
*/
|
||||
@Test
|
||||
fun testPrivKeyTweakMul_1() {
|
||||
val sec: ByteArray = Hex.decode("67E56582298859DDAE725F972992A07C6C4FB9F62A8FFF58CE3CA926A1063530".toLowerCase())
|
||||
@ -238,9 +206,6 @@ class Secp256k1Test {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* This tests private key tweak-add uncompressed
|
||||
*/
|
||||
@Test
|
||||
fun testPrivKeyTweakAdd_2() {
|
||||
val pub: ByteArray = Hex.decode("040A629506E1B65CD9D2E0BA9C75DF9C4FED0DB16DC9625ED14397F0AFC836FAE595DC53F8B0EFE61E703075BD9B143BAC75EC0E19F82A2208CAEB32BE53414C40".toLowerCase())
|
||||
@ -254,9 +219,6 @@ class Secp256k1Test {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* This tests private key tweak-mul uncompressed
|
||||
*/
|
||||
@Test
|
||||
fun testPrivKeyTweakMul_2() {
|
||||
val pub: ByteArray = Hex.decode("040A629506E1B65CD9D2E0BA9C75DF9C4FED0DB16DC9625ED14397F0AFC836FAE595DC53F8B0EFE61E703075BD9B143BAC75EC0E19F82A2208CAEB32BE53414C40".toLowerCase())
|
||||
@ -270,21 +232,11 @@ class Secp256k1Test {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* This tests seed randomization
|
||||
*/
|
||||
@Test
|
||||
fun testRandomize() {
|
||||
val seed: ByteArray = Hex.decode("A441B15FE9A3CF56661190A0B93B9DEC7D04127288CC87250967CF3B52894D11".toLowerCase()) //sha256hash of "random"
|
||||
val result: Boolean = Secp256k1.randomize(seed)
|
||||
assertTrue(result, "testRandomize")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testCreateECDHSecret() {
|
||||
val sec: ByteArray = Hex.decode("67E56582298859DDAE725F972992A07C6C4FB9F62A8FFF58CE3CA926A1063530".toLowerCase())
|
||||
val pub: ByteArray = Hex.decode("040A629506E1B65CD9D2E0BA9C75DF9C4FED0DB16DC9625ED14397F0AFC836FAE595DC53F8B0EFE61E703075BD9B143BAC75EC0E19F82A2208CAEB32BE53414C40".toLowerCase())
|
||||
val resultArr: ByteArray = Secp256k1.createECDHSecret(sec, pub)
|
||||
val resultArr: ByteArray = Secp256k1.ecdh(sec, pub)
|
||||
val ecdhString: String = Hex.encode(resultArr).toUpperCase()
|
||||
assertEquals(
|
||||
"2A2A67007A926E6594AF3EB564FC74005B37A9C8AEF2033C4552051B5C87F043",
|
||||
@ -297,10 +249,10 @@ class Secp256k1Test {
|
||||
fun testEcdsaRecover() {
|
||||
val data: ByteArray = Hex.decode("CF80CD8AED482D5D1527D7DC72FCEFF84E6326592848447D2DC0B0E87DFC9A90".toLowerCase()) //sha256hash of "testing"
|
||||
val sec: ByteArray = Hex.decode("67E56582298859DDAE725F972992A07C6C4FB9F62A8FFF58CE3CA926A1063530".toLowerCase())
|
||||
val pub: ByteArray = Secp256k1.computePubkey(sec, PubKeyFormat.UNCOMPRESSED)
|
||||
val sig: ByteArray = Secp256k1.sign(data, sec, SigFormat.COMPACT)
|
||||
val pub0: ByteArray = Secp256k1.ecdsaRecover(sig, data, 0, PubKeyFormat.UNCOMPRESSED)
|
||||
val pub1: ByteArray = Secp256k1.ecdsaRecover(sig, data, 1, PubKeyFormat.UNCOMPRESSED)
|
||||
val pub: ByteArray = Secp256k1.pubkeyCreate(sec)
|
||||
val sig: ByteArray = Secp256k1.sign(data, sec)
|
||||
val pub0: ByteArray = Secp256k1.ecdsaRecover(sig, data, 0)
|
||||
val pub1: ByteArray = Secp256k1.ecdsaRecover(sig, data, 1)
|
||||
assertTrue(pub.contentEquals(pub0) || pub.contentEquals(pub1), "testEcdsaRecover")
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user