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) 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) 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,20 @@ */ 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 final long context; + + public NativeSecp256k1() throws UnsatisfiedLinkError { + context = secp256k1_init_context(); + } + + public long getContext() { + return context; + } + /** * Verifies the given secp256k1 signature in native code. * Calling when enabled == false is undefined (probably library not loaded) @@ -50,7 +60,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,9 +76,9 @@ 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(); + r.unlock(); } } @@ -81,7 +91,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,9 +108,9 @@ r.lock(); try { - retByteArray = secp256k1_ecdsa_sign(byteBuff, Secp256k1Context.getContext()); + retByteArray = secp256k1_ecdsa_sign(byteBuff, context); } finally { - r.unlock(); + r.unlock(); } byte[] sigArr = retByteArray[0]; @@ -117,7 +127,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,9 +141,9 @@ r.lock(); try { - return secp256k1_ec_seckey_verify(byteBuff,Secp256k1Context.getContext()) == 1; + return secp256k1_ec_seckey_verify(byteBuff, context) == 1; } finally { - r.unlock(); + r.unlock(); } } @@ -147,7 +157,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,9 +173,9 @@ r.lock(); try { - retByteArray = secp256k1_ec_pubkey_create(byteBuff, Secp256k1Context.getContext()); + retByteArray = secp256k1_ec_pubkey_create(byteBuff, context); } finally { - r.unlock(); + r.unlock(); } byte[] pubArr = retByteArray[0]; @@ -181,20 +191,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(); + w.unlock(); } } - public static long cloneContext() { - r.lock(); - try { - return secp256k1_ctx_clone(Secp256k1Context.getContext()); - } finally { r.unlock(); } + public long cloneContext() { + r.lock(); + try { + return secp256k1_ctx_clone(context); + } finally { r.unlock(); } } /** @@ -203,7 +213,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,9 +229,9 @@ byte[][] retByteArray; r.lock(); try { - retByteArray = secp256k1_privkey_tweak_mul(byteBuff,Secp256k1Context.getContext()); + retByteArray = secp256k1_privkey_tweak_mul(byteBuff, context); } finally { - r.unlock(); + r.unlock(); } byte[] privArr = retByteArray[0]; @@ -242,7 +252,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,9 +268,9 @@ byte[][] retByteArray; r.lock(); try { - retByteArray = secp256k1_privkey_tweak_add(byteBuff,Secp256k1Context.getContext()); + retByteArray = secp256k1_privkey_tweak_add(byteBuff, context); } finally { - r.unlock(); + r.unlock(); } byte[] privArr = retByteArray[0]; @@ -281,7 +291,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,9 +307,9 @@ 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(); + r.unlock(); } byte[] pubArr = retByteArray[0]; @@ -320,7 +330,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,9 +346,9 @@ 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(); + r.unlock(); } byte[] pubArr = retByteArray[0]; @@ -359,7 +369,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,9 +385,9 @@ byte[][] retByteArray; r.lock(); try { - retByteArray = secp256k1_ecdh(byteBuff, Secp256k1Context.getContext(), pubkey.length); + retByteArray = secp256k1_ecdh(byteBuff, context, pubkey.length); } finally { - r.unlock(); + r.unlock(); } byte[] resArr = retByteArray[0]; @@ -394,7 +404,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,9 +418,9 @@ w.lock(); try { - return secp256k1_context_randomize(byteBuff, Secp256k1Context.getContext()) == 1; + return secp256k1_context_randomize(byteBuff, context) == 1; } finally { - w.unlock(); + w.unlock(); } } @@ -421,7 +431,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 +448,7 @@ r.lock(); try { - retByteArray = secp256k1_schnorr_sign(byteBuff, Secp256k1Context.getContext()); + retByteArray = secp256k1_schnorr_sign(byteBuff, context); } finally { r.unlock(); } @@ -459,7 +469,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 +485,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 +505,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,78 @@ /** * 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"); assertEquals(Secp256k1Context.isEnabled(), true, "isEnabled"); + NativeSecp256k1Test test = new NativeSecp256k1Test(); // 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(); - NativeSecp256k1.cleanup(); + // Test Context + test.testContexts(new NativeSecp256k1()); + 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 --- a/src/secp256k1/src/java/org/bitcoin/Secp256k1Context.java +++ b/src/secp256k1/src/java/org/bitcoin/Secp256k1Context.java @@ -22,30 +22,20 @@ */ 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,18 @@ (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; -} -