diff --git a/contrib/devtools/copyright_header.py b/contrib/devtools/copyright_header.py --- a/contrib/devtools/copyright_header.py +++ b/contrib/devtools/copyright_header.py @@ -23,8 +23,6 @@ 'src/secp256k1/include/secp256k1_schnorr.h', 'src/secp256k1/src/java/org_bitcoin_NativeSecp256k1.c', 'src/secp256k1/src/java/org_bitcoin_NativeSecp256k1.h', - 'src/secp256k1/src/java/org_bitcoin_Secp256k1Context.c', - 'src/secp256k1/src/java/org_bitcoin_Secp256k1Context.h', # auto generated: 'src/univalue/lib/univalue_escapes.h', 'src/qt/bitcoinstrings.cpp', diff --git a/src/secp256k1/CMakeLists.txt b/src/secp256k1/CMakeLists.txt --- a/src/secp256k1/CMakeLists.txt +++ b/src/secp256k1/CMakeLists.txt @@ -283,7 +283,6 @@ add_library(secp256k1_jni SHARED src/java/org_bitcoin_NativeSecp256k1.c - src/java/org_bitcoin_Secp256k1Context.c ) install_shared_library(secp256k1_jni) @@ -328,7 +327,6 @@ src/java/org/bitcoin/NativeSecp256k1.java src/java/org/bitcoin/NativeSecp256k1Test.java src/java/org/bitcoin/NativeSecp256k1Util.java - src/java/org/bitcoin/Secp256k1Context.java ENTRY_POINT org/bitcoin/NativeSecp256k1Test OUTPUT_NAME "${SECP256k1_JNI_TEST_JAR}" ) diff --git a/src/secp256k1/Makefile.am b/src/secp256k1/Makefile.am --- a/src/secp256k1/Makefile.am +++ b/src/secp256k1/Makefile.am @@ -39,7 +39,6 @@ noinst_HEADERS += src/field_5x52_int128_impl.h noinst_HEADERS += src/field_5x52_asm_impl.h noinst_HEADERS += src/java/org_bitcoin_NativeSecp256k1.h -noinst_HEADERS += src/java/org_bitcoin_Secp256k1Context.h noinst_HEADERS += src/util.h noinst_HEADERS += src/scratch.h noinst_HEADERS += src/scratch_impl.h @@ -75,7 +74,7 @@ libsecp256k1_la_CPPFLAGS = -DSECP256K1_BUILD -I$(top_srcdir)/include -I$(top_srcdir)/src $(SECP_INCLUDES) libsecp256k1_la_LIBADD = $(SECP_LIBS) $(COMMON_LIB) -libsecp256k1_jni_la_SOURCES = src/java/org_bitcoin_NativeSecp256k1.c src/java/org_bitcoin_Secp256k1Context.c +libsecp256k1_jni_la_SOURCES = src/java/org_bitcoin_NativeSecp256k1.c libsecp256k1_jni_la_CPPFLAGS = -DSECP256K1_BUILD $(JNI_INCLUDES) libsecp256k1_jni_la_LIBADD = $(SECP256K1_LIB) @@ -127,8 +126,7 @@ JAVA_FILES= \ $(JAVA_SRC)/NativeSecp256k1.java \ $(JAVA_SRC)/NativeSecp256k1Test.java \ - $(JAVA_SRC)/NativeSecp256k1Util.java \ - $(JAVA_SRC)/Secp256k1Context.java + $(JAVA_SRC)/NativeSecp256k1Util.java if USE_JNI diff --git a/src/secp256k1/src/java/org/bitcoin/NativeSecp256k1.java b/src/secp256k1/src/java/org/bitcoin/NativeSecp256k1.java --- a/src/secp256k1/src/java/org/bitcoin/NativeSecp256k1.java +++ b/src/secp256k1/src/java/org/bitcoin/NativeSecp256k1.java @@ -38,10 +38,39 @@ */ public class NativeSecp256k1 { - private static final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock(); - private static final Lock r = rwl.readLock(); - private static final Lock w = rwl.writeLock(); - private static ThreadLocal nativeByteBuffer = new ThreadLocal(); + private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock(); + private final Lock r = rwl.readLock(); + private final Lock w = rwl.writeLock(); + private ThreadLocal nativeByteBuffer = new ThreadLocal(); + private long context; + + private static final boolean enabled; + + static { //static initializer + boolean isEnabled = true; + try { + System.loadLibrary("secp256k1_jni"); + } catch (UnsatisfiedLinkError e) { + System.out.println("UnsatisfiedLinkError: " + e.toString()); + isEnabled = false; + } + enabled = isEnabled; + } + + public boolean isEnabled() { + return enabled; + } + + public NativeSecp256k1() throws IllegalArgumentException { + checkArgument(enabled); + context = secp256k1_init_context(); + } + + public long getContext() throws IllegalArgumentException { + checkArgument(context != -1); + return context; + } + /** * Verifies the given secp256k1 signature in native code. * Calling when enabled == false is undefined (probably library not loaded) @@ -50,7 +79,7 @@ * @param signature The signature * @param pub The public key which did the signing */ - public static boolean verify(byte[] data, byte[] signature, byte[] pub) { + public boolean verify(byte[] data, byte[] signature, byte[] pub) { checkArgument(data.length == 32 && signature.length <= 520 && pub.length <= 520); ByteBuffer byteBuff = nativeByteBuffer.get(); @@ -66,7 +95,7 @@ r.lock(); try { - return secp256k1_ecdsa_verify(byteBuff, Secp256k1Context.getContext(), signature.length, pub.length) == 1; + return secp256k1_ecdsa_verify(byteBuff, context, signature.length, pub.length) == 1; } finally { r.unlock(); } @@ -81,7 +110,7 @@ * Return values * @param sig byte array of signature */ - public static byte[] sign(byte[] data, byte[] sec) throws AssertFailException{ + public byte[] sign(byte[] data, byte[] sec) throws AssertFailException{ checkArgument(data.length == 32 && sec.length <= 32); ByteBuffer byteBuff = nativeByteBuffer.get(); @@ -98,7 +127,7 @@ r.lock(); try { - retByteArray = secp256k1_ecdsa_sign(byteBuff, Secp256k1Context.getContext()); + retByteArray = secp256k1_ecdsa_sign(byteBuff, context); } finally { r.unlock(); } @@ -117,7 +146,7 @@ * * @param seckey ECDSA Secret key, 32 bytes */ - public static boolean secKeyVerify(byte[] seckey) { + public boolean secKeyVerify(byte[] seckey) { checkArgument(seckey.length == 32); ByteBuffer byteBuff = nativeByteBuffer.get(); @@ -131,7 +160,7 @@ r.lock(); try { - return secp256k1_ec_seckey_verify(byteBuff,Secp256k1Context.getContext()) == 1; + return secp256k1_ec_seckey_verify(byteBuff, context) == 1; } finally { r.unlock(); } @@ -147,7 +176,7 @@ * @param pubkey ECDSA Public key, 33 or 65 bytes */ //TODO add a 'compressed' arg - public static byte[] computePubkey(byte[] seckey) throws AssertFailException{ + public byte[] computePubkey(byte[] seckey) throws AssertFailException{ checkArgument(seckey.length == 32); ByteBuffer byteBuff = nativeByteBuffer.get(); @@ -163,7 +192,7 @@ r.lock(); try { - retByteArray = secp256k1_ec_pubkey_create(byteBuff, Secp256k1Context.getContext()); + retByteArray = secp256k1_ec_pubkey_create(byteBuff, context); } finally { r.unlock(); } @@ -181,19 +210,20 @@ * libsecp256k1 Cleanup - This destroys the secp256k1 context object * This should be called at the end of the program for proper cleanup of the context. */ - public static synchronized void cleanup() { + public synchronized void cleanup() { w.lock(); try { - secp256k1_destroy_context(Secp256k1Context.getContext()); + secp256k1_destroy_context(context); } finally { w.unlock(); } + context = - 1; } - public static long cloneContext() { + public long cloneContext() { r.lock(); try { - return secp256k1_ctx_clone(Secp256k1Context.getContext()); + return secp256k1_ctx_clone(context); } finally { r.unlock(); } } @@ -203,7 +233,7 @@ * @param tweak some bytes to tweak with * @param seckey 32-byte seckey */ - public static byte[] privKeyTweakMul(byte[] privkey, byte[] tweak) throws AssertFailException{ + public byte[] privKeyTweakMul(byte[] privkey, byte[] tweak) throws AssertFailException{ checkArgument(privkey.length == 32); ByteBuffer byteBuff = nativeByteBuffer.get(); @@ -219,7 +249,7 @@ byte[][] retByteArray; r.lock(); try { - retByteArray = secp256k1_privkey_tweak_mul(byteBuff,Secp256k1Context.getContext()); + retByteArray = secp256k1_privkey_tweak_mul(byteBuff, context); } finally { r.unlock(); } @@ -242,7 +272,7 @@ * @param tweak some bytes to tweak with * @param seckey 32-byte seckey */ - public static byte[] privKeyTweakAdd(byte[] privkey, byte[] tweak) throws AssertFailException{ + public byte[] privKeyTweakAdd(byte[] privkey, byte[] tweak) throws AssertFailException{ checkArgument(privkey.length == 32); ByteBuffer byteBuff = nativeByteBuffer.get(); @@ -258,7 +288,7 @@ byte[][] retByteArray; r.lock(); try { - retByteArray = secp256k1_privkey_tweak_add(byteBuff,Secp256k1Context.getContext()); + retByteArray = secp256k1_privkey_tweak_add(byteBuff, context); } finally { r.unlock(); } @@ -281,7 +311,7 @@ * @param tweak some bytes to tweak with * @param pubkey 32-byte seckey */ - public static byte[] pubKeyTweakAdd(byte[] pubkey, byte[] tweak) throws AssertFailException{ + public byte[] pubKeyTweakAdd(byte[] pubkey, byte[] tweak) throws AssertFailException{ checkArgument(pubkey.length == 33 || pubkey.length == 65); ByteBuffer byteBuff = nativeByteBuffer.get(); @@ -297,7 +327,7 @@ byte[][] retByteArray; r.lock(); try { - retByteArray = secp256k1_pubkey_tweak_add(byteBuff,Secp256k1Context.getContext(), pubkey.length); + retByteArray = secp256k1_pubkey_tweak_add(byteBuff, context, pubkey.length); } finally { r.unlock(); } @@ -320,7 +350,7 @@ * @param tweak some bytes to tweak with * @param pubkey 32-byte seckey */ - public static byte[] pubKeyTweakMul(byte[] pubkey, byte[] tweak) throws AssertFailException{ + public byte[] pubKeyTweakMul(byte[] pubkey, byte[] tweak) throws AssertFailException{ checkArgument(pubkey.length == 33 || pubkey.length == 65); ByteBuffer byteBuff = nativeByteBuffer.get(); @@ -336,7 +366,7 @@ byte[][] retByteArray; r.lock(); try { - retByteArray = secp256k1_pubkey_tweak_mul(byteBuff,Secp256k1Context.getContext(), pubkey.length); + retByteArray = secp256k1_pubkey_tweak_mul(byteBuff, context, pubkey.length); } finally { r.unlock(); } @@ -359,7 +389,7 @@ * @param seckey byte array of secret key used in exponentiaion * @param pubkey byte array of public key used in exponentiaion */ - public static byte[] createECDHSecret(byte[] seckey, byte[] pubkey) throws AssertFailException{ + public byte[] createECDHSecret(byte[] seckey, byte[] pubkey) throws AssertFailException{ checkArgument(seckey.length <= 32 && pubkey.length <= 65); ByteBuffer byteBuff = nativeByteBuffer.get(); @@ -375,7 +405,7 @@ byte[][] retByteArray; r.lock(); try { - retByteArray = secp256k1_ecdh(byteBuff, Secp256k1Context.getContext(), pubkey.length); + retByteArray = secp256k1_ecdh(byteBuff, context, pubkey.length); } finally { r.unlock(); } @@ -394,7 +424,7 @@ * * @param seed 32-byte random seed */ - public static synchronized boolean randomize(byte[] seed) throws AssertFailException{ + public synchronized boolean randomize(byte[] seed) throws AssertFailException{ checkArgument(seed.length == 32 || seed == null); ByteBuffer byteBuff = nativeByteBuffer.get(); @@ -408,7 +438,7 @@ w.lock(); try { - return secp256k1_context_randomize(byteBuff, Secp256k1Context.getContext()) == 1; + return secp256k1_context_randomize(byteBuff, context) == 1; } finally { w.unlock(); } @@ -421,7 +451,7 @@ * @param seckey Secret key, 32 bytes * @return sig byte array of signature */ - public static byte[] schnorrSign(byte[] data, byte[] seckey) throws AssertFailException { + public byte[] schnorrSign(byte[] data, byte[] seckey) throws AssertFailException { checkArgument(data.length == 32 && seckey.length <= 32); ByteBuffer byteBuff = nativeByteBuffer.get(); @@ -438,7 +468,7 @@ r.lock(); try { - retByteArray = secp256k1_schnorr_sign(byteBuff, Secp256k1Context.getContext()); + retByteArray = secp256k1_schnorr_sign(byteBuff, context); } finally { r.unlock(); } @@ -459,7 +489,7 @@ * @param signature The signature is exactly 64 bytes * @param pub The public key which did the signing which is the same ECDSA */ - public static boolean schnorrVerify(byte[] data, byte[] signature, byte[] pub) { + public boolean schnorrVerify(byte[] data, byte[] signature, byte[] pub) { checkArgument(data.length == 32 && signature.length == 64 && (pub.length == 33 || pub.length == 65)); ByteBuffer byteBuff = nativeByteBuffer.get(); @@ -475,7 +505,7 @@ r.lock(); try { - return secp256k1_schnorr_verify(byteBuff, Secp256k1Context.getContext(), pub.length) == 1; + return secp256k1_schnorr_verify(byteBuff, context, pub.length) == 1; } finally { r.unlock(); } @@ -495,6 +525,8 @@ private static native void secp256k1_destroy_context(long context); + private static native long secp256k1_init_context(); + private static native int secp256k1_ecdsa_verify(ByteBuffer byteBuff, long context, int sigLen, int pubLen); private static native byte[][] secp256k1_ecdsa_sign(ByteBuffer byteBuff, long context); diff --git a/src/secp256k1/src/java/org/bitcoin/NativeSecp256k1Test.java b/src/secp256k1/src/java/org/bitcoin/NativeSecp256k1Test.java --- a/src/secp256k1/src/java/org/bitcoin/NativeSecp256k1Test.java +++ b/src/secp256k1/src/java/org/bitcoin/NativeSecp256k1Test.java @@ -26,12 +26,12 @@ return stringBuilder.toString(); } - //TODO improve comments/add more tests + NativeSecp256k1 nativeSecp256k1 = new NativeSecp256k1(); /** * This tests verify() for a valid signature. */ - public static void testVerifyPos() throws AssertFailException{ + public void testVerifyPos() throws AssertFailException{ boolean result = false; // sha256hash of "testing" @@ -39,14 +39,14 @@ byte[] sig = hexStringToByteArray("3044022079BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F817980220294F14E883B3F525B5367756C2A11EF6CF84B730B36C17CB0C56F0AAB2C98589"); byte[] pub = hexStringToByteArray("040A629506E1B65CD9D2E0BA9C75DF9C4FED0DB16DC9625ED14397F0AFC836FAE595DC53F8B0EFE61E703075BD9B143BAC75EC0E19F82A2208CAEB32BE53414C40"); - result = NativeSecp256k1.verify(data, sig, pub); + result = nativeSecp256k1.verify(data, sig, pub); assertEquals(result, true, "testVerifyPos"); } /** * This tests verify() for a non-valid signature. */ - public static void testVerifyNeg() throws AssertFailException{ + public void testVerifyNeg() throws AssertFailException{ boolean result = false; // sha256hash of "testing" @@ -54,41 +54,41 @@ byte[] sig = hexStringToByteArray("3044022079BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F817980220294F14E883B3F525B5367756C2A11EF6CF84B730B36C17CB0C56F0AAB2C98589"); byte[] pub = hexStringToByteArray("040A629506E1B65CD9D2E0BA9C75DF9C4FED0DB16DC9625ED14397F0AFC836FAE595DC53F8B0EFE61E703075BD9B143BAC75EC0E19F82A2208CAEB32BE53414C40"); - result = NativeSecp256k1.verify(data, sig, pub); + result = nativeSecp256k1.verify(data, sig, pub); assertEquals(result, false, "testVerifyNeg"); } /** * This tests secret key verify() for a valid secretkey. */ - public static void testSecKeyVerifyPos() throws AssertFailException{ + public void testSecKeyVerifyPos() throws AssertFailException{ boolean result = false; byte[] sec = hexStringToByteArray("67E56582298859DDAE725F972992A07C6C4FB9F62A8FFF58CE3CA926A1063530"); - result = NativeSecp256k1.secKeyVerify(sec); + result = nativeSecp256k1.secKeyVerify(sec); assertEquals(result, true, "testSecKeyVerifyPos"); } /** * This tests secret key verify() for an invalid secretkey. */ - public static void testSecKeyVerifyNeg() throws AssertFailException{ + public void testSecKeyVerifyNeg() throws AssertFailException{ boolean result = false; byte[] sec = hexStringToByteArray("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"); - result = NativeSecp256k1.secKeyVerify(sec); + result = nativeSecp256k1.secKeyVerify(sec); assertEquals(result, false, "testSecKeyVerifyNeg"); } /** * This tests public key create() for a valid secretkey. */ - public static void testPubKeyCreatePos() throws AssertFailException{ + public void testPubKeyCreatePos() throws AssertFailException{ byte[] sec = hexStringToByteArray("67E56582298859DDAE725F972992A07C6C4FB9F62A8FFF58CE3CA926A1063530"); - byte[] resultArr = NativeSecp256k1.computePubkey(sec); + byte[] resultArr = nativeSecp256k1.computePubkey(sec); String pubkeyString = byteArrayToHexString(resultArr); assertEquals(pubkeyString, "04C591A8FF19AC9C4E4E5793673B83123437E975285E7B442F4EE2654DFFCA5E2D2103ED494718C697AC9AEBCFD19612E224DB46661011863ED2FC54E71861E2A6", "testPubKeyCreatePos"); } @@ -96,10 +96,10 @@ /** * This tests public key create() for a invalid secretkey. */ - public static void testPubKeyCreateNeg() throws AssertFailException{ + public void testPubKeyCreateNeg() throws AssertFailException{ byte[] sec = hexStringToByteArray("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"); - byte[] resultArr = NativeSecp256k1.computePubkey(sec); + byte[] resultArr = nativeSecp256k1.computePubkey(sec); String pubkeyString = byteArrayToHexString(resultArr); assertEquals(pubkeyString, "", "testPubKeyCreateNeg"); } @@ -107,12 +107,12 @@ /** * This tests sign() for a valid secretkey. */ - public static void testSignPos() throws AssertFailException{ + public void testSignPos() throws AssertFailException{ // sha256hash of "testing" byte[] data = hexStringToByteArray("CF80CD8AED482D5D1527D7DC72FCEFF84E6326592848447D2DC0B0E87DFC9A90"); byte[] sec = hexStringToByteArray("67E56582298859DDAE725F972992A07C6C4FB9F62A8FFF58CE3CA926A1063530"); - byte[] resultArr = NativeSecp256k1.sign(data, sec); + byte[] resultArr = nativeSecp256k1.sign(data, sec); String sigString = byteArrayToHexString(resultArr); assertEquals(sigString, "3045022100F51D069AA46EDB4E2E77773FE364AA2AF6818AF733EA542CFC4D546640A58D8802204F1C442AC9F26F232451A0C3EE99F6875353FC73902C68055C19E31624F687CC", "testSignPos"); } @@ -120,12 +120,12 @@ /** * This tests sign() for a invalid secretkey. */ - public static void testSignNeg() throws AssertFailException{ + public void testSignNeg() throws AssertFailException{ // sha256hash of "testing" byte[] data = hexStringToByteArray("CF80CD8AED482D5D1527D7DC72FCEFF84E6326592848447D2DC0B0E87DFC9A90"); byte[] sec = hexStringToByteArray("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"); - byte[] resultArr = NativeSecp256k1.sign(data, sec); + byte[] resultArr = nativeSecp256k1.sign(data, sec); String sigString = byteArrayToHexString(resultArr); assertEquals(sigString, "", "testSignNeg"); } @@ -133,12 +133,12 @@ /** * This tests private key tweak-add. */ - public static void testPrivKeyTweakAdd_1() throws AssertFailException { + public void testPrivKeyTweakAdd_1() throws AssertFailException { // sha256hash of "tweak" byte[] data = hexStringToByteArray("3982F19BEF1615BCCFBB05E321C10E1D4CBA3DF0E841C2E41EEB6016347653C3"); byte[] sec = hexStringToByteArray("67E56582298859DDAE725F972992A07C6C4FB9F62A8FFF58CE3CA926A1063530"); - byte[] resultArr = NativeSecp256k1.privKeyTweakAdd(sec, data); + byte[] resultArr = nativeSecp256k1.privKeyTweakAdd(sec, data); String sigString = byteArrayToHexString(resultArr); assertEquals(sigString, "A168571E189E6F9A7E2D657A4B53AE99B909F7E712D1C23CED28093CD57C88F3", "testPrivKeyAdd_1"); } @@ -146,12 +146,12 @@ /** * This tests private key tweak-mul. */ - public static void testPrivKeyTweakMul_1() throws AssertFailException { + public void testPrivKeyTweakMul_1() throws AssertFailException { // sha256hash of "tweak" byte[] data = hexStringToByteArray("3982F19BEF1615BCCFBB05E321C10E1D4CBA3DF0E841C2E41EEB6016347653C3"); byte[] sec = hexStringToByteArray("67E56582298859DDAE725F972992A07C6C4FB9F62A8FFF58CE3CA926A1063530"); - byte[] resultArr = NativeSecp256k1.privKeyTweakMul(sec, data); + byte[] resultArr = nativeSecp256k1.privKeyTweakMul(sec, data); String sigString = byteArrayToHexString(resultArr); assertEquals(sigString, "97F8184235F101550F3C71C927507651BD3F1CDB4A5A33B8986ACF0DEE20FFFC", "testPrivKeyMul_1"); } @@ -159,12 +159,12 @@ /** * This tests private key tweak-add uncompressed. */ - public static void testPrivKeyTweakAdd_2() throws AssertFailException { + public void testPrivKeyTweakAdd_2() throws AssertFailException { // sha256hash of "tweak" byte[] data = hexStringToByteArray("3982F19BEF1615BCCFBB05E321C10E1D4CBA3DF0E841C2E41EEB6016347653C3"); byte[] pub = hexStringToByteArray("040A629506E1B65CD9D2E0BA9C75DF9C4FED0DB16DC9625ED14397F0AFC836FAE595DC53F8B0EFE61E703075BD9B143BAC75EC0E19F82A2208CAEB32BE53414C40"); - byte[] resultArr = NativeSecp256k1.pubKeyTweakAdd(pub ,data); + byte[] resultArr = nativeSecp256k1.pubKeyTweakAdd(pub ,data); String sigString = byteArrayToHexString(resultArr); assertEquals(sigString, "0411C6790F4B663CCE607BAAE08C43557EDC1A4D11D88DFCB3D841D0C6A941AF525A268E2A863C148555C48FB5FBA368E88718A46E205FABC3DBA2CCFFAB0796EF", "testPrivKeyAdd_2"); } @@ -172,12 +172,12 @@ /** * This tests private key tweak-mul uncompressed. */ - public static void testPrivKeyTweakMul_2() throws AssertFailException { + public void testPrivKeyTweakMul_2() throws AssertFailException { // sha256hash of "tweak" byte[] data = hexStringToByteArray("3982F19BEF1615BCCFBB05E321C10E1D4CBA3DF0E841C2E41EEB6016347653C3"); byte[] pub = hexStringToByteArray("040A629506E1B65CD9D2E0BA9C75DF9C4FED0DB16DC9625ED14397F0AFC836FAE595DC53F8B0EFE61E703075BD9B143BAC75EC0E19F82A2208CAEB32BE53414C40"); - byte[] resultArr = NativeSecp256k1.pubKeyTweakMul(pub, data); + byte[] resultArr = nativeSecp256k1.pubKeyTweakMul(pub, data); String sigString = byteArrayToHexString(resultArr); assertEquals(sigString, "04E0FE6FE55EBCA626B98A807F6CAF654139E14E5E3698F01A9A658E21DC1D2791EC060D4F412A794D5370F672BC94B722640B5F76914151CFCA6E712CA48CC589", "testPrivKeyMul_2"); } @@ -185,11 +185,11 @@ /** * This tests seed randomization. */ - public static void testRandomize() throws AssertFailException { + public void testRandomize() throws AssertFailException { // sha256hash of "random" byte[] seed = hexStringToByteArray("A441B15FE9A3CF56661190A0B93B9DEC7D04127288CC87250967CF3B52894D11"); - boolean result = NativeSecp256k1.randomize(seed); + boolean result = nativeSecp256k1.randomize(seed); assertEquals(result, true, "testRandomize"); } @@ -214,7 +214,7 @@ * It tests the following test vectors: * https://github.com/sipa/bips/blob/bip-schnorr/bip-schnorr/test-vectors.csv */ - public static void testSchnorrVerify() throws AssertFailException{ + public void testSchnorrVerify() throws AssertFailException{ SchnorrTestVector[] tests = new SchnorrTestVector[]{ new SchnorrTestVector( "0000000000000000000000000000000000000000000000000000000000000000", @@ -335,7 +335,7 @@ byte[] data = hexStringToByteArray(test.data); byte[] sig = hexStringToByteArray(test.sig); byte[] pub = hexStringToByteArray(test.pubKey); - boolean result = NativeSecp256k1.schnorrVerify(data, sig, pub); + boolean result = nativeSecp256k1.schnorrVerify(data, sig, pub); String testMsg = String.join(" ", "testSchnorrVerify", String.valueOf(i++), String.valueOf(expected), test.comment); @@ -346,71 +346,81 @@ /** * This tests signSchnorr() for a valid secretkey. */ - public static void testSchnorrSign() throws AssertFailException{ + public void testSchnorrSign() throws AssertFailException{ // sha256(sha256("Very deterministic message")) byte[] data = hexStringToByteArray("5255683DA567900BFD3E786ED8836A4E7763C221BF1AC20ECE2A5171B9199E8A"); byte[] sec = hexStringToByteArray("12B004FFF7F4B69EF8650E767F18F11EDE158148B425660723B9F9A66E61F747"); - byte[] resultArr = NativeSecp256k1.schnorrSign(data, sec); + byte[] resultArr = nativeSecp256k1.schnorrSign(data, sec); String sigString = byteArrayToHexString(resultArr); assertEquals(sigString, "2C56731AC2F7A7E7F11518FC7722A166B02438924CA9D8B4D111347B81D0717571846DE67AD3D913A8FDF9D8F3F73161A4C48AE81CB183B214765FEB86E255CE", "testSchnorrSign"); } - public static void testCreateECDHSecret() throws AssertFailException{ + public void testCreateECDHSecret() throws AssertFailException{ byte[] sec = hexStringToByteArray("67E56582298859DDAE725F972992A07C6C4FB9F62A8FFF58CE3CA926A1063530"); byte[] pub = hexStringToByteArray("040A629506E1B65CD9D2E0BA9C75DF9C4FED0DB16DC9625ED14397F0AFC836FAE595DC53F8B0EFE61E703075BD9B143BAC75EC0E19F82A2208CAEB32BE53414C40"); - byte[] resultArr = NativeSecp256k1.createECDHSecret(sec, pub); + byte[] resultArr = nativeSecp256k1.createECDHSecret(sec, pub); String ecdhString = byteArrayToHexString(resultArr); assertEquals(ecdhString, "2A2A67007A926E6594AF3EB564FC74005B37A9C8AEF2033C4552051B5C87F043", "testCreateECDHSecret"); } + public void testContexts(NativeSecp256k1 a) throws AssertFailException { + assertEquals(nativeSecp256k1.getContext() != a.getContext(), true, "testContexts"); + } + public static void main(String[] args) throws AssertFailException{ - System.out.println("\nlibsecp256k1 enabled: " + Secp256k1Context.isEnabled() + "\n"); + NativeSecp256k1Test test = new NativeSecp256k1Test(); + + System.out.println("\nlibsecp256k1 enabled: " + test.nativeSecp256k1.isEnabled() + "\n"); + + assertEquals(test.nativeSecp256k1.isEnabled(), true, "isEnabled"); - assertEquals(Secp256k1Context.isEnabled(), true, "isEnabled"); // Test verify() success/fail - testVerifyPos(); - testVerifyNeg(); + test.testVerifyPos(); + test.testVerifyNeg(); // Test secKeyVerify() success/fail - testSecKeyVerifyPos(); - testSecKeyVerifyNeg(); + test.testSecKeyVerifyPos(); + test.testSecKeyVerifyNeg(); // Test computePubkey() success/fail - testPubKeyCreatePos(); - testPubKeyCreateNeg(); + test.testPubKeyCreatePos(); + test.testPubKeyCreateNeg(); // Test sign() success/fail - testSignPos(); - testSignNeg(); + test.testSignPos(); + test.testSignNeg(); // Test privKeyTweakAdd() 1 - testPrivKeyTweakAdd_1(); + test.testPrivKeyTweakAdd_1(); // Test privKeyTweakMul() 2 - testPrivKeyTweakMul_1(); + test.testPrivKeyTweakMul_1(); // Test privKeyTweakAdd() 3 - testPrivKeyTweakAdd_2(); + test.testPrivKeyTweakAdd_2(); // Test privKeyTweakMul() 4 - testPrivKeyTweakMul_2(); + test.testPrivKeyTweakMul_2(); // Test randomize() - testRandomize(); + test.testRandomize(); // Test verifySchnorr() success/fail - testSchnorrVerify(); + test.testSchnorrVerify(); // Test schnorrSign() - testSchnorrSign(); + test.testSchnorrSign(); // Test ECDH - testCreateECDHSecret(); + test.testCreateECDHSecret(); + + // Test Context + test.testContexts(new NativeSecp256k1()); - NativeSecp256k1.cleanup(); + test.nativeSecp256k1.cleanup(); System.out.println("All tests passed."); } diff --git a/src/secp256k1/src/java/org/bitcoin/Secp256k1Context.java b/src/secp256k1/src/java/org/bitcoin/Secp256k1Context.java deleted file mode 100644 --- a/src/secp256k1/src/java/org/bitcoin/Secp256k1Context.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2014-2016 the libsecp256k1 contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.bitcoin; - -/** - * This class holds the context reference used in native methods - * to handle ECDSA operations. - */ -public class Secp256k1Context { - private static final boolean enabled; //true if the library is loaded - private static final long context; //ref to pointer to context obj - - static { //static initializer - boolean isEnabled = true; - long contextRef = -1; - try { - System.loadLibrary("secp256k1_jni"); - contextRef = secp256k1_init_context(); - } catch (UnsatisfiedLinkError e) { - System.out.println("UnsatisfiedLinkError: " + e.toString()); - isEnabled = false; - } - enabled = isEnabled; - context = contextRef; - } - - public static boolean isEnabled() { - return enabled; - } - - public static long getContext() { - if(!enabled) return -1; //sanity check - return context; - } - - private static native long secp256k1_init_context(); -} diff --git a/src/secp256k1/src/java/org_bitcoin_NativeSecp256k1.h b/src/secp256k1/src/java/org_bitcoin_NativeSecp256k1.h --- a/src/secp256k1/src/java/org_bitcoin_NativeSecp256k1.h +++ b/src/secp256k1/src/java/org_bitcoin_NativeSecp256k1.h @@ -1,135 +1,142 @@ -/* DO NOT EDIT THIS FILE - it is machine generated */ -#include -#include "include/secp256k1.h" -/* Header for class org_bitcoin_NativeSecp256k1 */ - -#ifndef _Included_org_bitcoin_NativeSecp256k1 -#define _Included_org_bitcoin_NativeSecp256k1 -#ifdef __cplusplus -extern "C" { -#endif -/* - * Class: org_bitcoin_NativeSecp256k1 - * Method: secp256k1_ctx_clone - * Signature: (J)J - */ -SECP256K1_API jlong JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ctx_1clone - (JNIEnv *, jclass, jlong); - -/* - * Class: org_bitcoin_NativeSecp256k1 - * Method: secp256k1_context_randomize - * Signature: (Ljava/nio/ByteBuffer;J)I - */ -SECP256K1_API jint JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1context_1randomize - (JNIEnv *, jclass, jobject, jlong); - -/* - * Class: org_bitcoin_NativeSecp256k1 - * Method: secp256k1_privkey_tweak_add - * Signature: (Ljava/nio/ByteBuffer;J)[[B - */ -SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1privkey_1tweak_1add - (JNIEnv *, jclass, jobject, jlong); - -/* - * Class: org_bitcoin_NativeSecp256k1 - * Method: secp256k1_privkey_tweak_mul - * Signature: (Ljava/nio/ByteBuffer;J)[[B - */ -SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1privkey_1tweak_1mul - (JNIEnv *, jclass, jobject, jlong); - -/* - * Class: org_bitcoin_NativeSecp256k1 - * Method: secp256k1_pubkey_tweak_add - * Signature: (Ljava/nio/ByteBuffer;JI)[[B - */ -SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1pubkey_1tweak_1add - (JNIEnv *, jclass, jobject, jlong, jint); - -/* - * Class: org_bitcoin_NativeSecp256k1 - * Method: secp256k1_pubkey_tweak_mul - * Signature: (Ljava/nio/ByteBuffer;JI)[[B - */ -SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1pubkey_1tweak_1mul - (JNIEnv *, jclass, jobject, jlong, jint); - -/* - * Class: org_bitcoin_NativeSecp256k1 - * Method: secp256k1_destroy_context - * Signature: (J)V - */ -SECP256K1_API void JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1destroy_1context - (JNIEnv *, jclass, jlong); - -/* - * Class: org_bitcoin_NativeSecp256k1 - * Method: secp256k1_ecdsa_verify - * Signature: (Ljava/nio/ByteBuffer;JII)I - */ -SECP256K1_API jint JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ecdsa_1verify - (JNIEnv *, jclass, jobject, jlong, jint, jint); - -/* - * Class: org_bitcoin_NativeSecp256k1 - * Method: secp256k1_ecdsa_sign - * Signature: (Ljava/nio/ByteBuffer;J)[[B - */ -SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ecdsa_1sign - (JNIEnv *, jclass, jobject, jlong); - -/* - * Class: org_bitcoin_NativeSecp256k1 - * Method: secp256k1_ec_seckey_verify - * Signature: (Ljava/nio/ByteBuffer;J)I - */ -SECP256K1_API jint JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ec_1seckey_1verify - (JNIEnv *, jclass, jobject, jlong); - -/* - * Class: org_bitcoin_NativeSecp256k1 - * Method: secp256k1_ec_pubkey_create - * Signature: (Ljava/nio/ByteBuffer;J)[[B - */ -SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ec_1pubkey_1create - (JNIEnv *, jclass, jobject, jlong); - -/* - * Class: org_bitcoin_NativeSecp256k1 - * Method: secp256k1_ec_pubkey_parse - * Signature: (Ljava/nio/ByteBuffer;JI)[[B - */ -SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ec_1pubkey_1parse - (JNIEnv *, jclass, jobject, jlong, jint); - -/* - * Class: org_bitcoin_NativeSecp256k1 - * Method: secp256k1_schnorr_verify - * Signature: (Ljava/nio/ByteBuffer;JI)I - */ -SECP256K1_API jint JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1schnorr_1verify - (JNIEnv *, jclass, jobject, jlong, jint); - -/* - * Class: org_bitcoin_NativeSecp256k1 - * Method: secp256k1_schnorr_sign - * Signature: (Ljava/nio/ByteBuffer;J)[[B - */ -SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1schnorr_1sign - (JNIEnv *, jclass, jobject, jlong); - -/* - * Class: org_bitcoin_NativeSecp256k1 - * Method: secp256k1_ecdh - * Signature: (Ljava/nio/ByteBuffer;JI)[[B - */ -SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ecdh - (JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l, jint publen); - - -#ifdef __cplusplus -} -#endif -#endif +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +#include "include/secp256k1.h" +/* Header for class org_bitcoin_NativeSecp256k1 */ + +#ifndef _Included_org_bitcoin_NativeSecp256k1 +#define _Included_org_bitcoin_NativeSecp256k1 +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: org_bitcoin_NativeSecp256k1 + * Method: secp256k1_ctx_clone + * Signature: (J)J + */ +SECP256K1_API jlong JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ctx_1clone + (JNIEnv *, jclass, jlong); + +/* + * Class: org_bitcoin_NativeSecp256k1 + * Method: secp256k1_context_randomize + * Signature: (Ljava/nio/ByteBuffer;J)I + */ +SECP256K1_API jint JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1context_1randomize + (JNIEnv *, jclass, jobject, jlong); + +/* + * Class: org_bitcoin_NativeSecp256k1 + * Method: secp256k1_privkey_tweak_add + * Signature: (Ljava/nio/ByteBuffer;J)[[B + */ +SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1privkey_1tweak_1add + (JNIEnv *, jclass, jobject, jlong); + +/* + * Class: org_bitcoin_NativeSecp256k1 + * Method: secp256k1_privkey_tweak_mul + * Signature: (Ljava/nio/ByteBuffer;J)[[B + */ +SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1privkey_1tweak_1mul + (JNIEnv *, jclass, jobject, jlong); + +/* + * Class: org_bitcoin_NativeSecp256k1 + * Method: secp256k1_pubkey_tweak_add + * Signature: (Ljava/nio/ByteBuffer;JI)[[B + */ +SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1pubkey_1tweak_1add + (JNIEnv *, jclass, jobject, jlong, jint); + +/* + * Class: org_bitcoin_NativeSecp256k1 + * Method: secp256k1_pubkey_tweak_mul + * Signature: (Ljava/nio/ByteBuffer;JI)[[B + */ +SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1pubkey_1tweak_1mul + (JNIEnv *, jclass, jobject, jlong, jint); + +/* + * Class: org_bitcoin_NativeSecp256k1 + * Method: secp256k1_destroy_context + * Signature: (J)V + */ +SECP256K1_API void JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1destroy_1context + (JNIEnv *, jclass, jlong); + +/* + * Class: org_bitcoin_NativeSecp256k1 + * Method: secp256k1_init_context + * Signature: ()J + */ +SECP256K1_API jlong JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1init_1context + (JNIEnv *, jclass); + +/* + * Class: org_bitcoin_NativeSecp256k1 + * Method: secp256k1_ecdsa_verify + * Signature: (Ljava/nio/ByteBuffer;JII)I + */ +SECP256K1_API jint JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ecdsa_1verify + (JNIEnv *, jclass, jobject, jlong, jint, jint); + +/* + * Class: org_bitcoin_NativeSecp256k1 + * Method: secp256k1_ecdsa_sign + * Signature: (Ljava/nio/ByteBuffer;J)[[B + */ +SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ecdsa_1sign + (JNIEnv *, jclass, jobject, jlong); + +/* + * Class: org_bitcoin_NativeSecp256k1 + * Method: secp256k1_ec_seckey_verify + * Signature: (Ljava/nio/ByteBuffer;J)I + */ +SECP256K1_API jint JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ec_1seckey_1verify + (JNIEnv *, jclass, jobject, jlong); + +/* + * Class: org_bitcoin_NativeSecp256k1 + * Method: secp256k1_ec_pubkey_create + * Signature: (Ljava/nio/ByteBuffer;J)[[B + */ +SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ec_1pubkey_1create + (JNIEnv *, jclass, jobject, jlong); + +/* + * Class: org_bitcoin_NativeSecp256k1 + * Method: secp256k1_ec_pubkey_parse + * Signature: (Ljava/nio/ByteBuffer;JI)[[B + */ +SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ec_1pubkey_1parse + (JNIEnv *, jclass, jobject, jlong, jint); + +/* + * Class: org_bitcoin_NativeSecp256k1 + * Method: secp256k1_schnorr_verify + * Signature: (Ljava/nio/ByteBuffer;JI)I + */ +SECP256K1_API jint JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1schnorr_1verify + (JNIEnv *, jclass, jobject, jlong, jint); + +/* + * Class: org_bitcoin_NativeSecp256k1 + * Method: secp256k1_schnorr_sign + * Signature: (Ljava/nio/ByteBuffer;J)[[B + */ +SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1schnorr_1sign + (JNIEnv *, jclass, jobject, jlong); + +/* + * Class: org_bitcoin_NativeSecp256k1 + * Method: secp256k1_ecdh + * Signature: (Ljava/nio/ByteBuffer;JI)[[B + */ +SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ecdh + (JNIEnv *, jclass, jobject, jlong, jint); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/secp256k1/src/java/org_bitcoin_NativeSecp256k1.c b/src/secp256k1/src/java/org_bitcoin_NativeSecp256k1.c --- a/src/secp256k1/src/java/org_bitcoin_NativeSecp256k1.c +++ b/src/secp256k1/src/java/org_bitcoin_NativeSecp256k1.c @@ -43,6 +43,17 @@ (void)classObject;(void)env; } +SECP256K1_API jlong JNICALL Java_org_bitcoin_NativeSecp256k1_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 jint JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ecdsa_1verify (JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l, jint siglen, jint publen) { diff --git a/src/secp256k1/src/java/org_bitcoin_Secp256k1Context.h b/src/secp256k1/src/java/org_bitcoin_Secp256k1Context.h deleted file mode 100644 --- a/src/secp256k1/src/java/org_bitcoin_Secp256k1Context.h +++ /dev/null @@ -1,22 +0,0 @@ -/* DO NOT EDIT THIS FILE - it is machine generated */ -#include -#include "include/secp256k1.h" -/* Header for class org_bitcoin_Secp256k1Context */ - -#ifndef _Included_org_bitcoin_Secp256k1Context -#define _Included_org_bitcoin_Secp256k1Context -#ifdef __cplusplus -extern "C" { -#endif -/* - * Class: org_bitcoin_Secp256k1Context - * Method: secp256k1_init_context - * Signature: ()J - */ -SECP256K1_API jlong JNICALL Java_org_bitcoin_Secp256k1Context_secp256k1_1init_1context - (JNIEnv *, jclass); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/src/secp256k1/src/java/org_bitcoin_Secp256k1Context.c b/src/secp256k1/src/java/org_bitcoin_Secp256k1Context.c deleted file mode 100644 --- a/src/secp256k1/src/java/org_bitcoin_Secp256k1Context.c +++ /dev/null @@ -1,15 +0,0 @@ -#include -#include -#include "org_bitcoin_Secp256k1Context.h" -#include "include/secp256k1.h" - -SECP256K1_API jlong JNICALL Java_org_bitcoin_Secp256k1Context_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; -} -