Merge #682: Remove Java Native Interface
642cd062bdRemove Java Native Interface (Jonas Nick) Pull request description: This was discussed in #508. The main reasons are that the existing Java Native Interface (JNI) bindings would need way more work to remain useful to Java developers but the maintainers and regular contributors of libsecp are not very familiar with Java (and evidently are motivated enough to improve the situation). We don't know who relies on these bindings with the exception of ACINQ who have their own fork at https://github.com/ACINQ/secp256k1/tree/jni-embed/src/java (@sstone). Bitcoinj can optionally use the libsecp bindings. Ideally, there would be a separate repository owned by Java developers with just the bindings. Until this exists, Java developers relying on libsecp can use ACINQs fork or an older commit of libsecp. ACKs for top commit: real-or-random: ACK642cd062bdI read the diff real-or-random: ACK642cd062bdI read the diff, and I verified that the diff to 7d9066a66c0f13cabb0c4f71aca30edd3494f0d5, which has been ACKed by sipa, is only the additonal removal of ax_jni_include_dir.m4 Tree-SHA512: 9e573f2b01897bd5f301707062b41de53424517b537ce0834d9049d003cfd73fa1bcc024b543256016e4c9a1126f7c7fef559b84dc4914083b5a2d0ad5e57ea8
This commit is contained in:
@@ -1,446 +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 java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import com.google.common.base.Preconditions;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
import static org.bitcoin.NativeSecp256k1Util.*;
|
||||
|
||||
/**
|
||||
* <p>This class holds native methods to handle ECDSA verification.</p>
|
||||
*
|
||||
* <p>You can find an example library that can be used for this at https://github.com/bitcoin/secp256k1</p>
|
||||
*
|
||||
* <p>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
|
||||
* </p>
|
||||
*/
|
||||
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<ByteBuffer> nativeECDSABuffer = new ThreadLocal<ByteBuffer>();
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
public static boolean verify(byte[] data, byte[] signature, byte[] pub) throws AssertFailException{
|
||||
Preconditions.checkArgument(data.length == 32 && signature.length <= 520 && pub.length <= 520);
|
||||
|
||||
ByteBuffer byteBuff = nativeECDSABuffer.get();
|
||||
if (byteBuff == null || byteBuff.capacity() < 520) {
|
||||
byteBuff = ByteBuffer.allocateDirect(520);
|
||||
byteBuff.order(ByteOrder.nativeOrder());
|
||||
nativeECDSABuffer.set(byteBuff);
|
||||
}
|
||||
byteBuff.rewind();
|
||||
byteBuff.put(data);
|
||||
byteBuff.put(signature);
|
||||
byteBuff.put(pub);
|
||||
|
||||
byte[][] retByteArray;
|
||||
|
||||
r.lock();
|
||||
try {
|
||||
return secp256k1_ecdsa_verify(byteBuff, Secp256k1Context.getContext(), signature.length, pub.length) == 1;
|
||||
} finally {
|
||||
r.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* libsecp256k1 Create an ECDSA signature.
|
||||
*
|
||||
* @param data Message hash, 32 bytes
|
||||
* @param key Secret key, 32 bytes
|
||||
*
|
||||
* Return values
|
||||
* @param sig byte array of signature
|
||||
*/
|
||||
public static byte[] sign(byte[] data, byte[] sec) throws AssertFailException{
|
||||
Preconditions.checkArgument(data.length == 32 && sec.length <= 32);
|
||||
|
||||
ByteBuffer byteBuff = nativeECDSABuffer.get();
|
||||
if (byteBuff == null || byteBuff.capacity() < 32 + 32) {
|
||||
byteBuff = ByteBuffer.allocateDirect(32 + 32);
|
||||
byteBuff.order(ByteOrder.nativeOrder());
|
||||
nativeECDSABuffer.set(byteBuff);
|
||||
}
|
||||
byteBuff.rewind();
|
||||
byteBuff.put(data);
|
||||
byteBuff.put(sec);
|
||||
|
||||
byte[][] retByteArray;
|
||||
|
||||
r.lock();
|
||||
try {
|
||||
retByteArray = secp256k1_ecdsa_sign(byteBuff, Secp256k1Context.getContext());
|
||||
} finally {
|
||||
r.unlock();
|
||||
}
|
||||
|
||||
byte[] sigArr = retByteArray[0];
|
||||
int sigLen = new BigInteger(new byte[] { retByteArray[1][0] }).intValue();
|
||||
int retVal = new BigInteger(new byte[] { retByteArray[1][1] }).intValue();
|
||||
|
||||
assertEquals(sigArr.length, sigLen, "Got bad signature length.");
|
||||
|
||||
return retVal == 0 ? new byte[0] : sigArr;
|
||||
}
|
||||
|
||||
/**
|
||||
* libsecp256k1 Seckey Verify - returns 1 if valid, 0 if invalid
|
||||
*
|
||||
* @param seckey ECDSA Secret key, 32 bytes
|
||||
*/
|
||||
public static boolean secKeyVerify(byte[] seckey) {
|
||||
Preconditions.checkArgument(seckey.length == 32);
|
||||
|
||||
ByteBuffer byteBuff = nativeECDSABuffer.get();
|
||||
if (byteBuff == null || byteBuff.capacity() < seckey.length) {
|
||||
byteBuff = ByteBuffer.allocateDirect(seckey.length);
|
||||
byteBuff.order(ByteOrder.nativeOrder());
|
||||
nativeECDSABuffer.set(byteBuff);
|
||||
}
|
||||
byteBuff.rewind();
|
||||
byteBuff.put(seckey);
|
||||
|
||||
r.lock();
|
||||
try {
|
||||
return 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
|
||||
*
|
||||
* Return values
|
||||
* @param pubkey ECDSA Public key, 33 or 65 bytes
|
||||
*/
|
||||
//TODO add a 'compressed' arg
|
||||
public static byte[] computePubkey(byte[] seckey) throws AssertFailException{
|
||||
Preconditions.checkArgument(seckey.length == 32);
|
||||
|
||||
ByteBuffer byteBuff = nativeECDSABuffer.get();
|
||||
if (byteBuff == null || byteBuff.capacity() < seckey.length) {
|
||||
byteBuff = ByteBuffer.allocateDirect(seckey.length);
|
||||
byteBuff.order(ByteOrder.nativeOrder());
|
||||
nativeECDSABuffer.set(byteBuff);
|
||||
}
|
||||
byteBuff.rewind();
|
||||
byteBuff.put(seckey);
|
||||
|
||||
byte[][] retByteArray;
|
||||
|
||||
r.lock();
|
||||
try {
|
||||
retByteArray = secp256k1_ec_pubkey_create(byteBuff, Secp256k1Context.getContext());
|
||||
} finally {
|
||||
r.unlock();
|
||||
}
|
||||
|
||||
byte[] pubArr = retByteArray[0];
|
||||
int pubLen = new BigInteger(new byte[] { retByteArray[1][0] }).intValue();
|
||||
int retVal = new BigInteger(new byte[] { retByteArray[1][1] }).intValue();
|
||||
|
||||
assertEquals(pubArr.length, pubLen, "Got bad pubkey length.");
|
||||
|
||||
return retVal == 0 ? new byte[0]: 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.
|
||||
*/
|
||||
public static synchronized void cleanup() {
|
||||
w.lock();
|
||||
try {
|
||||
secp256k1_destroy_context(Secp256k1Context.getContext());
|
||||
} finally {
|
||||
w.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public static long cloneContext() {
|
||||
r.lock();
|
||||
try {
|
||||
return secp256k1_ctx_clone(Secp256k1Context.getContext());
|
||||
} finally { r.unlock(); }
|
||||
}
|
||||
|
||||
/**
|
||||
* libsecp256k1 PrivKey Tweak-Mul - Tweak privkey by multiplying to it
|
||||
*
|
||||
* @param tweak some bytes to tweak with
|
||||
* @param seckey 32-byte seckey
|
||||
*/
|
||||
public static byte[] privKeyTweakMul(byte[] privkey, byte[] tweak) throws AssertFailException{
|
||||
Preconditions.checkArgument(privkey.length == 32);
|
||||
|
||||
ByteBuffer byteBuff = nativeECDSABuffer.get();
|
||||
if (byteBuff == null || byteBuff.capacity() < privkey.length + tweak.length) {
|
||||
byteBuff = ByteBuffer.allocateDirect(privkey.length + tweak.length);
|
||||
byteBuff.order(ByteOrder.nativeOrder());
|
||||
nativeECDSABuffer.set(byteBuff);
|
||||
}
|
||||
byteBuff.rewind();
|
||||
byteBuff.put(privkey);
|
||||
byteBuff.put(tweak);
|
||||
|
||||
byte[][] retByteArray;
|
||||
r.lock();
|
||||
try {
|
||||
retByteArray = secp256k1_privkey_tweak_mul(byteBuff,Secp256k1Context.getContext());
|
||||
} finally {
|
||||
r.unlock();
|
||||
}
|
||||
|
||||
byte[] privArr = retByteArray[0];
|
||||
|
||||
int privLen = (byte) new BigInteger(new byte[] { retByteArray[1][0] }).intValue() & 0xFF;
|
||||
int retVal = new BigInteger(new byte[] { retByteArray[1][1] }).intValue();
|
||||
|
||||
assertEquals(privArr.length, privLen, "Got bad pubkey length.");
|
||||
|
||||
assertEquals(retVal, 1, "Failed return value check.");
|
||||
|
||||
return privArr;
|
||||
}
|
||||
|
||||
/**
|
||||
* libsecp256k1 PrivKey Tweak-Add - Tweak privkey by adding to it
|
||||
*
|
||||
* @param tweak some bytes to tweak with
|
||||
* @param seckey 32-byte seckey
|
||||
*/
|
||||
public static byte[] privKeyTweakAdd(byte[] privkey, byte[] tweak) throws AssertFailException{
|
||||
Preconditions.checkArgument(privkey.length == 32);
|
||||
|
||||
ByteBuffer byteBuff = nativeECDSABuffer.get();
|
||||
if (byteBuff == null || byteBuff.capacity() < privkey.length + tweak.length) {
|
||||
byteBuff = ByteBuffer.allocateDirect(privkey.length + tweak.length);
|
||||
byteBuff.order(ByteOrder.nativeOrder());
|
||||
nativeECDSABuffer.set(byteBuff);
|
||||
}
|
||||
byteBuff.rewind();
|
||||
byteBuff.put(privkey);
|
||||
byteBuff.put(tweak);
|
||||
|
||||
byte[][] retByteArray;
|
||||
r.lock();
|
||||
try {
|
||||
retByteArray = secp256k1_privkey_tweak_add(byteBuff,Secp256k1Context.getContext());
|
||||
} finally {
|
||||
r.unlock();
|
||||
}
|
||||
|
||||
byte[] privArr = retByteArray[0];
|
||||
|
||||
int privLen = (byte) new BigInteger(new byte[] { retByteArray[1][0] }).intValue() & 0xFF;
|
||||
int retVal = new BigInteger(new byte[] { retByteArray[1][1] }).intValue();
|
||||
|
||||
assertEquals(privArr.length, privLen, "Got bad pubkey length.");
|
||||
|
||||
assertEquals(retVal, 1, "Failed return value check.");
|
||||
|
||||
return privArr;
|
||||
}
|
||||
|
||||
/**
|
||||
* libsecp256k1 PubKey Tweak-Add - Tweak pubkey by adding to it
|
||||
*
|
||||
* @param tweak some bytes to tweak with
|
||||
* @param pubkey 32-byte seckey
|
||||
*/
|
||||
public static byte[] pubKeyTweakAdd(byte[] pubkey, byte[] tweak) throws AssertFailException{
|
||||
Preconditions.checkArgument(pubkey.length == 33 || pubkey.length == 65);
|
||||
|
||||
ByteBuffer byteBuff = nativeECDSABuffer.get();
|
||||
if (byteBuff == null || byteBuff.capacity() < pubkey.length + tweak.length) {
|
||||
byteBuff = ByteBuffer.allocateDirect(pubkey.length + tweak.length);
|
||||
byteBuff.order(ByteOrder.nativeOrder());
|
||||
nativeECDSABuffer.set(byteBuff);
|
||||
}
|
||||
byteBuff.rewind();
|
||||
byteBuff.put(pubkey);
|
||||
byteBuff.put(tweak);
|
||||
|
||||
byte[][] retByteArray;
|
||||
r.lock();
|
||||
try {
|
||||
retByteArray = secp256k1_pubkey_tweak_add(byteBuff,Secp256k1Context.getContext(), pubkey.length);
|
||||
} finally {
|
||||
r.unlock();
|
||||
}
|
||||
|
||||
byte[] pubArr = retByteArray[0];
|
||||
|
||||
int pubLen = (byte) new BigInteger(new byte[] { retByteArray[1][0] }).intValue() & 0xFF;
|
||||
int retVal = new BigInteger(new byte[] { retByteArray[1][1] }).intValue();
|
||||
|
||||
assertEquals(pubArr.length, pubLen, "Got bad pubkey length.");
|
||||
|
||||
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
|
||||
*/
|
||||
public static byte[] pubKeyTweakMul(byte[] pubkey, byte[] tweak) throws AssertFailException{
|
||||
Preconditions.checkArgument(pubkey.length == 33 || pubkey.length == 65);
|
||||
|
||||
ByteBuffer byteBuff = nativeECDSABuffer.get();
|
||||
if (byteBuff == null || byteBuff.capacity() < pubkey.length + tweak.length) {
|
||||
byteBuff = ByteBuffer.allocateDirect(pubkey.length + tweak.length);
|
||||
byteBuff.order(ByteOrder.nativeOrder());
|
||||
nativeECDSABuffer.set(byteBuff);
|
||||
}
|
||||
byteBuff.rewind();
|
||||
byteBuff.put(pubkey);
|
||||
byteBuff.put(tweak);
|
||||
|
||||
byte[][] retByteArray;
|
||||
r.lock();
|
||||
try {
|
||||
retByteArray = secp256k1_pubkey_tweak_mul(byteBuff,Secp256k1Context.getContext(), pubkey.length);
|
||||
} finally {
|
||||
r.unlock();
|
||||
}
|
||||
|
||||
byte[] pubArr = retByteArray[0];
|
||||
|
||||
int pubLen = (byte) new BigInteger(new byte[] { retByteArray[1][0] }).intValue() & 0xFF;
|
||||
int retVal = new BigInteger(new byte[] { retByteArray[1][1] }).intValue();
|
||||
|
||||
assertEquals(pubArr.length, pubLen, "Got bad pubkey length.");
|
||||
|
||||
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
|
||||
*/
|
||||
public static byte[] createECDHSecret(byte[] seckey, byte[] pubkey) throws AssertFailException{
|
||||
Preconditions.checkArgument(seckey.length <= 32 && pubkey.length <= 65);
|
||||
|
||||
ByteBuffer byteBuff = nativeECDSABuffer.get();
|
||||
if (byteBuff == null || byteBuff.capacity() < 32 + pubkey.length) {
|
||||
byteBuff = ByteBuffer.allocateDirect(32 + pubkey.length);
|
||||
byteBuff.order(ByteOrder.nativeOrder());
|
||||
nativeECDSABuffer.set(byteBuff);
|
||||
}
|
||||
byteBuff.rewind();
|
||||
byteBuff.put(seckey);
|
||||
byteBuff.put(pubkey);
|
||||
|
||||
byte[][] retByteArray;
|
||||
r.lock();
|
||||
try {
|
||||
retByteArray = secp256k1_ecdh(byteBuff, Secp256k1Context.getContext(), pubkey.length);
|
||||
} finally {
|
||||
r.unlock();
|
||||
}
|
||||
|
||||
byte[] resArr = retByteArray[0];
|
||||
int retVal = new BigInteger(new byte[] { retByteArray[1][0] }).intValue();
|
||||
|
||||
assertEquals(resArr.length, 32, "Got bad result length.");
|
||||
assertEquals(retVal, 1, "Failed return value check.");
|
||||
|
||||
return resArr;
|
||||
}
|
||||
|
||||
/**
|
||||
* libsecp256k1 randomize - updates the context randomization
|
||||
*
|
||||
* @param seed 32-byte random seed
|
||||
*/
|
||||
public static synchronized boolean randomize(byte[] seed) throws AssertFailException{
|
||||
Preconditions.checkArgument(seed.length == 32 || seed == null);
|
||||
|
||||
ByteBuffer byteBuff = nativeECDSABuffer.get();
|
||||
if (byteBuff == null || byteBuff.capacity() < seed.length) {
|
||||
byteBuff = ByteBuffer.allocateDirect(seed.length);
|
||||
byteBuff.order(ByteOrder.nativeOrder());
|
||||
nativeECDSABuffer.set(byteBuff);
|
||||
}
|
||||
byteBuff.rewind();
|
||||
byteBuff.put(seed);
|
||||
|
||||
w.lock();
|
||||
try {
|
||||
return secp256k1_context_randomize(byteBuff, Secp256k1Context.getContext()) == 1;
|
||||
} finally {
|
||||
w.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
private static native long secp256k1_ctx_clone(long context);
|
||||
|
||||
private static native int secp256k1_context_randomize(ByteBuffer byteBuff, long context);
|
||||
|
||||
private static native byte[][] secp256k1_privkey_tweak_add(ByteBuffer byteBuff, long context);
|
||||
|
||||
private static native byte[][] secp256k1_privkey_tweak_mul(ByteBuffer byteBuff, long context);
|
||||
|
||||
private static native byte[][] secp256k1_pubkey_tweak_add(ByteBuffer byteBuff, long context, int pubLen);
|
||||
|
||||
private static native byte[][] secp256k1_pubkey_tweak_mul(ByteBuffer byteBuff, long context, int pubLen);
|
||||
|
||||
private static native void secp256k1_destroy_context(long 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);
|
||||
|
||||
private static native int secp256k1_ec_seckey_verify(ByteBuffer byteBuff, long context);
|
||||
|
||||
private static native byte[][] secp256k1_ec_pubkey_create(ByteBuffer byteBuff, long context);
|
||||
|
||||
private static native byte[][] secp256k1_ec_pubkey_parse(ByteBuffer byteBuff, long context, int inputLen);
|
||||
|
||||
private static native byte[][] secp256k1_ecdh(ByteBuffer byteBuff, long context, int inputLen);
|
||||
|
||||
}
|
||||
@@ -1,225 +0,0 @@
|
||||
package org.bitcoin;
|
||||
|
||||
import com.google.common.io.BaseEncoding;
|
||||
import java.util.Arrays;
|
||||
import java.math.BigInteger;
|
||||
import static org.bitcoin.NativeSecp256k1Util.*;
|
||||
|
||||
/**
|
||||
* This class holds test cases defined for testing this library.
|
||||
*/
|
||||
public class NativeSecp256k1Test {
|
||||
|
||||
//TODO improve comments/add more tests
|
||||
/**
|
||||
* This tests verify() for a valid signature
|
||||
*/
|
||||
public static void testVerifyPos() throws AssertFailException{
|
||||
boolean result = false;
|
||||
byte[] data = BaseEncoding.base16().lowerCase().decode("CF80CD8AED482D5D1527D7DC72FCEFF84E6326592848447D2DC0B0E87DFC9A90".toLowerCase()); //sha256hash of "testing"
|
||||
byte[] sig = BaseEncoding.base16().lowerCase().decode("3044022079BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F817980220294F14E883B3F525B5367756C2A11EF6CF84B730B36C17CB0C56F0AAB2C98589".toLowerCase());
|
||||
byte[] pub = BaseEncoding.base16().lowerCase().decode("040A629506E1B65CD9D2E0BA9C75DF9C4FED0DB16DC9625ED14397F0AFC836FAE595DC53F8B0EFE61E703075BD9B143BAC75EC0E19F82A2208CAEB32BE53414C40".toLowerCase());
|
||||
|
||||
result = NativeSecp256k1.verify( data, sig, pub);
|
||||
assertEquals( result, true , "testVerifyPos");
|
||||
}
|
||||
|
||||
/**
|
||||
* This tests verify() for a non-valid signature
|
||||
*/
|
||||
public static void testVerifyNeg() throws AssertFailException{
|
||||
boolean result = false;
|
||||
byte[] data = BaseEncoding.base16().lowerCase().decode("CF80CD8AED482D5D1527D7DC72FCEFF84E6326592848447D2DC0B0E87DFC9A91".toLowerCase()); //sha256hash of "testing"
|
||||
byte[] sig = BaseEncoding.base16().lowerCase().decode("3044022079BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F817980220294F14E883B3F525B5367756C2A11EF6CF84B730B36C17CB0C56F0AAB2C98589".toLowerCase());
|
||||
byte[] pub = BaseEncoding.base16().lowerCase().decode("040A629506E1B65CD9D2E0BA9C75DF9C4FED0DB16DC9625ED14397F0AFC836FAE595DC53F8B0EFE61E703075BD9B143BAC75EC0E19F82A2208CAEB32BE53414C40".toLowerCase());
|
||||
|
||||
result = NativeSecp256k1.verify( data, sig, pub);
|
||||
//System.out.println(" TEST " + new BigInteger(1, resultbytes).toString(16));
|
||||
assertEquals( result, false , "testVerifyNeg");
|
||||
}
|
||||
|
||||
/**
|
||||
* This tests secret key verify() for a valid secretkey
|
||||
*/
|
||||
public static void testSecKeyVerifyPos() throws AssertFailException{
|
||||
boolean result = false;
|
||||
byte[] sec = BaseEncoding.base16().lowerCase().decode("67E56582298859DDAE725F972992A07C6C4FB9F62A8FFF58CE3CA926A1063530".toLowerCase());
|
||||
|
||||
result = NativeSecp256k1.secKeyVerify( sec );
|
||||
//System.out.println(" TEST " + new BigInteger(1, resultbytes).toString(16));
|
||||
assertEquals( result, true , "testSecKeyVerifyPos");
|
||||
}
|
||||
|
||||
/**
|
||||
* This tests secret key verify() for an invalid secretkey
|
||||
*/
|
||||
public static void testSecKeyVerifyNeg() throws AssertFailException{
|
||||
boolean result = false;
|
||||
byte[] sec = BaseEncoding.base16().lowerCase().decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF".toLowerCase());
|
||||
|
||||
result = NativeSecp256k1.secKeyVerify( sec );
|
||||
//System.out.println(" TEST " + new BigInteger(1, resultbytes).toString(16));
|
||||
assertEquals( result, false , "testSecKeyVerifyNeg");
|
||||
}
|
||||
|
||||
/**
|
||||
* This tests public key create() for a valid secretkey
|
||||
*/
|
||||
public static void testPubKeyCreatePos() throws AssertFailException{
|
||||
byte[] sec = BaseEncoding.base16().lowerCase().decode("67E56582298859DDAE725F972992A07C6C4FB9F62A8FFF58CE3CA926A1063530".toLowerCase());
|
||||
|
||||
byte[] resultArr = NativeSecp256k1.computePubkey( sec);
|
||||
String pubkeyString = BaseEncoding.base16().encode(resultArr);
|
||||
assertEquals( pubkeyString , "04C591A8FF19AC9C4E4E5793673B83123437E975285E7B442F4EE2654DFFCA5E2D2103ED494718C697AC9AEBCFD19612E224DB46661011863ED2FC54E71861E2A6" , "testPubKeyCreatePos");
|
||||
}
|
||||
|
||||
/**
|
||||
* This tests public key create() for a invalid secretkey
|
||||
*/
|
||||
public static void testPubKeyCreateNeg() throws AssertFailException{
|
||||
byte[] sec = BaseEncoding.base16().lowerCase().decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF".toLowerCase());
|
||||
|
||||
byte[] resultArr = NativeSecp256k1.computePubkey( sec);
|
||||
String pubkeyString = BaseEncoding.base16().encode(resultArr);
|
||||
assertEquals( pubkeyString, "" , "testPubKeyCreateNeg");
|
||||
}
|
||||
|
||||
/**
|
||||
* This tests sign() for a valid secretkey
|
||||
*/
|
||||
public static void testSignPos() throws AssertFailException{
|
||||
|
||||
byte[] data = BaseEncoding.base16().lowerCase().decode("CF80CD8AED482D5D1527D7DC72FCEFF84E6326592848447D2DC0B0E87DFC9A90".toLowerCase()); //sha256hash of "testing"
|
||||
byte[] sec = BaseEncoding.base16().lowerCase().decode("67E56582298859DDAE725F972992A07C6C4FB9F62A8FFF58CE3CA926A1063530".toLowerCase());
|
||||
|
||||
byte[] resultArr = NativeSecp256k1.sign(data, sec);
|
||||
String sigString = BaseEncoding.base16().encode(resultArr);
|
||||
assertEquals( sigString, "30440220182A108E1448DC8F1FB467D06A0F3BB8EA0533584CB954EF8DA112F1D60E39A202201C66F36DA211C087F3AF88B50EDF4F9BDAA6CF5FD6817E74DCA34DB12390C6E9" , "testSignPos");
|
||||
}
|
||||
|
||||
/**
|
||||
* This tests sign() for a invalid secretkey
|
||||
*/
|
||||
public static void testSignNeg() throws AssertFailException{
|
||||
byte[] data = BaseEncoding.base16().lowerCase().decode("CF80CD8AED482D5D1527D7DC72FCEFF84E6326592848447D2DC0B0E87DFC9A90".toLowerCase()); //sha256hash of "testing"
|
||||
byte[] sec = BaseEncoding.base16().lowerCase().decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF".toLowerCase());
|
||||
|
||||
byte[] resultArr = NativeSecp256k1.sign(data, sec);
|
||||
String sigString = BaseEncoding.base16().encode(resultArr);
|
||||
assertEquals( sigString, "" , "testSignNeg");
|
||||
}
|
||||
|
||||
/**
|
||||
* This tests private key tweak-add
|
||||
*/
|
||||
public static void testPrivKeyTweakAdd_1() throws AssertFailException {
|
||||
byte[] sec = BaseEncoding.base16().lowerCase().decode("67E56582298859DDAE725F972992A07C6C4FB9F62A8FFF58CE3CA926A1063530".toLowerCase());
|
||||
byte[] data = BaseEncoding.base16().lowerCase().decode("3982F19BEF1615BCCFBB05E321C10E1D4CBA3DF0E841C2E41EEB6016347653C3".toLowerCase()); //sha256hash of "tweak"
|
||||
|
||||
byte[] resultArr = NativeSecp256k1.privKeyTweakAdd( sec , data );
|
||||
String sigString = BaseEncoding.base16().encode(resultArr);
|
||||
assertEquals( sigString , "A168571E189E6F9A7E2D657A4B53AE99B909F7E712D1C23CED28093CD57C88F3" , "testPrivKeyAdd_1");
|
||||
}
|
||||
|
||||
/**
|
||||
* This tests private key tweak-mul
|
||||
*/
|
||||
public static void testPrivKeyTweakMul_1() throws AssertFailException {
|
||||
byte[] sec = BaseEncoding.base16().lowerCase().decode("67E56582298859DDAE725F972992A07C6C4FB9F62A8FFF58CE3CA926A1063530".toLowerCase());
|
||||
byte[] data = BaseEncoding.base16().lowerCase().decode("3982F19BEF1615BCCFBB05E321C10E1D4CBA3DF0E841C2E41EEB6016347653C3".toLowerCase()); //sha256hash of "tweak"
|
||||
|
||||
byte[] resultArr = NativeSecp256k1.privKeyTweakMul( sec , data );
|
||||
String sigString = BaseEncoding.base16().encode(resultArr);
|
||||
assertEquals( sigString , "97F8184235F101550F3C71C927507651BD3F1CDB4A5A33B8986ACF0DEE20FFFC" , "testPrivKeyMul_1");
|
||||
}
|
||||
|
||||
/**
|
||||
* This tests private key tweak-add uncompressed
|
||||
*/
|
||||
public static void testPrivKeyTweakAdd_2() throws AssertFailException {
|
||||
byte[] pub = BaseEncoding.base16().lowerCase().decode("040A629506E1B65CD9D2E0BA9C75DF9C4FED0DB16DC9625ED14397F0AFC836FAE595DC53F8B0EFE61E703075BD9B143BAC75EC0E19F82A2208CAEB32BE53414C40".toLowerCase());
|
||||
byte[] data = BaseEncoding.base16().lowerCase().decode("3982F19BEF1615BCCFBB05E321C10E1D4CBA3DF0E841C2E41EEB6016347653C3".toLowerCase()); //sha256hash of "tweak"
|
||||
|
||||
byte[] resultArr = NativeSecp256k1.pubKeyTweakAdd( pub , data );
|
||||
String sigString = BaseEncoding.base16().encode(resultArr);
|
||||
assertEquals( sigString , "0411C6790F4B663CCE607BAAE08C43557EDC1A4D11D88DFCB3D841D0C6A941AF525A268E2A863C148555C48FB5FBA368E88718A46E205FABC3DBA2CCFFAB0796EF" , "testPrivKeyAdd_2");
|
||||
}
|
||||
|
||||
/**
|
||||
* This tests private key tweak-mul uncompressed
|
||||
*/
|
||||
public static void testPrivKeyTweakMul_2() throws AssertFailException {
|
||||
byte[] pub = BaseEncoding.base16().lowerCase().decode("040A629506E1B65CD9D2E0BA9C75DF9C4FED0DB16DC9625ED14397F0AFC836FAE595DC53F8B0EFE61E703075BD9B143BAC75EC0E19F82A2208CAEB32BE53414C40".toLowerCase());
|
||||
byte[] data = BaseEncoding.base16().lowerCase().decode("3982F19BEF1615BCCFBB05E321C10E1D4CBA3DF0E841C2E41EEB6016347653C3".toLowerCase()); //sha256hash of "tweak"
|
||||
|
||||
byte[] resultArr = NativeSecp256k1.pubKeyTweakMul( pub , data );
|
||||
String sigString = BaseEncoding.base16().encode(resultArr);
|
||||
assertEquals( sigString , "04E0FE6FE55EBCA626B98A807F6CAF654139E14E5E3698F01A9A658E21DC1D2791EC060D4F412A794D5370F672BC94B722640B5F76914151CFCA6E712CA48CC589" , "testPrivKeyMul_2");
|
||||
}
|
||||
|
||||
/**
|
||||
* This tests seed randomization
|
||||
*/
|
||||
public static void testRandomize() throws AssertFailException {
|
||||
byte[] seed = BaseEncoding.base16().lowerCase().decode("A441B15FE9A3CF56661190A0B93B9DEC7D04127288CC87250967CF3B52894D11".toLowerCase()); //sha256hash of "random"
|
||||
boolean result = NativeSecp256k1.randomize(seed);
|
||||
assertEquals( result, true, "testRandomize");
|
||||
}
|
||||
|
||||
public static void testCreateECDHSecret() throws AssertFailException{
|
||||
|
||||
byte[] sec = BaseEncoding.base16().lowerCase().decode("67E56582298859DDAE725F972992A07C6C4FB9F62A8FFF58CE3CA926A1063530".toLowerCase());
|
||||
byte[] pub = BaseEncoding.base16().lowerCase().decode("040A629506E1B65CD9D2E0BA9C75DF9C4FED0DB16DC9625ED14397F0AFC836FAE595DC53F8B0EFE61E703075BD9B143BAC75EC0E19F82A2208CAEB32BE53414C40".toLowerCase());
|
||||
|
||||
byte[] resultArr = NativeSecp256k1.createECDHSecret(sec, pub);
|
||||
String ecdhString = BaseEncoding.base16().encode(resultArr);
|
||||
assertEquals( ecdhString, "2A2A67007A926E6594AF3EB564FC74005B37A9C8AEF2033C4552051B5C87F043" , "testCreateECDHSecret");
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws AssertFailException{
|
||||
|
||||
|
||||
System.out.println("\n libsecp256k1 enabled: " + Secp256k1Context.isEnabled() + "\n");
|
||||
|
||||
assertEquals( Secp256k1Context.isEnabled(), true, "isEnabled" );
|
||||
|
||||
//Test verify() success/fail
|
||||
testVerifyPos();
|
||||
testVerifyNeg();
|
||||
|
||||
//Test secKeyVerify() success/fail
|
||||
testSecKeyVerifyPos();
|
||||
testSecKeyVerifyNeg();
|
||||
|
||||
//Test computePubkey() success/fail
|
||||
testPubKeyCreatePos();
|
||||
testPubKeyCreateNeg();
|
||||
|
||||
//Test sign() success/fail
|
||||
testSignPos();
|
||||
testSignNeg();
|
||||
|
||||
//Test privKeyTweakAdd() 1
|
||||
testPrivKeyTweakAdd_1();
|
||||
|
||||
//Test privKeyTweakMul() 2
|
||||
testPrivKeyTweakMul_1();
|
||||
|
||||
//Test privKeyTweakAdd() 3
|
||||
testPrivKeyTweakAdd_2();
|
||||
|
||||
//Test privKeyTweakMul() 4
|
||||
testPrivKeyTweakMul_2();
|
||||
|
||||
//Test randomize()
|
||||
testRandomize();
|
||||
|
||||
//Test ECDH
|
||||
testCreateECDHSecret();
|
||||
|
||||
NativeSecp256k1.cleanup();
|
||||
|
||||
System.out.println(" All tests passed." );
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,45 +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;
|
||||
|
||||
public class NativeSecp256k1Util{
|
||||
|
||||
public static void assertEquals( int val, int val2, String message ) throws AssertFailException{
|
||||
if( val != val2 )
|
||||
throw new AssertFailException("FAIL: " + message);
|
||||
}
|
||||
|
||||
public static void assertEquals( boolean val, boolean val2, String message ) throws AssertFailException{
|
||||
if( val != val2 )
|
||||
throw new AssertFailException("FAIL: " + message);
|
||||
else
|
||||
System.out.println("PASS: " + message);
|
||||
}
|
||||
|
||||
public static void assertEquals( String val, String val2, String message ) throws AssertFailException{
|
||||
if( !val.equals(val2) )
|
||||
throw new AssertFailException("FAIL: " + message);
|
||||
else
|
||||
System.out.println("PASS: " + message);
|
||||
}
|
||||
|
||||
public static class AssertFailException extends Exception {
|
||||
public AssertFailException(String message) {
|
||||
super( message );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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");
|
||||
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();
|
||||
}
|
||||
@@ -1,379 +0,0 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include "org_bitcoin_NativeSecp256k1.h"
|
||||
#include "include/secp256k1.h"
|
||||
#include "include/secp256k1_ecdh.h"
|
||||
#include "include/secp256k1_recovery.h"
|
||||
|
||||
|
||||
SECP256K1_API jlong JNICALL Java_org_bitcoin_NativeSecp256k1_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_NativeSecp256k1_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_NativeSecp256k1_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_NativeSecp256k1_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 = 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_NativeSecp256k1_secp256k1_1ecdsa_1sign
|
||||
(JNIEnv* env, jclass classObject, jobject byteBufferObject, 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 = 72;
|
||||
|
||||
if( ret ) {
|
||||
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 jint JNICALL Java_org_bitcoin_NativeSecp256k1_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_NativeSecp256k1_secp256k1_1ec_1pubkey_1create
|
||||
(JNIEnv* env, jclass classObject, jobject byteBufferObject, 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 = 65;
|
||||
|
||||
if( ret ) {
|
||||
int ret2 = secp256k1_ec_pubkey_serialize(ctx,outputSer, &outputLen, &pubkey,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_NativeSecp256k1_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_NativeSecp256k1_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;
|
||||
}
|
||||
|
||||
SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_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 = 65;
|
||||
|
||||
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,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_NativeSecp256k1_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 = 65;
|
||||
|
||||
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,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 jlong JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ecdsa_1pubkey_1combine
|
||||
(JNIEnv * env, jclass classObject, jobject byteBufferObject, jlong ctx_l, jint numkeys)
|
||||
{
|
||||
(void)classObject;(void)env;(void)byteBufferObject;(void)ctx_l;(void)numkeys;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_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;
|
||||
}
|
||||
@@ -1,119 +0,0 @@
|
||||
/* DO NOT EDIT THIS FILE - it is machine generated */
|
||||
#include <jni.h>
|
||||
#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_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
|
||||
@@ -1,15 +0,0 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#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;
|
||||
}
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
/* DO NOT EDIT THIS FILE - it is machine generated */
|
||||
#include <jni.h>
|
||||
#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
|
||||
Reference in New Issue
Block a user