Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding compressed public key flag to java api #443

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 52 additions & 26 deletions src/java/org/bitcoin/NativeSecp256k1.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,14 @@
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>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`
Expand All @@ -52,8 +51,8 @@ public class NativeSecp256k1 {
* @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);

checkInvariant(data.length == 32 && signature.length <= 520 && pub.length <= 520);
ByteBuffer byteBuff = nativeECDSABuffer.get();
if (byteBuff == null || byteBuff.capacity() < 520) {
byteBuff = ByteBuffer.allocateDirect(520);
Expand All @@ -65,8 +64,6 @@ public static boolean verify(byte[] data, byte[] signature, byte[] pub) throws A
byteBuff.put(signature);
byteBuff.put(pub);

byte[][] retByteArray;

r.lock();
try {
return secp256k1_ecdsa_verify(byteBuff, Secp256k1Context.getContext(), signature.length, pub.length) == 1;
Expand All @@ -85,7 +82,7 @@ public static boolean verify(byte[] data, byte[] signature, byte[] pub) throws A
* @param sig byte array of signature
*/
public static byte[] sign(byte[] data, byte[] sec) throws AssertFailException{
Preconditions.checkArgument(data.length == 32 && sec.length <= 32);
checkInvariant(data.length == 32 && sec.length <= 32);

ByteBuffer byteBuff = nativeECDSABuffer.get();
if (byteBuff == null || byteBuff.capacity() < 32 + 32) {
Expand Down Expand Up @@ -121,7 +118,7 @@ public static byte[] sign(byte[] data, byte[] sec) throws AssertFailException{
* @param seckey ECDSA Secret key, 32 bytes
*/
public static boolean secKeyVerify(byte[] seckey) {
Preconditions.checkArgument(seckey.length == 32);
checkInvariant(seckey.length == 32);

ByteBuffer byteBuff = nativeECDSABuffer.get();
if (byteBuff == null || byteBuff.capacity() < seckey.length) {
Expand Down Expand Up @@ -149,9 +146,8 @@ public static boolean secKeyVerify(byte[] seckey) {
* 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);
public static byte[] computePubkey(byte[] seckey, boolean fCompressed) throws AssertFailException{
checkInvariant(seckey.length == 32);

ByteBuffer byteBuff = nativeECDSABuffer.get();
if (byteBuff == null || byteBuff.capacity() < seckey.length) {
Expand All @@ -166,7 +162,7 @@ public static byte[] computePubkey(byte[] seckey) throws AssertFailException{

r.lock();
try {
retByteArray = secp256k1_ec_pubkey_create(byteBuff, Secp256k1Context.getContext());
retByteArray = secp256k1_ec_pubkey_create(byteBuff, Secp256k1Context.getContext(), fCompressed);
} finally {
r.unlock();
}
Expand Down Expand Up @@ -207,7 +203,7 @@ public static long cloneContext() {
* @param seckey 32-byte seckey
*/
public static byte[] privKeyTweakMul(byte[] privkey, byte[] tweak) throws AssertFailException{
Preconditions.checkArgument(privkey.length == 32);
checkInvariant(privkey.length == 32);

ByteBuffer byteBuff = nativeECDSABuffer.get();
if (byteBuff == null || byteBuff.capacity() < privkey.length + tweak.length) {
Expand Down Expand Up @@ -246,7 +242,7 @@ public static byte[] privKeyTweakMul(byte[] privkey, byte[] tweak) throws Assert
* @param seckey 32-byte seckey
*/
public static byte[] privKeyTweakAdd(byte[] privkey, byte[] tweak) throws AssertFailException{
Preconditions.checkArgument(privkey.length == 32);
checkInvariant(privkey.length == 32);

ByteBuffer byteBuff = nativeECDSABuffer.get();
if (byteBuff == null || byteBuff.capacity() < privkey.length + tweak.length) {
Expand Down Expand Up @@ -278,14 +274,43 @@ public static byte[] privKeyTweakAdd(byte[] privkey, byte[] tweak) throws Assert
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
*
* @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);
public static byte[] pubKeyTweakAdd(byte[] pubkey, byte[] tweak, boolean fCompressed) throws AssertFailException{
checkInvariant((pubkey.length == 33 && fCompressed) || (pubkey.length == 65 && !fCompressed));

ByteBuffer byteBuff = nativeECDSABuffer.get();
if (byteBuff == null || byteBuff.capacity() < pubkey.length + tweak.length) {
Expand All @@ -300,7 +325,7 @@ public static byte[] pubKeyTweakAdd(byte[] pubkey, byte[] tweak) throws AssertFa
byte[][] retByteArray;
r.lock();
try {
retByteArray = secp256k1_pubkey_tweak_add(byteBuff,Secp256k1Context.getContext(), pubkey.length);
retByteArray = secp256k1_pubkey_tweak_add(byteBuff,Secp256k1Context.getContext(), pubkey.length, fCompressed);
} finally {
r.unlock();
}
Expand All @@ -323,8 +348,8 @@ public static byte[] pubKeyTweakAdd(byte[] pubkey, byte[] tweak) throws AssertFa
* @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);
public static byte[] pubKeyTweakMul(byte[] pubkey, byte[] tweak, boolean fCompressed) throws AssertFailException{
checkInvariant((pubkey.length == 33 && fCompressed) || (pubkey.length == 65 && !fCompressed));

ByteBuffer byteBuff = nativeECDSABuffer.get();
if (byteBuff == null || byteBuff.capacity() < pubkey.length + tweak.length) {
Expand All @@ -339,7 +364,7 @@ public static byte[] pubKeyTweakMul(byte[] pubkey, byte[] tweak) throws AssertFa
byte[][] retByteArray;
r.lock();
try {
retByteArray = secp256k1_pubkey_tweak_mul(byteBuff,Secp256k1Context.getContext(), pubkey.length);
retByteArray = secp256k1_pubkey_tweak_mul(byteBuff,Secp256k1Context.getContext(), pubkey.length, fCompressed);
} finally {
r.unlock();
}
Expand All @@ -363,7 +388,7 @@ public static byte[] pubKeyTweakMul(byte[] pubkey, byte[] tweak) throws AssertFa
* @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);
checkInvariant(seckey.length <= 32 && pubkey.length <= 65);

ByteBuffer byteBuff = nativeECDSABuffer.get();
if (byteBuff == null || byteBuff.capacity() < 32 + pubkey.length) {
Expand Down Expand Up @@ -398,7 +423,7 @@ public static byte[] createECDHSecret(byte[] seckey, byte[] pubkey) throws Asser
* @param seed 32-byte random seed
*/
public static synchronized boolean randomize(byte[] seed) throws AssertFailException{
Preconditions.checkArgument(seed.length == 32 || seed == null);
checkInvariant(seed.length == 32 || seed == null);

ByteBuffer byteBuff = nativeECDSABuffer.get();
if (byteBuff == null || byteBuff.capacity() < seed.length) {
Expand All @@ -425,9 +450,9 @@ public static synchronized boolean randomize(byte[] seed) throws AssertFailExcep

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_add(ByteBuffer byteBuff, long context, int pubLen, boolean fCompressed);

private static native byte[][] secp256k1_pubkey_tweak_mul(ByteBuffer byteBuff, long context, int pubLen);
private static native byte[][] secp256k1_pubkey_tweak_mul(ByteBuffer byteBuff, long context, int pubLen, boolean fCompressed);

private static native void secp256k1_destroy_context(long context);

Expand All @@ -437,10 +462,11 @@ public static synchronized boolean randomize(byte[] seed) throws AssertFailExcep

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_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);

}

Loading