Merge pull request #69 from Christewart/secp256k1_api_enhancement

Adding new secp256k1 functionality
This commit is contained in:
Chris Stewart 2017-05-29 10:16:32 -05:00 committed by GitHub
commit f089bff810
4 changed files with 160 additions and 112 deletions

View file

@ -21,7 +21,6 @@ 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.*;
@ -29,7 +28,7 @@ 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>You can find an example library that can be used for this at https://github.com/bitcoin-core/secp256k1</p>
*
* <p>To build secp256k1 for use with bitcoinj, run
* `./configure --enable-jni --enable-experimental --enable-module-ecdh`
@ -53,7 +52,7 @@ public class NativeSecp256k1 {
*/
public static boolean verify(byte[] data, byte[] signature, byte[] pub) throws AssertFailException{
checkInvariant(data.length == 32 && signature.length <= 520 && pub.length <= 520);
checkInvariant(Secp256k1Context.isEnabled());
ByteBuffer byteBuff = nativeECDSABuffer.get();
if (byteBuff == null || byteBuff.capacity() < 520) {
byteBuff = ByteBuffer.allocateDirect(520);
@ -65,14 +64,11 @@ public class NativeSecp256k1 {
byteBuff.put(signature);
byteBuff.put(pub);
byte[][] retByteArray;
r.lock();
try {
return secp256k1_ecdsa_verify(byteBuff, Secp256k1Context.getContext(),
signature.length, pub.length) == 1;
return secp256k1_ecdsa_verify(byteBuff, Secp256k1Context.getContext(), signature.length, pub.length) == 1;
} finally {
r.unlock();
r.unlock();
}
}
@ -86,9 +82,7 @@ public class NativeSecp256k1 {
* @param sig byte array of signature
*/
public static byte[] sign(byte[] data, byte[] sec) throws AssertFailException{
checkInvariant(data != null);
checkInvariant(data.length == 32);
checkInvariant(sec.length <= 32);
checkInvariant(data.length == 32 && sec.length <= 32);
ByteBuffer byteBuff = nativeECDSABuffer.get();
if (byteBuff == null || byteBuff.capacity() < 32 + 32) {
@ -104,9 +98,9 @@ public class NativeSecp256k1 {
r.lock();
try {
retByteArray = secp256k1_ecdsa_sign(byteBuff, Secp256k1Context.getContext());
retByteArray = secp256k1_ecdsa_sign(byteBuff, Secp256k1Context.getContext());
} finally {
r.unlock();
r.unlock();
}
byte[] sigArr = retByteArray[0];
@ -137,9 +131,9 @@ public class NativeSecp256k1 {
r.lock();
try {
return secp256k1_ec_seckey_verify(byteBuff,Secp256k1Context.getContext()) == 1;
return secp256k1_ec_seckey_verify(byteBuff,Secp256k1Context.getContext()) == 1;
} finally {
r.unlock();
r.unlock();
}
}
@ -152,7 +146,6 @@ public class NativeSecp256k1 {
* Return values
* @param pubkey ECDSA Public key, 33 or 65 bytes
*/
//TODO add a 'compressed' arg
public static byte[] computePubkey(byte[] seckey, boolean fCompressed) throws AssertFailException{
checkInvariant(seckey.length == 32);
@ -169,9 +162,9 @@ public class NativeSecp256k1 {
r.lock();
try {
retByteArray = secp256k1_ec_pubkey_create(byteBuff, Secp256k1Context.getContext(), fCompressed);
retByteArray = secp256k1_ec_pubkey_create(byteBuff, Secp256k1Context.getContext(), fCompressed);
} finally {
r.unlock();
r.unlock();
}
byte[] pubArr = retByteArray[0];
@ -190,17 +183,17 @@ public class NativeSecp256k1 {
public static synchronized void cleanup() {
w.lock();
try {
secp256k1_destroy_context(Secp256k1Context.getContext());
secp256k1_destroy_context(Secp256k1Context.getContext());
} finally {
w.unlock();
w.unlock();
}
}
public static long cloneContext() {
r.lock();
try {
return secp256k1_ctx_clone(Secp256k1Context.getContext());
} finally { r.unlock(); }
r.lock();
try {
return secp256k1_ctx_clone(Secp256k1Context.getContext());
} finally { r.unlock(); }
}
/**
@ -225,9 +218,9 @@ public class NativeSecp256k1 {
byte[][] retByteArray;
r.lock();
try {
retByteArray = secp256k1_privkey_tweak_mul(byteBuff,Secp256k1Context.getContext());
retByteArray = secp256k1_privkey_tweak_mul(byteBuff,Secp256k1Context.getContext());
} finally {
r.unlock();
r.unlock();
}
byte[] privArr = retByteArray[0];
@ -264,9 +257,9 @@ public class NativeSecp256k1 {
byte[][] retByteArray;
r.lock();
try {
retByteArray = secp256k1_privkey_tweak_add(byteBuff,Secp256k1Context.getContext());
retByteArray = secp256k1_privkey_tweak_add(byteBuff,Secp256k1Context.getContext());
} finally {
r.unlock();
r.unlock();
}
byte[] privArr = retByteArray[0];
@ -281,6 +274,35 @@ public class NativeSecp256k1 {
return privArr;
}
/**
* libsecp256k1 checks if a pubkey is valid
* [[https://github.com/bitcoin-core/secp256k1/blob/0f9e69db555ea35b90f49fa48925c366261452ec/src/secp256k1.c#L150]]
* @param pubkey
* @return
*/
public static boolean isValidPubKey(byte[] pubkey) {
if (!(pubkey.length == 33 || pubkey.length == 65)) {
return false;
}
final int expectedLen = pubkey.length;
ByteBuffer byteBuff = nativeECDSABuffer.get();
if (byteBuff == null || byteBuff.capacity() < pubkey.length) {
byteBuff = ByteBuffer.allocateDirect(pubkey.length);
byteBuff.order(ByteOrder.nativeOrder());
nativeECDSABuffer.set(byteBuff);
}
byteBuff.rewind();
byteBuff.put(pubkey);
r.lock();
try {
return secp256k1_ec_pubkey_parse(byteBuff,Secp256k1Context.getContext(),expectedLen) == 1;
} finally {
r.unlock();
}
}
/**
* libsecp256k1 PubKey Tweak-Add - Tweak pubkey by adding to it
*
@ -288,7 +310,7 @@ public class NativeSecp256k1 {
* @param pubkey 32-byte seckey
*/
public static byte[] pubKeyTweakAdd(byte[] pubkey, byte[] tweak, boolean fCompressed) throws AssertFailException{
checkInvariant(pubkey.length == 33 || pubkey.length == 65);
checkInvariant((pubkey.length == 33 && fCompressed) || (pubkey.length == 65 && !fCompressed));
ByteBuffer byteBuff = nativeECDSABuffer.get();
if (byteBuff == null || byteBuff.capacity() < pubkey.length + tweak.length) {
@ -303,9 +325,9 @@ public class NativeSecp256k1 {
byte[][] retByteArray;
r.lock();
try {
retByteArray = secp256k1_pubkey_tweak_add(byteBuff,Secp256k1Context.getContext(), pubkey.length, fCompressed);
retByteArray = secp256k1_pubkey_tweak_add(byteBuff,Secp256k1Context.getContext(), pubkey.length, fCompressed);
} finally {
r.unlock();
r.unlock();
}
byte[] pubArr = retByteArray[0];
@ -327,7 +349,7 @@ public class NativeSecp256k1 {
* @param pubkey 32-byte seckey
*/
public static byte[] pubKeyTweakMul(byte[] pubkey, byte[] tweak, boolean fCompressed) throws AssertFailException{
checkInvariant(pubkey.length == 33 || pubkey.length == 65);
checkInvariant((pubkey.length == 33 && fCompressed) || (pubkey.length == 65 && !fCompressed));
ByteBuffer byteBuff = nativeECDSABuffer.get();
if (byteBuff == null || byteBuff.capacity() < pubkey.length + tweak.length) {
@ -342,9 +364,9 @@ public class NativeSecp256k1 {
byte[][] retByteArray;
r.lock();
try {
retByteArray = secp256k1_pubkey_tweak_mul(byteBuff,Secp256k1Context.getContext(), pubkey.length, fCompressed);
retByteArray = secp256k1_pubkey_tweak_mul(byteBuff,Secp256k1Context.getContext(), pubkey.length, fCompressed);
} finally {
r.unlock();
r.unlock();
}
byte[] pubArr = retByteArray[0];
@ -381,9 +403,9 @@ public class NativeSecp256k1 {
byte[][] retByteArray;
r.lock();
try {
retByteArray = secp256k1_ecdh(byteBuff, Secp256k1Context.getContext(), pubkey.length);
retByteArray = secp256k1_ecdh(byteBuff, Secp256k1Context.getContext(), pubkey.length);
} finally {
r.unlock();
r.unlock();
}
byte[] resArr = retByteArray[0];
@ -414,9 +436,9 @@ public class NativeSecp256k1 {
w.lock();
try {
return secp256k1_context_randomize(byteBuff, Secp256k1Context.getContext()) == 1;
return secp256k1_context_randomize(byteBuff, Secp256k1Context.getContext()) == 1;
} finally {
w.unlock();
w.unlock();
}
}
@ -442,16 +464,9 @@ public class NativeSecp256k1 {
private static native byte[][] secp256k1_ec_pubkey_create(ByteBuffer byteBuff, long context, boolean fCompressed);
private static native byte[][] secp256k1_ec_pubkey_parse(ByteBuffer byteBuff, long context, int inputLen);
private static native int secp256k1_ec_pubkey_parse(ByteBuffer byteBuff, long context, int inputLen);
private static native byte[][] secp256k1_ecdh(ByteBuffer byteBuff, long context, int inputLen);
private static void checkInvariant(boolean result) throws IllegalArgumentException {
if (!result) throw new IllegalArgumentException();
}
}

View file

@ -16,30 +16,35 @@
package org.bitcoin;
public class NativeSecp256k1Util {
public class NativeSecp256k1Util{
public static void assertEquals( int val, int val2, String message ) throws AssertFailException{
if( val != val2 )
throw new AssertFailException("FAIL: " + message);
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);
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);
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 );
}
public static void checkInvariant(boolean result) throws IllegalArgumentException {
if (!result) throw new IllegalArgumentException();
}
}
public static class AssertFailException extends Exception {
public AssertFailException(String message) {
super( message );
}
}
}

View file

@ -21,31 +21,31 @@ package org.bitcoin;
* 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
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;
}
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 boolean isEnabled() {
return enabled;
}
public static long getContext() {
if(!enabled) return -1; //sanity check
return context;
}
public static long getContext() {
if(!enabled) return -1; //sanity check
return context;
}
private static native long secp256k1_init_context();
}
private static native long secp256k1_init_context();
}

View file

@ -1,3 +1,4 @@
package org.bitcoin;
import com.google.common.io.BaseEncoding;
@ -11,6 +12,9 @@ import static org.bitcoin.NativeSecp256k1Util.assertEquals;
*/
public class NativeSecp256k1Test {
private static final BaseEncoding hexEncoder = BaseEncoding.base16();
//TODO improve comments/add more tests
/**
* This tests verify() for a valid signature
@ -18,9 +22,9 @@ public class NativeSecp256k1Test {
@Test
public 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());
byte[] data = hexEncoder.decode("CF80CD8AED482D5D1527D7DC72FCEFF84E6326592848447D2DC0B0E87DFC9A90"); //sha256hash of "testing"
byte[] sig = hexEncoder.decode("3044022079BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F817980220294F14E883B3F525B5367756C2A11EF6CF84B730B36C17CB0C56F0AAB2C98589");
byte[] pub = hexEncoder.decode("040A629506E1B65CD9D2E0BA9C75DF9C4FED0DB16DC9625ED14397F0AFC836FAE595DC53F8B0EFE61E703075BD9B143BAC75EC0E19F82A2208CAEB32BE53414C40");
result = NativeSecp256k1.verify( data, sig, pub);
assertEquals( result, true , "testVerifyPos");
@ -32,9 +36,9 @@ public class NativeSecp256k1Test {
@Test
public 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());
byte[] data = hexEncoder.decode("CF80CD8AED482D5D1527D7DC72FCEFF84E6326592848447D2DC0B0E87DFC9A91"); //sha256hash of "testing"
byte[] sig = hexEncoder.decode("3044022079BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F817980220294F14E883B3F525B5367756C2A11EF6CF84B730B36C17CB0C56F0AAB2C98589");
byte[] pub = hexEncoder.decode("040A629506E1B65CD9D2E0BA9C75DF9C4FED0DB16DC9625ED14397F0AFC836FAE595DC53F8B0EFE61E703075BD9B143BAC75EC0E19F82A2208CAEB32BE53414C40");
result = NativeSecp256k1.verify( data, sig, pub);
//System.out.println(" TEST " + new BigInteger(1, resultbytes).toString(16));
@ -47,7 +51,7 @@ public class NativeSecp256k1Test {
@Test
public void testSecKeyVerifyPos() throws AssertFailException{
boolean result = false;
byte[] sec = BaseEncoding.base16().lowerCase().decode("67E56582298859DDAE725F972992A07C6C4FB9F62A8FFF58CE3CA926A1063530".toLowerCase());
byte[] sec = hexEncoder.decode("67E56582298859DDAE725F972992A07C6C4FB9F62A8FFF58CE3CA926A1063530");
result = NativeSecp256k1.secKeyVerify( sec );
//System.out.println(" TEST " + new BigInteger(1, resultbytes).toString(16));
@ -60,7 +64,7 @@ public class NativeSecp256k1Test {
@Test
public void testSecKeyVerifyNeg() throws AssertFailException{
boolean result = false;
byte[] sec = BaseEncoding.base16().lowerCase().decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF".toLowerCase());
byte[] sec = hexEncoder.decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF");
result = NativeSecp256k1.secKeyVerify( sec );
//System.out.println(" TEST " + new BigInteger(1, resultbytes).toString(16));
@ -72,7 +76,7 @@ public class NativeSecp256k1Test {
*/
@Test
public void testPubKeyCreatePos() throws AssertFailException{
byte[] sec = BaseEncoding.base16().lowerCase().decode("67E56582298859DDAE725F972992A07C6C4FB9F62A8FFF58CE3CA926A1063530".toLowerCase());
byte[] sec = hexEncoder.decode("67E56582298859DDAE725F972992A07C6C4FB9F62A8FFF58CE3CA926A1063530");
byte[] resultArr = NativeSecp256k1.computePubkey( sec, true);
String pubkeyString = javax.xml.bind.DatatypeConverter.printHexBinary(resultArr);
@ -84,7 +88,7 @@ public class NativeSecp256k1Test {
*/
@Test
public void testPubKeyCreateNeg() throws AssertFailException{
byte[] sec = BaseEncoding.base16().lowerCase().decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF".toLowerCase());
byte[] sec = hexEncoder.decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF");
byte[] resultArr = NativeSecp256k1.computePubkey( sec, true);
String pubkeyString = javax.xml.bind.DatatypeConverter.printHexBinary(resultArr);
@ -97,8 +101,8 @@ public class NativeSecp256k1Test {
@Test
public void testSignPos() throws AssertFailException{
byte[] data = BaseEncoding.base16().lowerCase().decode("CF80CD8AED482D5D1527D7DC72FCEFF84E6326592848447D2DC0B0E87DFC9A90".toLowerCase()); //sha256hash of "testing"
byte[] sec = BaseEncoding.base16().lowerCase().decode("67E56582298859DDAE725F972992A07C6C4FB9F62A8FFF58CE3CA926A1063530".toLowerCase());
byte[] data = hexEncoder.decode("CF80CD8AED482D5D1527D7DC72FCEFF84E6326592848447D2DC0B0E87DFC9A90"); //sha256hash of "testing"
byte[] sec = hexEncoder.decode("67E56582298859DDAE725F972992A07C6C4FB9F62A8FFF58CE3CA926A1063530");
byte[] resultArr = NativeSecp256k1.sign(data, sec);
String sigString = javax.xml.bind.DatatypeConverter.printHexBinary(resultArr);
@ -110,8 +114,8 @@ public class NativeSecp256k1Test {
*/
@Test
public void testSignNeg() throws AssertFailException{
byte[] data = BaseEncoding.base16().lowerCase().decode("CF80CD8AED482D5D1527D7DC72FCEFF84E6326592848447D2DC0B0E87DFC9A90".toLowerCase()); //sha256hash of "testing"
byte[] sec = BaseEncoding.base16().lowerCase().decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF".toLowerCase());
byte[] data = hexEncoder.decode("CF80CD8AED482D5D1527D7DC72FCEFF84E6326592848447D2DC0B0E87DFC9A90"); //sha256hash of "testing"
byte[] sec = hexEncoder.decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF");
byte[] resultArr = NativeSecp256k1.sign(data, sec);
String sigString = javax.xml.bind.DatatypeConverter.printHexBinary(resultArr);
@ -123,8 +127,8 @@ public class NativeSecp256k1Test {
*/
@Test
public 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[] sec = hexEncoder.decode("67E56582298859DDAE725F972992A07C6C4FB9F62A8FFF58CE3CA926A1063530");
byte[] data = hexEncoder.decode("3982F19BEF1615BCCFBB05E321C10E1D4CBA3DF0E841C2E41EEB6016347653C3"); //sha256hash of "tweak"
byte[] resultArr = NativeSecp256k1.privKeyTweakAdd( sec , data );
String sigString = javax.xml.bind.DatatypeConverter.printHexBinary(resultArr);
@ -136,8 +140,8 @@ public class NativeSecp256k1Test {
*/
@Test
public 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[] sec = hexEncoder.decode("67E56582298859DDAE725F972992A07C6C4FB9F62A8FFF58CE3CA926A1063530");
byte[] data = hexEncoder.decode("3982F19BEF1615BCCFBB05E321C10E1D4CBA3DF0E841C2E41EEB6016347653C3"); //sha256hash of "tweak"
byte[] resultArr = NativeSecp256k1.privKeyTweakMul( sec , data );
String sigString = javax.xml.bind.DatatypeConverter.printHexBinary(resultArr);
@ -149,8 +153,8 @@ public class NativeSecp256k1Test {
*/
@Test
public 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[] pub = hexEncoder.decode("040A629506E1B65CD9D2E0BA9C75DF9C4FED0DB16DC9625ED14397F0AFC836FAE595DC53F8B0EFE61E703075BD9B143BAC75EC0E19F82A2208CAEB32BE53414C40");
byte[] data = hexEncoder.decode("3982F19BEF1615BCCFBB05E321C10E1D4CBA3DF0E841C2E41EEB6016347653C3"); //sha256hash of "tweak"
byte[] resultArr = NativeSecp256k1.pubKeyTweakAdd( pub , data, false );
String sigString = javax.xml.bind.DatatypeConverter.printHexBinary(resultArr);
@ -162,8 +166,8 @@ public class NativeSecp256k1Test {
*/
@Test
public 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[] pub = hexEncoder.decode("040A629506E1B65CD9D2E0BA9C75DF9C4FED0DB16DC9625ED14397F0AFC836FAE595DC53F8B0EFE61E703075BD9B143BAC75EC0E19F82A2208CAEB32BE53414C40");
byte[] data = hexEncoder.decode("3982F19BEF1615BCCFBB05E321C10E1D4CBA3DF0E841C2E41EEB6016347653C3"); //sha256hash of "tweak"
byte[] resultArr = NativeSecp256k1.pubKeyTweakMul( pub , data, false );
String sigString = javax.xml.bind.DatatypeConverter.printHexBinary(resultArr);
@ -174,7 +178,7 @@ public class NativeSecp256k1Test {
*/
@Test
public void testRandomize() throws AssertFailException {
byte[] seed = BaseEncoding.base16().lowerCase().decode("A441B15FE9A3CF56661190A0B93B9DEC7D04127288CC87250967CF3B52894D11".toLowerCase()); //sha256hash of "random"
byte[] seed = hexEncoder.decode("A441B15FE9A3CF56661190A0B93B9DEC7D04127288CC87250967CF3B52894D11"); //sha256hash of "random"
boolean result = NativeSecp256k1.randomize(seed);
assertEquals( result, true, "testRandomize");
}
@ -182,12 +186,36 @@ public class NativeSecp256k1Test {
@Test
public void testCreateECDHSecret() throws AssertFailException{
byte[] sec = BaseEncoding.base16().lowerCase().decode("67E56582298859DDAE725F972992A07C6C4FB9F62A8FFF58CE3CA926A1063530".toLowerCase());
byte[] pub = BaseEncoding.base16().lowerCase().decode("040A629506E1B65CD9D2E0BA9C75DF9C4FED0DB16DC9625ED14397F0AFC836FAE595DC53F8B0EFE61E703075BD9B143BAC75EC0E19F82A2208CAEB32BE53414C40".toLowerCase());
byte[] sec = hexEncoder.decode("67E56582298859DDAE725F972992A07C6C4FB9F62A8FFF58CE3CA926A1063530");
byte[] pub = hexEncoder.decode("040A629506E1B65CD9D2E0BA9C75DF9C4FED0DB16DC9625ED14397F0AFC836FAE595DC53F8B0EFE61E703075BD9B143BAC75EC0E19F82A2208CAEB32BE53414C40");
byte[] resultArr = NativeSecp256k1.createECDHSecret(sec, pub);
String ecdhString = javax.xml.bind.DatatypeConverter.printHexBinary(resultArr);
assertEquals( ecdhString, "2A2A67007A926E6594AF3EB564FC74005B37A9C8AEF2033C4552051B5C87F043" , "testCreateECDHSecret");
}
}
/**
* Tests that we can parse public keys
* @throws AssertFailException
*/
@Test
public void testIsValidPubKeyPos() throws AssertFailException {
byte[] pubkey = hexEncoder.lowerCase().decode("0456b3817434935db42afda0165de529b938cf67c7510168a51b9297b1ca7e4d91ea59c64516373dd2fe6acc79bb762718bc2659fa68d343bdb12d5ef7b9ed002b");
byte[] compressedPubKey = hexEncoder.lowerCase().decode("03de961a47a519c5c0fc8e744d1f657f9ea6b9a921d2a3bceb8743e1885f752676");
boolean result1 = NativeSecp256k1.isValidPubKey(pubkey);
boolean result2 = NativeSecp256k1.isValidPubKey(compressedPubKey);
assertEquals(result1, true, "Uncompressed pubkey parsed failed");
assertEquals(result2, true, "Compressed pubkey parsed failed");
}
@Test
public void testIsValidPubKeyNeg() throws AssertFailException {
//do we have test vectors some where to test this more thoroughly?
byte[] pubkey = hexEncoder.decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF");
boolean result1 = NativeSecp256k1.isValidPubKey(pubkey);
assertEquals(result1, false, "Compressed pubkey parsed succeeded when it should have failed");
}
}