mirror of
https://github.com/bitcoin-s/bitcoin-s.git
synced 2025-02-24 15:02:17 +01:00
Adding new secp256k1 functionality
This commit is contained in:
parent
8d99b4cc65
commit
b3bcc1d99d
4 changed files with 160 additions and 112 deletions
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue