diff --git a/contrib/teamcity/build-secp256k1.sh b/contrib/teamcity/build-secp256k1.sh index 56d8778b4..3f997d15f 100755 --- a/contrib/teamcity/build-secp256k1.sh +++ b/contrib/teamcity/build-secp256k1.sh @@ -1,38 +1,31 @@ #!/bin/bash set -eu TOPLEVEL=`git rev-parse --show-toplevel` if [[ -z "${TOPLEVEL}" ]]; then echo "No .git directory found, assuming pwd" TOPLEVEL=`pwd -P` fi SECP_DIR="${TOPLEVEL}/src/secp256k1" # Generate necessary autoconf files cd ${SECP_DIR} ./autogen.sh -# Download the guava dependency if it doesn't exist -mkdir -p "${SECP_DIR}/src/java/guava" -GUAVA_FILE="${SECP_DIR}/src/java/guava/guava-18.0.jar" -if [ ! -f "${GUAVA_FILE}" ]; then - wget https://search.maven.org/remotecontent?filepath=com/google/guava/guava/18.0/guava-18.0.jar -O "${GUAVA_FILE}" -fi - # Setup build directory BUILD_DIR="${SECP_DIR}/build" mkdir -p ${BUILD_DIR} cd ${BUILD_DIR} # Determine the number of build threads THREADS=$(nproc || sysctl -n hw.ncpu) ../configure --enable-jni --enable-experimental --enable-module-ecdh # Run build make -j ${THREADS} # Run Java tests make check-java diff --git a/src/secp256k1/.travis.yml b/src/secp256k1/.travis.yml index c4154e9a8..1d8ba7b57 100644 --- a/src/secp256k1/.travis.yml +++ b/src/secp256k1/.travis.yml @@ -1,69 +1,63 @@ language: c sudo: false addons: apt: packages: libgmp-dev compiler: - clang - gcc -cache: - directories: - - src/java/guava/ env: global: - FIELD=auto BIGNUM=auto SCALAR=auto ENDOMORPHISM=no STATICPRECOMPUTATION=yes ASM=no BUILD=check EXTRAFLAGS= HOST= ECDH=no RECOVERY=no EXPERIMENTAL=no JNI=no - - GUAVA_URL=https://search.maven.org/remotecontent?filepath=com/google/guava/guava/18.0/guava-18.0.jar GUAVA_JAR=src/java/guava/guava-18.0.jar matrix: - SCALAR=32bit RECOVERY=yes - SCALAR=32bit FIELD=32bit ECDH=yes EXPERIMENTAL=yes - SCALAR=64bit - FIELD=64bit RECOVERY=yes - FIELD=64bit ENDOMORPHISM=yes - FIELD=64bit ENDOMORPHISM=yes ECDH=yes EXPERIMENTAL=yes - FIELD=64bit ASM=x86_64 - FIELD=64bit ENDOMORPHISM=yes ASM=x86_64 - FIELD=32bit ENDOMORPHISM=yes - BIGNUM=no - BIGNUM=no ENDOMORPHISM=yes RECOVERY=yes EXPERIMENTAL=yes - BIGNUM=no STATICPRECOMPUTATION=no - BUILD=distcheck - EXTRAFLAGS=CPPFLAGS=-DDETERMINISTIC - EXTRAFLAGS=CFLAGS=-O0 - BUILD=check-java JNI=yes ECDH=yes EXPERIMENTAL=yes matrix: fast_finish: true include: - compiler: clang env: HOST=i686-linux-gnu ENDOMORPHISM=yes addons: apt: packages: - gcc-multilib - libgmp-dev:i386 - compiler: clang env: HOST=i686-linux-gnu addons: apt: packages: - gcc-multilib - compiler: gcc env: HOST=i686-linux-gnu ENDOMORPHISM=yes addons: apt: packages: - gcc-multilib - compiler: gcc env: HOST=i686-linux-gnu addons: apt: packages: - gcc-multilib - libgmp-dev:i386 -before_install: mkdir -p `dirname $GUAVA_JAR` -install: if [ ! -f $GUAVA_JAR ]; then wget $GUAVA_URL -O $GUAVA_JAR; fi before_script: ./autogen.sh script: - if [ -n "$HOST" ]; then export USE_HOST="--host=$HOST"; fi - if [ "x$HOST" = "xi686-linux-gnu" ]; then export CC="$CC -m32"; fi - ./configure --enable-experimental=$EXPERIMENTAL --enable-endomorphism=$ENDOMORPHISM --with-field=$FIELD --with-bignum=$BIGNUM --with-scalar=$SCALAR --enable-ecmult-static-precomputation=$STATICPRECOMPUTATION --enable-module-ecdh=$ECDH --enable-module-recovery=$RECOVERY --enable-jni=$JNI $EXTRAFLAGS $USE_HOST && make -j2 $BUILD os: linux diff --git a/src/secp256k1/Makefile.am b/src/secp256k1/Makefile.am index 41177befe..51c04e545 100644 --- a/src/secp256k1/Makefile.am +++ b/src/secp256k1/Makefile.am @@ -1,185 +1,178 @@ ACLOCAL_AMFLAGS = -I build-aux/m4 lib_LTLIBRARIES = libsecp256k1.la if USE_JNI JNI_LIB = libsecp256k1_jni.la noinst_LTLIBRARIES = $(JNI_LIB) else JNI_LIB = endif include_HEADERS = include/secp256k1.h noinst_HEADERS = noinst_HEADERS += src/scalar.h noinst_HEADERS += src/scalar_4x64.h noinst_HEADERS += src/scalar_8x32.h noinst_HEADERS += src/scalar_low.h noinst_HEADERS += src/scalar_impl.h noinst_HEADERS += src/scalar_4x64_impl.h noinst_HEADERS += src/scalar_8x32_impl.h noinst_HEADERS += src/scalar_low_impl.h noinst_HEADERS += src/group.h noinst_HEADERS += src/group_impl.h noinst_HEADERS += src/num_gmp.h noinst_HEADERS += src/num_gmp_impl.h noinst_HEADERS += src/ecdsa.h noinst_HEADERS += src/ecdsa_impl.h noinst_HEADERS += src/eckey.h noinst_HEADERS += src/eckey_impl.h noinst_HEADERS += src/ecmult.h noinst_HEADERS += src/ecmult_impl.h noinst_HEADERS += src/ecmult_const.h noinst_HEADERS += src/ecmult_const_impl.h noinst_HEADERS += src/ecmult_gen.h noinst_HEADERS += src/ecmult_gen_impl.h noinst_HEADERS += src/num.h noinst_HEADERS += src/num_impl.h noinst_HEADERS += src/field_10x26.h noinst_HEADERS += src/field_10x26_impl.h noinst_HEADERS += src/field_5x52.h noinst_HEADERS += src/field_5x52_impl.h noinst_HEADERS += src/field_5x52_int128_impl.h noinst_HEADERS += src/field_5x52_asm_impl.h noinst_HEADERS += src/java/org_bitcoin_NativeSecp256k1.h noinst_HEADERS += src/java/org_bitcoin_Secp256k1Context.h noinst_HEADERS += src/util.h noinst_HEADERS += src/testrand.h noinst_HEADERS += src/testrand_impl.h noinst_HEADERS += src/hash.h noinst_HEADERS += src/hash_impl.h noinst_HEADERS += src/field.h noinst_HEADERS += src/field_impl.h noinst_HEADERS += src/bench.h noinst_HEADERS += contrib/lax_der_parsing.h noinst_HEADERS += contrib/lax_der_parsing.c noinst_HEADERS += contrib/lax_der_privatekey_parsing.h noinst_HEADERS += contrib/lax_der_privatekey_parsing.c if USE_EXTERNAL_ASM COMMON_LIB = libsecp256k1_common.la noinst_LTLIBRARIES = $(COMMON_LIB) else COMMON_LIB = endif pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = libsecp256k1.pc if USE_EXTERNAL_ASM if USE_ASM_ARM libsecp256k1_common_la_SOURCES = src/asm/field_10x26_arm.s endif endif libsecp256k1_la_SOURCES = src/secp256k1.c libsecp256k1_la_CPPFLAGS = -DSECP256K1_BUILD -I$(top_srcdir)/include -I$(top_srcdir)/src $(SECP_INCLUDES) libsecp256k1_la_LIBADD = $(JNI_LIB) $(SECP_LIBS) $(COMMON_LIB) libsecp256k1_jni_la_SOURCES = src/java/org_bitcoin_NativeSecp256k1.c src/java/org_bitcoin_Secp256k1Context.c libsecp256k1_jni_la_CPPFLAGS = -DSECP256K1_BUILD $(JNI_INCLUDES) noinst_PROGRAMS = if USE_BENCHMARK noinst_PROGRAMS += bench_verify bench_sign bench_internal bench_verify_SOURCES = src/bench_verify.c bench_verify_LDADD = libsecp256k1.la $(SECP_LIBS) $(SECP_TEST_LIBS) $(COMMON_LIB) bench_sign_SOURCES = src/bench_sign.c bench_sign_LDADD = libsecp256k1.la $(SECP_LIBS) $(SECP_TEST_LIBS) $(COMMON_LIB) bench_internal_SOURCES = src/bench_internal.c bench_internal_LDADD = $(SECP_LIBS) $(COMMON_LIB) bench_internal_CPPFLAGS = -DSECP256K1_BUILD -I$(top_srcdir)/src $(SECP_INCLUDES) endif TESTS = if USE_TESTS noinst_PROGRAMS += tests tests_SOURCES = src/tests.c tests_CPPFLAGS = -DSECP256K1_BUILD -I$(top_srcdir)/src -I$(top_srcdir)/include $(SECP_INCLUDES) $(SECP_TEST_INCLUDES) if !ENABLE_COVERAGE tests_CPPFLAGS += -DVERIFY endif tests_LDADD = $(SECP_LIBS) $(SECP_TEST_LIBS) $(COMMON_LIB) tests_LDFLAGS = -static TESTS += tests endif if USE_EXHAUSTIVE_TESTS noinst_PROGRAMS += exhaustive_tests exhaustive_tests_SOURCES = src/tests_exhaustive.c exhaustive_tests_CPPFLAGS = -DSECP256K1_BUILD -I$(top_srcdir)/src $(SECP_INCLUDES) if !ENABLE_COVERAGE exhaustive_tests_CPPFLAGS += -DVERIFY endif exhaustive_tests_LDADD = $(SECP_LIBS) exhaustive_tests_LDFLAGS = -static TESTS += exhaustive_tests endif JAVAROOT=$(srcdir)/src/java JAVAORG=org/bitcoin -JAVA_GUAVA=$(JAVAROOT)/guava/guava-18.0.jar -CLASSPATH_ENV=CLASSPATH=$(JAVA_GUAVA) JAVA_FILES= \ $(JAVAROOT)/$(JAVAORG)/NativeSecp256k1.java \ $(JAVAROOT)/$(JAVAORG)/NativeSecp256k1Test.java \ $(JAVAROOT)/$(JAVAORG)/NativeSecp256k1Util.java \ $(JAVAROOT)/$(JAVAORG)/Secp256k1Context.java if USE_JNI -$(JAVA_GUAVA): - @echo Guava is missing. Fetch it via: \ - wget https://search.maven.org/remotecontent?filepath=com/google/guava/guava/18.0/guava-18.0.jar -O $(@) - @false - .stamp-java: $(JAVA_FILES) @echo Compiling $^ - $(AM_V_at)$(CLASSPATH_ENV) javac $^ + $(AM_V_at) javac $^ @touch $@ if USE_TESTS -check-java: libsecp256k1.la $(JAVA_GUAVA) .stamp-java - $(AM_V_at)java -Djava.library.path="./:./src:./src/.libs:.libs/" -cp "$(JAVA_GUAVA):$(JAVAROOT)" $(JAVAORG)/NativeSecp256k1Test +check-java: libsecp256k1.la .stamp-java + $(AM_V_at)java -Djava.library.path="./:./src:./src/.libs:.libs/" -cp "$(JAVAROOT)" $(JAVAORG)/NativeSecp256k1Test endif endif if USE_ECMULT_STATIC_PRECOMPUTATION CPPFLAGS_FOR_BUILD +=-I$(top_srcdir) CFLAGS_FOR_BUILD += -Wall -Wextra -Wno-unused-function gen_context_OBJECTS = gen_context.o gen_context_BIN = gen_context$(BUILD_EXEEXT) gen_%.o: src/gen_%.c $(CC_FOR_BUILD) $(CPPFLAGS_FOR_BUILD) $(CFLAGS_FOR_BUILD) -c $< -o $@ $(gen_context_BIN): $(gen_context_OBJECTS) $(CC_FOR_BUILD) $^ -o $@ $(libsecp256k1_la_OBJECTS): src/ecmult_static_context.h $(tests_OBJECTS): src/ecmult_static_context.h $(bench_internal_OBJECTS): src/ecmult_static_context.h src/ecmult_static_context.h: $(gen_context_BIN) ./$(gen_context_BIN) CLEANFILES = $(gen_context_BIN) src/ecmult_static_context.h $(JAVAROOT)/$(JAVAORG)/*.class .stamp-java endif EXTRA_DIST = autogen.sh src/gen_context.c src/basic-config.h $(JAVA_FILES) if ENABLE_MODULE_ECDH include src/modules/ecdh/Makefile.am.include endif if ENABLE_MODULE_MULTISET include src/modules/multiset/Makefile.am.include endif if ENABLE_MODULE_RECOVERY include src/modules/recovery/Makefile.am.include endif if ENABLE_MODULE_SCHNORR include src/modules/schnorr/Makefile.am.include endif diff --git a/src/secp256k1/src/java/org/bitcoin/NativeSecp256k1.java b/src/secp256k1/src/java/org/bitcoin/NativeSecp256k1.java index 1c67802fb..6b31cc9d8 100644 --- a/src/secp256k1/src/java/org/bitcoin/NativeSecp256k1.java +++ b/src/secp256k1/src/java/org/bitcoin/NativeSecp256k1.java @@ -1,446 +1,445 @@ /* * 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.*; /** *

This class holds native methods to handle ECDSA verification.

* *

You can find an example library that can be used for this at https://github.com/bitcoin/secp256k1

* *

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 *

*/ 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 nativeECDSABuffer = new ThreadLocal(); /** * 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); + public static boolean verify(byte[] data, byte[] signature, byte[] pub) { + 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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); } diff --git a/src/secp256k1/src/java/org/bitcoin/NativeSecp256k1Test.java b/src/secp256k1/src/java/org/bitcoin/NativeSecp256k1Test.java index 78b4f4e1b..9fc0360dd 100644 --- a/src/secp256k1/src/java/org/bitcoin/NativeSecp256k1Test.java +++ b/src/secp256k1/src/java/org/bitcoin/NativeSecp256k1Test.java @@ -1,226 +1,223 @@ package org.bitcoin; -import com.google.common.io.BaseEncoding; -import java.util.Arrays; -import java.math.BigInteger; import javax.xml.bind.DatatypeConverter; 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()); + byte[] data = DatatypeConverter.parseHexBinary("CF80CD8AED482D5D1527D7DC72FCEFF84E6326592848447D2DC0B0E87DFC9A90"); //sha256hash of "testing" + byte[] sig = DatatypeConverter.parseHexBinary("3044022079BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F817980220294F14E883B3F525B5367756C2A11EF6CF84B730B36C17CB0C56F0AAB2C98589"); + byte[] pub = DatatypeConverter.parseHexBinary("040A629506E1B65CD9D2E0BA9C75DF9C4FED0DB16DC9625ED14397F0AFC836FAE595DC53F8B0EFE61E703075BD9B143BAC75EC0E19F82A2208CAEB32BE53414C40"); 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()); + byte[] data = DatatypeConverter.parseHexBinary("CF80CD8AED482D5D1527D7DC72FCEFF84E6326592848447D2DC0B0E87DFC9A91"); //sha256hash of "testing" + byte[] sig = DatatypeConverter.parseHexBinary("3044022079BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F817980220294F14E883B3F525B5367756C2A11EF6CF84B730B36C17CB0C56F0AAB2C98589"); + byte[] pub = DatatypeConverter.parseHexBinary("040A629506E1B65CD9D2E0BA9C75DF9C4FED0DB16DC9625ED14397F0AFC836FAE595DC53F8B0EFE61E703075BD9B143BAC75EC0E19F82A2208CAEB32BE53414C40"); 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()); + byte[] sec = DatatypeConverter.parseHexBinary("67E56582298859DDAE725F972992A07C6C4FB9F62A8FFF58CE3CA926A1063530"); 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()); + byte[] sec = DatatypeConverter.parseHexBinary("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"); 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[] sec = DatatypeConverter.parseHexBinary("67E56582298859DDAE725F972992A07C6C4FB9F62A8FFF58CE3CA926A1063530"); byte[] resultArr = NativeSecp256k1.computePubkey( sec); - String pubkeyString = javax.xml.bind.DatatypeConverter.printHexBinary(resultArr); + String pubkeyString = DatatypeConverter.printHexBinary(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[] sec = DatatypeConverter.parseHexBinary("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"); - byte[] resultArr = NativeSecp256k1.computePubkey( sec); - String pubkeyString = javax.xml.bind.DatatypeConverter.printHexBinary(resultArr); - assertEquals( pubkeyString, "" , "testPubKeyCreateNeg"); + byte[] resultArr = NativeSecp256k1.computePubkey( sec); + String pubkeyString = DatatypeConverter.printHexBinary(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[] data = DatatypeConverter.parseHexBinary("CF80CD8AED482D5D1527D7DC72FCEFF84E6326592848447D2DC0B0E87DFC9A90"); //sha256hash of "testing" + byte[] sec = DatatypeConverter.parseHexBinary("67E56582298859DDAE725F972992A07C6C4FB9F62A8FFF58CE3CA926A1063530"); byte[] resultArr = NativeSecp256k1.sign(data, sec); - String sigString = javax.xml.bind.DatatypeConverter.printHexBinary(resultArr); + String sigString = DatatypeConverter.printHexBinary(resultArr); assertEquals( sigString, "3045022100F51D069AA46EDB4E2E77773FE364AA2AF6818AF733EA542CFC4D546640A58D8802204F1C442AC9F26F232451A0C3EE99F6875353FC73902C68055C19E31624F687CC" , "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[] data = DatatypeConverter.parseHexBinary("CF80CD8AED482D5D1527D7DC72FCEFF84E6326592848447D2DC0B0E87DFC9A90"); //sha256hash of "testing" + byte[] sec = DatatypeConverter.parseHexBinary("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"); byte[] resultArr = NativeSecp256k1.sign(data, sec); - String sigString = javax.xml.bind.DatatypeConverter.printHexBinary(resultArr); + String sigString = DatatypeConverter.printHexBinary(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[] sec = DatatypeConverter.parseHexBinary("67E56582298859DDAE725F972992A07C6C4FB9F62A8FFF58CE3CA926A1063530"); + byte[] data = DatatypeConverter.parseHexBinary("3982F19BEF1615BCCFBB05E321C10E1D4CBA3DF0E841C2E41EEB6016347653C3"); //sha256hash of "tweak" byte[] resultArr = NativeSecp256k1.privKeyTweakAdd( sec , data ); - String sigString = javax.xml.bind.DatatypeConverter.printHexBinary(resultArr); + String sigString = DatatypeConverter.printHexBinary(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[] sec = DatatypeConverter.parseHexBinary("67E56582298859DDAE725F972992A07C6C4FB9F62A8FFF58CE3CA926A1063530"); + byte[] data = DatatypeConverter.parseHexBinary("3982F19BEF1615BCCFBB05E321C10E1D4CBA3DF0E841C2E41EEB6016347653C3"); //sha256hash of "tweak" byte[] resultArr = NativeSecp256k1.privKeyTweakMul( sec , data ); - String sigString = javax.xml.bind.DatatypeConverter.printHexBinary(resultArr); + String sigString = DatatypeConverter.printHexBinary(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[] pub = DatatypeConverter.parseHexBinary("040A629506E1B65CD9D2E0BA9C75DF9C4FED0DB16DC9625ED14397F0AFC836FAE595DC53F8B0EFE61E703075BD9B143BAC75EC0E19F82A2208CAEB32BE53414C40"); + byte[] data = DatatypeConverter.parseHexBinary("3982F19BEF1615BCCFBB05E321C10E1D4CBA3DF0E841C2E41EEB6016347653C3"); //sha256hash of "tweak" byte[] resultArr = NativeSecp256k1.pubKeyTweakAdd( pub , data ); - String sigString = javax.xml.bind.DatatypeConverter.printHexBinary(resultArr); + String sigString = DatatypeConverter.printHexBinary(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[] pub = DatatypeConverter.parseHexBinary("040A629506E1B65CD9D2E0BA9C75DF9C4FED0DB16DC9625ED14397F0AFC836FAE595DC53F8B0EFE61E703075BD9B143BAC75EC0E19F82A2208CAEB32BE53414C40"); + byte[] data = DatatypeConverter.parseHexBinary("3982F19BEF1615BCCFBB05E321C10E1D4CBA3DF0E841C2E41EEB6016347653C3"); //sha256hash of "tweak" byte[] resultArr = NativeSecp256k1.pubKeyTweakMul( pub , data ); - String sigString = javax.xml.bind.DatatypeConverter.printHexBinary(resultArr); + String sigString = DatatypeConverter.printHexBinary(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" + byte[] seed = DatatypeConverter.parseHexBinary("A441B15FE9A3CF56661190A0B93B9DEC7D04127288CC87250967CF3B52894D11"); //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[] sec = DatatypeConverter.parseHexBinary("67E56582298859DDAE725F972992A07C6C4FB9F62A8FFF58CE3CA926A1063530"); + byte[] pub = DatatypeConverter.parseHexBinary("040A629506E1B65CD9D2E0BA9C75DF9C4FED0DB16DC9625ED14397F0AFC836FAE595DC53F8B0EFE61E703075BD9B143BAC75EC0E19F82A2208CAEB32BE53414C40"); byte[] resultArr = NativeSecp256k1.createECDHSecret(sec, pub); - String ecdhString = javax.xml.bind.DatatypeConverter.printHexBinary(resultArr); + String ecdhString = DatatypeConverter.printHexBinary(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." ); } } diff --git a/src/secp256k1/src/java/org/bitcoin/NativeSecp256k1Util.java b/src/secp256k1/src/java/org/bitcoin/NativeSecp256k1Util.java index 04732ba04..54c6fcc5b 100644 --- a/src/secp256k1/src/java/org/bitcoin/NativeSecp256k1Util.java +++ b/src/secp256k1/src/java/org/bitcoin/NativeSecp256k1Util.java @@ -1,45 +1,51 @@ /* * 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 void checkArgument(boolean expression) { + if (!expression) { + throw new IllegalArgumentException(); + } + } + public static class AssertFailException extends Exception { public AssertFailException(String message) { super( message ); } } }