JNI library
Squashed and rebased. Thanks to @theuni and @faizkhan00 for doing the majority of work here! Also thanks to @btchip for help with debugging and review.
This commit is contained in:
		
							parent
							
								
									bd2895fdd9
								
							
						
					
					
						commit
						3093576aa4
					
				| @ -6,9 +6,13 @@ addons: | |||||||
| compiler: | compiler: | ||||||
|   - clang |   - clang | ||||||
|   - gcc |   - gcc | ||||||
|  | cache: | ||||||
|  |   directories: | ||||||
|  |   - src/java/guava/ | ||||||
| env: | env: | ||||||
|   global: |   global: | ||||||
|     - FIELD=auto  BIGNUM=auto  SCALAR=auto  ENDOMORPHISM=no  STATICPRECOMPUTATION=yes  ASM=no  BUILD=check  EXTRAFLAGS=  HOST=  ECDH=no  schnorr=no  RECOVERY=no  EXPERIMENTAL=no |     - FIELD=auto  BIGNUM=auto  SCALAR=auto  ENDOMORPHISM=no  STATICPRECOMPUTATION=yes  ASM=no  BUILD=check  EXTRAFLAGS=  HOST=  ECDH=no  schnorr=no  RECOVERY=no  EXPERIMENTAL=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: |   matrix: | ||||||
|     - SCALAR=32bit    RECOVERY=yes |     - SCALAR=32bit    RECOVERY=yes | ||||||
|     - SCALAR=32bit    FIELD=32bit       ECDH=yes  EXPERIMENTAL=yes |     - SCALAR=32bit    FIELD=32bit       ECDH=yes  EXPERIMENTAL=yes | ||||||
| @ -26,6 +30,7 @@ env: | |||||||
|     - BUILD=distcheck |     - BUILD=distcheck | ||||||
|     - EXTRAFLAGS=CPPFLAGS=-DDETERMINISTIC |     - EXTRAFLAGS=CPPFLAGS=-DDETERMINISTIC | ||||||
|     - EXTRAFLAGS=CFLAGS=-O0 |     - EXTRAFLAGS=CFLAGS=-O0 | ||||||
|  |     - BUILD=check-java ECDH=yes SCHNORR=yes EXPERIMENTAL=yes | ||||||
| matrix: | matrix: | ||||||
|   fast_finish: true |   fast_finish: true | ||||||
|   include: |   include: | ||||||
| @ -55,6 +60,8 @@ matrix: | |||||||
|           packages: |           packages: | ||||||
|             - gcc-multilib |             - gcc-multilib | ||||||
|             - libgmp-dev:i386 |             - 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 | before_script: ./autogen.sh | ||||||
| script: | script: | ||||||
|  - if [ -n "$HOST" ]; then export USE_HOST="--host=$HOST"; fi |  - if [ -n "$HOST" ]; then export USE_HOST="--host=$HOST"; fi | ||||||
|  | |||||||
							
								
								
									
										49
									
								
								Makefile.am
									
									
									
									
									
								
							
							
						
						
									
										49
									
								
								Makefile.am
									
									
									
									
									
								
							| @ -1,6 +1,12 @@ | |||||||
| ACLOCAL_AMFLAGS = -I build-aux/m4 | ACLOCAL_AMFLAGS = -I build-aux/m4 | ||||||
| 
 | 
 | ||||||
| lib_LTLIBRARIES = libsecp256k1.la | 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 | include_HEADERS = include/secp256k1.h | ||||||
| noinst_HEADERS = | noinst_HEADERS = | ||||||
| noinst_HEADERS += src/scalar.h | noinst_HEADERS += src/scalar.h | ||||||
| @ -32,6 +38,7 @@ noinst_HEADERS += src/field_5x52_impl.h | |||||||
| noinst_HEADERS += src/field_5x52_int128_impl.h | noinst_HEADERS += src/field_5x52_int128_impl.h | ||||||
| noinst_HEADERS += src/field_5x52_asm_impl.h | noinst_HEADERS += src/field_5x52_asm_impl.h | ||||||
| noinst_HEADERS += src/java/org_bitcoin_NativeSecp256k1.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/util.h | ||||||
| noinst_HEADERS += src/testrand.h | noinst_HEADERS += src/testrand.h | ||||||
| noinst_HEADERS += src/testrand_impl.h | noinst_HEADERS += src/testrand_impl.h | ||||||
| @ -49,9 +56,11 @@ pkgconfigdir = $(libdir)/pkgconfig | |||||||
| pkgconfig_DATA = libsecp256k1.pc | pkgconfig_DATA = libsecp256k1.pc | ||||||
| 
 | 
 | ||||||
| libsecp256k1_la_SOURCES = src/secp256k1.c | libsecp256k1_la_SOURCES = src/secp256k1.c | ||||||
| libsecp256k1_la_CPPFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/src $(SECP_INCLUDES) | libsecp256k1_la_CPPFLAGS = -DSECP256K1_BUILD -I$(top_srcdir)/include -I$(top_srcdir)/src $(SECP_INCLUDES) | ||||||
| libsecp256k1_la_LIBADD = $(SECP_LIBS) | libsecp256k1_la_LIBADD = $(JNI_LIB) $(SECP_LIBS) | ||||||
| 
 | 
 | ||||||
|  | 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 = | noinst_PROGRAMS = | ||||||
| if USE_BENCHMARK | if USE_BENCHMARK | ||||||
| @ -68,12 +77,42 @@ endif | |||||||
| if USE_TESTS | if USE_TESTS | ||||||
| noinst_PROGRAMS += tests | noinst_PROGRAMS += tests | ||||||
| tests_SOURCES = src/tests.c | tests_SOURCES = src/tests.c | ||||||
| tests_CPPFLAGS = -DVERIFY -I$(top_srcdir)/src -I$(top_srcdir)/include $(SECP_INCLUDES) $(SECP_TEST_INCLUDES) | tests_CPPFLAGS = -DSECP256K1_BUILD -DVERIFY -I$(top_srcdir)/src -I$(top_srcdir)/include $(SECP_INCLUDES) $(SECP_TEST_INCLUDES) | ||||||
| tests_LDADD = $(SECP_LIBS) $(SECP_TEST_LIBS) | tests_LDADD = $(SECP_LIBS) $(SECP_TEST_LIBS) | ||||||
| tests_LDFLAGS = -static | tests_LDFLAGS = -static | ||||||
| TESTS = tests | TESTS = tests | ||||||
| endif | endif | ||||||
| 
 | 
 | ||||||
|  | JAVAROOT=src/java | ||||||
|  | JAVAORG=org/bitcoin | ||||||
|  | JAVA_GUAVA=$(srcdir)/$(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 $^ | ||||||
|  | 	@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 | ||||||
|  | 
 | ||||||
|  | endif | ||||||
|  | endif | ||||||
|  | 
 | ||||||
| if USE_ECMULT_STATIC_PRECOMPUTATION | if USE_ECMULT_STATIC_PRECOMPUTATION | ||||||
| CPPFLAGS_FOR_BUILD +=-I$(top_srcdir) | CPPFLAGS_FOR_BUILD +=-I$(top_srcdir) | ||||||
| CFLAGS_FOR_BUILD += -Wall -Wextra -Wno-unused-function | CFLAGS_FOR_BUILD += -Wall -Wextra -Wno-unused-function | ||||||
| @ -93,10 +132,10 @@ $(bench_internal_OBJECTS): src/ecmult_static_context.h | |||||||
| src/ecmult_static_context.h: $(gen_context_BIN) | src/ecmult_static_context.h: $(gen_context_BIN) | ||||||
| 	./$(gen_context_BIN) | 	./$(gen_context_BIN) | ||||||
| 
 | 
 | ||||||
| CLEANFILES = $(gen_context_BIN) src/ecmult_static_context.h | CLEANFILES = $(gen_context_BIN) src/ecmult_static_context.h $(JAVAROOT)/$(JAVAORG)/*.class .stamp-java | ||||||
| endif | endif | ||||||
| 
 | 
 | ||||||
| EXTRA_DIST = autogen.sh src/gen_context.c src/basic-config.h | EXTRA_DIST = autogen.sh src/gen_context.c src/basic-config.h $(JAVA_FILES) | ||||||
| 
 | 
 | ||||||
| if ENABLE_MODULE_ECDH | if ENABLE_MODULE_ECDH | ||||||
| include src/modules/ecdh/Makefile.am.include | include src/modules/ecdh/Makefile.am.include | ||||||
|  | |||||||
							
								
								
									
										140
									
								
								build-aux/m4/ax_jni_include_dir.m4
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										140
									
								
								build-aux/m4/ax_jni_include_dir.m4
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,140 @@ | |||||||
|  | # =========================================================================== | ||||||
|  | #    http://www.gnu.org/software/autoconf-archive/ax_jni_include_dir.html | ||||||
|  | # =========================================================================== | ||||||
|  | # | ||||||
|  | # SYNOPSIS | ||||||
|  | # | ||||||
|  | #   AX_JNI_INCLUDE_DIR | ||||||
|  | # | ||||||
|  | # DESCRIPTION | ||||||
|  | # | ||||||
|  | #   AX_JNI_INCLUDE_DIR finds include directories needed for compiling | ||||||
|  | #   programs using the JNI interface. | ||||||
|  | # | ||||||
|  | #   JNI include directories are usually in the Java distribution. This is | ||||||
|  | #   deduced from the value of $JAVA_HOME, $JAVAC, or the path to "javac", in | ||||||
|  | #   that order. When this macro completes, a list of directories is left in | ||||||
|  | #   the variable JNI_INCLUDE_DIRS. | ||||||
|  | # | ||||||
|  | #   Example usage follows: | ||||||
|  | # | ||||||
|  | #     AX_JNI_INCLUDE_DIR | ||||||
|  | # | ||||||
|  | #     for JNI_INCLUDE_DIR in $JNI_INCLUDE_DIRS | ||||||
|  | #     do | ||||||
|  | #             CPPFLAGS="$CPPFLAGS -I$JNI_INCLUDE_DIR" | ||||||
|  | #     done | ||||||
|  | # | ||||||
|  | #   If you want to force a specific compiler: | ||||||
|  | # | ||||||
|  | #   - at the configure.in level, set JAVAC=yourcompiler before calling | ||||||
|  | #   AX_JNI_INCLUDE_DIR | ||||||
|  | # | ||||||
|  | #   - at the configure level, setenv JAVAC | ||||||
|  | # | ||||||
|  | #   Note: This macro can work with the autoconf M4 macros for Java programs. | ||||||
|  | #   This particular macro is not part of the original set of macros. | ||||||
|  | # | ||||||
|  | # LICENSE | ||||||
|  | # | ||||||
|  | #   Copyright (c) 2008 Don Anderson <dda@sleepycat.com> | ||||||
|  | # | ||||||
|  | #   Copying and distribution of this file, with or without modification, are | ||||||
|  | #   permitted in any medium without royalty provided the copyright notice | ||||||
|  | #   and this notice are preserved. This file is offered as-is, without any | ||||||
|  | #   warranty. | ||||||
|  | 
 | ||||||
|  | #serial 10 | ||||||
|  | 
 | ||||||
|  | AU_ALIAS([AC_JNI_INCLUDE_DIR], [AX_JNI_INCLUDE_DIR]) | ||||||
|  | AC_DEFUN([AX_JNI_INCLUDE_DIR],[ | ||||||
|  | 
 | ||||||
|  | JNI_INCLUDE_DIRS="" | ||||||
|  | 
 | ||||||
|  | if test "x$JAVA_HOME" != x; then | ||||||
|  | 	_JTOPDIR="$JAVA_HOME" | ||||||
|  | else | ||||||
|  | 	if test "x$JAVAC" = x; then | ||||||
|  | 		JAVAC=javac | ||||||
|  | 	fi | ||||||
|  | 	AC_PATH_PROG([_ACJNI_JAVAC], [$JAVAC], [no]) | ||||||
|  | 	if test "x$_ACJNI_JAVAC" = xno; then | ||||||
|  | 		AC_MSG_WARN([cannot find JDK; try setting \$JAVAC or \$JAVA_HOME]) | ||||||
|  | 	fi | ||||||
|  | 	_ACJNI_FOLLOW_SYMLINKS("$_ACJNI_JAVAC") | ||||||
|  | 	_JTOPDIR=`echo "$_ACJNI_FOLLOWED" | sed -e 's://*:/:g' -e 's:/[[^/]]*$::'` | ||||||
|  | fi | ||||||
|  | 
 | ||||||
|  | case "$host_os" in | ||||||
|  |         darwin*)        _JTOPDIR=`echo "$_JTOPDIR" | sed -e 's:/[[^/]]*$::'` | ||||||
|  |                         _JINC="$_JTOPDIR/Headers";; | ||||||
|  |         *)              _JINC="$_JTOPDIR/include";; | ||||||
|  | esac | ||||||
|  | _AS_ECHO_LOG([_JTOPDIR=$_JTOPDIR]) | ||||||
|  | _AS_ECHO_LOG([_JINC=$_JINC]) | ||||||
|  | 
 | ||||||
|  | # On Mac OS X 10.6.4, jni.h is a symlink: | ||||||
|  | # /System/Library/Frameworks/JavaVM.framework/Versions/Current/Headers/jni.h | ||||||
|  | # -> ../../CurrentJDK/Headers/jni.h. | ||||||
|  | 
 | ||||||
|  | AC_CACHE_CHECK(jni headers, ac_cv_jni_header_path, | ||||||
|  | [ | ||||||
|  | if test -f "$_JINC/jni.h"; then | ||||||
|  |   ac_cv_jni_header_path="$_JINC" | ||||||
|  |   JNI_INCLUDE_DIRS="$JNI_INCLUDE_DIRS $ac_cv_jni_header_path" | ||||||
|  | else | ||||||
|  |   _JTOPDIR=`echo "$_JTOPDIR" | sed -e 's:/[[^/]]*$::'` | ||||||
|  |   if test -f "$_JTOPDIR/include/jni.h"; then | ||||||
|  |     ac_cv_jni_header_path="$_JTOPDIR/include" | ||||||
|  |     JNI_INCLUDE_DIRS="$JNI_INCLUDE_DIRS $ac_cv_jni_header_path" | ||||||
|  |   else | ||||||
|  |     ac_cv_jni_header_path=none | ||||||
|  |   fi | ||||||
|  | fi | ||||||
|  | ]) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | # get the likely subdirectories for system specific java includes | ||||||
|  | case "$host_os" in | ||||||
|  | bsdi*)          _JNI_INC_SUBDIRS="bsdos";; | ||||||
|  | darwin*)        _JNI_INC_SUBDIRS="darwin";; | ||||||
|  | freebsd*)       _JNI_INC_SUBDIRS="freebsd";; | ||||||
|  | linux*)         _JNI_INC_SUBDIRS="linux genunix";; | ||||||
|  | osf*)           _JNI_INC_SUBDIRS="alpha";; | ||||||
|  | solaris*)       _JNI_INC_SUBDIRS="solaris";; | ||||||
|  | mingw*)		_JNI_INC_SUBDIRS="win32";; | ||||||
|  | cygwin*)	_JNI_INC_SUBDIRS="win32";; | ||||||
|  | *)              _JNI_INC_SUBDIRS="genunix";; | ||||||
|  | esac | ||||||
|  | 
 | ||||||
|  | if test "x$ac_cv_jni_header_path" != "xnone"; then | ||||||
|  |   # add any subdirectories that are present | ||||||
|  |   for JINCSUBDIR in $_JNI_INC_SUBDIRS | ||||||
|  |   do | ||||||
|  |       if test -d "$_JTOPDIR/include/$JINCSUBDIR"; then | ||||||
|  |            JNI_INCLUDE_DIRS="$JNI_INCLUDE_DIRS $_JTOPDIR/include/$JINCSUBDIR" | ||||||
|  |       fi | ||||||
|  |   done | ||||||
|  | fi | ||||||
|  | ]) | ||||||
|  | 
 | ||||||
|  | # _ACJNI_FOLLOW_SYMLINKS <path> | ||||||
|  | # Follows symbolic links on <path>, | ||||||
|  | # finally setting variable _ACJNI_FOLLOWED | ||||||
|  | # ---------------------------------------- | ||||||
|  | AC_DEFUN([_ACJNI_FOLLOW_SYMLINKS],[ | ||||||
|  | # find the include directory relative to the javac executable | ||||||
|  | _cur="$1" | ||||||
|  | while ls -ld "$_cur" 2>/dev/null | grep " -> " >/dev/null; do | ||||||
|  |         AC_MSG_CHECKING([symlink for $_cur]) | ||||||
|  |         _slink=`ls -ld "$_cur" | sed 's/.* -> //'` | ||||||
|  |         case "$_slink" in | ||||||
|  |         /*) _cur="$_slink";; | ||||||
|  |         # 'X' avoids triggering unwanted echo options. | ||||||
|  |         *) _cur=`echo "X$_cur" | sed -e 's/^X//' -e 's:[[^/]]*$::'`"$_slink";; | ||||||
|  |         esac | ||||||
|  |         AC_MSG_RESULT([$_cur]) | ||||||
|  | done | ||||||
|  | _ACJNI_FOLLOWED="$_cur" | ||||||
|  | ])# _ACJNI | ||||||
							
								
								
									
										26
									
								
								configure.ac
									
									
									
									
									
								
							
							
						
						
									
										26
									
								
								configure.ac
									
									
									
									
									
								
							| @ -123,6 +123,11 @@ AC_ARG_ENABLE(module_recovery, | |||||||
|     [enable_module_recovery=$enableval], |     [enable_module_recovery=$enableval], | ||||||
|     [enable_module_recovery=no]) |     [enable_module_recovery=no]) | ||||||
| 
 | 
 | ||||||
|  | AC_ARG_ENABLE(jni, | ||||||
|  |     AS_HELP_STRING([--enable-jni],[enable libsecp256k1_jni (default is auto)]), | ||||||
|  |     [use_jni=$enableval], | ||||||
|  |     [use_jni=auto]) | ||||||
|  | 
 | ||||||
| AC_ARG_WITH([field], [AS_HELP_STRING([--with-field=64bit|32bit|auto], | AC_ARG_WITH([field], [AS_HELP_STRING([--with-field=64bit|32bit|auto], | ||||||
| [Specify Field Implementation. Default is auto])],[req_field=$withval], [req_field=auto]) | [Specify Field Implementation. Default is auto])],[req_field=$withval], [req_field=auto]) | ||||||
| 
 | 
 | ||||||
| @ -323,6 +328,22 @@ if test x"$use_tests" = x"yes"; then | |||||||
|   fi |   fi | ||||||
| fi | fi | ||||||
| 
 | 
 | ||||||
|  | if test x"$use_jni" != x"no"; then | ||||||
|  |   AX_JNI_INCLUDE_DIR | ||||||
|  |   if test "x$JNI_INCLUDE_DIRS" = "x"; then | ||||||
|  |     if test x"$use_jni" = x"yes"; then | ||||||
|  |       AC_MSG_ERROR([jni support explicitly requested but headers were not found]) | ||||||
|  |     fi | ||||||
|  |     AC_MSG_WARN([jni headers not found. jni support disabled]) | ||||||
|  |     use_jni=no | ||||||
|  |   else | ||||||
|  |     use_jni=yes | ||||||
|  |     for JNI_INCLUDE_DIR in $JNI_INCLUDE_DIRS; do | ||||||
|  |       JNI_INCLUDES="$JNI_INCLUDES -I$JNI_INCLUDE_DIR" | ||||||
|  |     done | ||||||
|  |   fi | ||||||
|  | fi | ||||||
|  | 
 | ||||||
| if test x"$set_bignum" = x"gmp"; then | if test x"$set_bignum" = x"gmp"; then | ||||||
|   SECP_LIBS="$SECP_LIBS $GMP_LIBS" |   SECP_LIBS="$SECP_LIBS $GMP_LIBS" | ||||||
|   SECP_INCLUDES="$SECP_INCLUDES $GMP_CPPFLAGS" |   SECP_INCLUDES="$SECP_INCLUDES $GMP_CPPFLAGS" | ||||||
| @ -355,7 +376,10 @@ AC_MSG_NOTICE([Using field implementation: $set_field]) | |||||||
| AC_MSG_NOTICE([Using bignum implementation: $set_bignum]) | AC_MSG_NOTICE([Using bignum implementation: $set_bignum]) | ||||||
| AC_MSG_NOTICE([Using scalar implementation: $set_scalar]) | AC_MSG_NOTICE([Using scalar implementation: $set_scalar]) | ||||||
| AC_MSG_NOTICE([Using endomorphism optimizations: $use_endomorphism]) | AC_MSG_NOTICE([Using endomorphism optimizations: $use_endomorphism]) | ||||||
|  | AC_MSG_NOTICE([Building ECDH module: $enable_module_ecdh]) | ||||||
|  | AC_MSG_NOTICE([Building Schnorr signatures module: $enable_module_schnorr]) | ||||||
| AC_MSG_NOTICE([Building ECDSA pubkey recovery module: $enable_module_recovery]) | AC_MSG_NOTICE([Building ECDSA pubkey recovery module: $enable_module_recovery]) | ||||||
|  | AC_MSG_NOTICE([Using jni: $use_jni]) | ||||||
| 
 | 
 | ||||||
| if test x"$enable_experimental" = x"yes"; then | if test x"$enable_experimental" = x"yes"; then | ||||||
|   AC_MSG_NOTICE([******]) |   AC_MSG_NOTICE([******]) | ||||||
| @ -375,6 +399,7 @@ fi | |||||||
| 
 | 
 | ||||||
| AC_CONFIG_HEADERS([src/libsecp256k1-config.h]) | AC_CONFIG_HEADERS([src/libsecp256k1-config.h]) | ||||||
| AC_CONFIG_FILES([Makefile libsecp256k1.pc]) | AC_CONFIG_FILES([Makefile libsecp256k1.pc]) | ||||||
|  | AC_SUBST(JNI_INCLUDES) | ||||||
| AC_SUBST(SECP_INCLUDES) | AC_SUBST(SECP_INCLUDES) | ||||||
| AC_SUBST(SECP_LIBS) | AC_SUBST(SECP_LIBS) | ||||||
| AC_SUBST(SECP_TEST_LIBS) | AC_SUBST(SECP_TEST_LIBS) | ||||||
| @ -385,6 +410,7 @@ AM_CONDITIONAL([USE_ECMULT_STATIC_PRECOMPUTATION], [test x"$use_ecmult_static_pr | |||||||
| AM_CONDITIONAL([ENABLE_MODULE_ECDH], [test x"$enable_module_ecdh" = x"yes"]) | AM_CONDITIONAL([ENABLE_MODULE_ECDH], [test x"$enable_module_ecdh" = x"yes"]) | ||||||
| AM_CONDITIONAL([ENABLE_MODULE_SCHNORR], [test x"$enable_module_schnorr" = x"yes"]) | AM_CONDITIONAL([ENABLE_MODULE_SCHNORR], [test x"$enable_module_schnorr" = x"yes"]) | ||||||
| AM_CONDITIONAL([ENABLE_MODULE_RECOVERY], [test x"$enable_module_recovery" = x"yes"]) | AM_CONDITIONAL([ENABLE_MODULE_RECOVERY], [test x"$enable_module_recovery" = x"yes"]) | ||||||
|  | AM_CONDITIONAL([USE_JNI], [test x"$use_jni" == x"yes"]) | ||||||
| 
 | 
 | ||||||
| dnl make sure nothing new is exported so that we don't break the cache | dnl make sure nothing new is exported so that we don't break the cache | ||||||
| PKGCONFIG_PATH_TEMP="$PKG_CONFIG_PATH" | PKGCONFIG_PATH_TEMP="$PKG_CONFIG_PATH" | ||||||
|  | |||||||
| @ -3,8 +3,11 @@ package org.bitcoin; | |||||||
| import java.nio.ByteBuffer; | import java.nio.ByteBuffer; | ||||||
| import java.nio.ByteOrder; | import java.nio.ByteOrder; | ||||||
| 
 | 
 | ||||||
|  | import java.math.BigInteger; | ||||||
| import com.google.common.base.Preconditions; | 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. |  * This class holds native methods to handle ECDSA verification. | ||||||
| @ -12,17 +15,10 @@ import com.google.common.base.Preconditions; | |||||||
|  * https://github.com/sipa/secp256k1 |  * https://github.com/sipa/secp256k1 | ||||||
|  */ |  */ | ||||||
| public class NativeSecp256k1 { | public class NativeSecp256k1 { | ||||||
|     public static final boolean enabled; |  | ||||||
|     static { |  | ||||||
|         boolean isEnabled = true; |  | ||||||
|         try { |  | ||||||
|             System.loadLibrary("javasecp256k1"); |  | ||||||
|         } catch (UnsatisfiedLinkError e) { |  | ||||||
|             isEnabled = false; |  | ||||||
|         } |  | ||||||
|         enabled = isEnabled; |  | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|  |     private static final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock(); | ||||||
|  |     private static final Lock r = rwl.readLock(); | ||||||
|  |     private static final Lock w = rwl.writeLock(); | ||||||
|     private static ThreadLocal<ByteBuffer> nativeECDSABuffer = new ThreadLocal<ByteBuffer>(); |     private static ThreadLocal<ByteBuffer> nativeECDSABuffer = new ThreadLocal<ByteBuffer>(); | ||||||
|     /** |     /** | ||||||
|      * Verifies the given secp256k1 signature in native code. |      * Verifies the given secp256k1 signature in native code. | ||||||
| @ -32,29 +28,724 @@ public class NativeSecp256k1 { | |||||||
|      * @param signature The signature |      * @param signature The signature | ||||||
|      * @param pub The public key which did the signing |      * @param pub The public key which did the signing | ||||||
|      */ |      */ | ||||||
|     public static boolean verify(byte[] data, byte[] signature, byte[] pub) { |     public static boolean verify(byte[] data, byte[] signature, byte[] pub) throws AssertFailException{ | ||||||
|         Preconditions.checkArgument(data.length == 32 && signature.length <= 520 && pub.length <= 520); |         Preconditions.checkArgument(data.length == 32 && signature.length <= 520 && pub.length <= 520); | ||||||
| 
 | 
 | ||||||
|         ByteBuffer byteBuff = nativeECDSABuffer.get(); |         ByteBuffer byteBuff = nativeECDSABuffer.get(); | ||||||
|         if (byteBuff == null) { |         if (byteBuff == null || byteBuff.capacity() < 520) { | ||||||
|             byteBuff = ByteBuffer.allocateDirect(32 + 8 + 520 + 520); |             byteBuff = ByteBuffer.allocateDirect(520); | ||||||
|             byteBuff.order(ByteOrder.nativeOrder()); |             byteBuff.order(ByteOrder.nativeOrder()); | ||||||
|             nativeECDSABuffer.set(byteBuff); |             nativeECDSABuffer.set(byteBuff); | ||||||
|         } |         } | ||||||
|         byteBuff.rewind(); |         byteBuff.rewind(); | ||||||
|         byteBuff.put(data); |         byteBuff.put(data); | ||||||
|         byteBuff.putInt(signature.length); |  | ||||||
|         byteBuff.putInt(pub.length); |  | ||||||
|         byteBuff.put(signature); |         byteBuff.put(signature); | ||||||
|         byteBuff.put(pub); |         byteBuff.put(pub); | ||||||
|         return secp256k1_ecdsa_verify(byteBuff) == 1; | 
 | ||||||
|  |         byte[][] retByteArray; | ||||||
|  | 
 | ||||||
|  |         r.lock(); | ||||||
|  |         try { | ||||||
|  |           return secp256k1_ecdsa_verify(byteBuff, Secp256k1Context.getContext(), signature.length, pub.length) == 1; | ||||||
|  |         } finally { | ||||||
|  |           r.unlock(); | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|      * @param byteBuff signature format is byte[32] data, |      * recover the given secp256k1 pubkey in native code. | ||||||
|      *        native-endian int signatureLength, native-endian int pubkeyLength, |      * | ||||||
|      *        byte[signatureLength] signature, byte[pubkeyLength] pub |      * @param data The data which was signed, must be exactly 32 bytes | ||||||
|      * @returns 1 for valid signature, anything else for invalid |      * @param signature The signature | ||||||
|  |      * @param compressed whether to recover a compressed pubkey | ||||||
|  |      * @param pub The public key which did the signing | ||||||
|      */ |      */ | ||||||
|     private static native int secp256k1_ecdsa_verify(ByteBuffer byteBuff); |     //TODO recoverCompact() | ||||||
|  |     public static byte[] recoverCompact(byte[] data, byte[] signature,int compressed, int recID) throws AssertFailException{ | ||||||
|  |         Preconditions.checkArgument(data.length == 32 && signature.length == 64 && (compressed == 0 || compressed == 1)); | ||||||
|  | 
 | ||||||
|  |         ByteBuffer byteBuff = nativeECDSABuffer.get(); | ||||||
|  |         if (byteBuff == null || byteBuff.capacity() < 32 + 64) { | ||||||
|  |             byteBuff = ByteBuffer.allocateDirect(32 + 64); | ||||||
|  |             byteBuff.order(ByteOrder.nativeOrder()); | ||||||
|  |             nativeECDSABuffer.set(byteBuff); | ||||||
|  |         } | ||||||
|  |         byteBuff.rewind(); | ||||||
|  |         byteBuff.put(data); | ||||||
|  |         byteBuff.put(signature); | ||||||
|  | 
 | ||||||
|  |         byte[][] retByteArray = null;//secp256k1_ecdsa_recover_compact(byteBuff, Secp256k1Context, compressed, recID); | ||||||
|  | 
 | ||||||
|  |         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 signature length."); | ||||||
|  | 
 | ||||||
|  |         assertEquals(retVal, 1, "Failed return value check."); | ||||||
|  | 
 | ||||||
|  |         return pubArr; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * libsecp256k1 Create an ECDSA signature. | ||||||
|  |      * | ||||||
|  |      * @param data Message hash, 32 bytes | ||||||
|  |      * @param key Secret key, 32 bytes | ||||||
|  |      * | ||||||
|  |      * Return values | ||||||
|  |      * @param sig byte array of signature | ||||||
|  |      */ | ||||||
|  | 
 | ||||||
|  |     public static byte[] sign(byte[] data, byte[] sec) throws AssertFailException{ | ||||||
|  |         Preconditions.checkArgument(data.length == 32 && sec.length <= 32); | ||||||
|  | 
 | ||||||
|  |         ByteBuffer byteBuff = nativeECDSABuffer.get(); | ||||||
|  |         if (byteBuff == null || byteBuff.capacity() < 32 + 32) { | ||||||
|  |             byteBuff = ByteBuffer.allocateDirect(32 + 32); | ||||||
|  |             byteBuff.order(ByteOrder.nativeOrder()); | ||||||
|  |             nativeECDSABuffer.set(byteBuff); | ||||||
|  |         } | ||||||
|  |         byteBuff.rewind(); | ||||||
|  |         byteBuff.put(data); | ||||||
|  |         byteBuff.put(sec); | ||||||
|  | 
 | ||||||
|  |         byte[][] retByteArray; | ||||||
|  | 
 | ||||||
|  |         r.lock(); | ||||||
|  |         try { | ||||||
|  |           retByteArray = secp256k1_ecdsa_sign(byteBuff, Secp256k1Context.getContext()); | ||||||
|  |         } finally { | ||||||
|  |           r.unlock(); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         byte[] sigArr = retByteArray[0]; | ||||||
|  |         int sigLen = new BigInteger(new byte[] { retByteArray[1][0] }).intValue(); | ||||||
|  |         int retVal = new BigInteger(new byte[] { retByteArray[1][1] }).intValue(); | ||||||
|  | 
 | ||||||
|  |         assertEquals(sigArr.length, sigLen, "Got bad signature length."); | ||||||
|  | 
 | ||||||
|  |         return retVal == 0 ? new byte[0] : sigArr; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * libsecp256k1 Seckey Verify - returns 1 if valid, 0 if invalid | ||||||
|  |      * | ||||||
|  |      * @param seckey ECDSA Secret key, 32 bytes | ||||||
|  |      */ | ||||||
|  | 
 | ||||||
|  |     public static boolean secKeyVerify(byte[] seckey) { | ||||||
|  |         Preconditions.checkArgument(seckey.length == 32); | ||||||
|  | 
 | ||||||
|  |         ByteBuffer byteBuff = nativeECDSABuffer.get(); | ||||||
|  |         if (byteBuff == null || byteBuff.capacity() < seckey.length) { | ||||||
|  |             byteBuff = ByteBuffer.allocateDirect(seckey.length); | ||||||
|  |             byteBuff.order(ByteOrder.nativeOrder()); | ||||||
|  |             nativeECDSABuffer.set(byteBuff); | ||||||
|  |         } | ||||||
|  |         byteBuff.rewind(); | ||||||
|  |         byteBuff.put(seckey); | ||||||
|  | 
 | ||||||
|  |         r.lock(); | ||||||
|  |         try { | ||||||
|  |           return secp256k1_ec_seckey_verify(byteBuff,Secp256k1Context.getContext()) == 1; | ||||||
|  |         } finally { | ||||||
|  |           r.unlock(); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * libsecp256k1 Compute Pubkey - computes public key from secret key | ||||||
|  |      * | ||||||
|  |      * @param seckey ECDSA Secret key, 32 bytes | ||||||
|  |      * @param compressed 1 to return compressed key, 0 for uncompressed | ||||||
|  |      * | ||||||
|  |      * Return values | ||||||
|  |      * @param pubkey ECDSA Public key, 33 or 65 bytes | ||||||
|  |      */ | ||||||
|  | 
 | ||||||
|  |     //TODO support 'compressed' arg | ||||||
|  |     public static byte[] computePubkey(byte[] seckey) throws AssertFailException{ | ||||||
|  |         Preconditions.checkArgument(seckey.length == 32); | ||||||
|  | 
 | ||||||
|  |         ByteBuffer byteBuff = nativeECDSABuffer.get(); | ||||||
|  |         if (byteBuff == null || byteBuff.capacity() < seckey.length) { | ||||||
|  |             byteBuff = ByteBuffer.allocateDirect(seckey.length); | ||||||
|  |             byteBuff.order(ByteOrder.nativeOrder()); | ||||||
|  |             nativeECDSABuffer.set(byteBuff); | ||||||
|  |         } | ||||||
|  |         byteBuff.rewind(); | ||||||
|  |         byteBuff.put(seckey); | ||||||
|  | 
 | ||||||
|  |         byte[][] retByteArray; | ||||||
|  | 
 | ||||||
|  |         r.lock(); | ||||||
|  |         try { | ||||||
|  |           retByteArray = secp256k1_ec_pubkey_create(byteBuff, Secp256k1Context.getContext()); | ||||||
|  |         } finally { | ||||||
|  |           r.unlock(); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         byte[] pubArr = retByteArray[0]; | ||||||
|  |         int pubLen = new BigInteger(new byte[] { retByteArray[1][0] }).intValue(); | ||||||
|  |         int retVal = new BigInteger(new byte[] { retByteArray[1][1] }).intValue(); | ||||||
|  | 
 | ||||||
|  |         assertEquals(pubArr.length, pubLen, "Got bad pubkey length."); | ||||||
|  | 
 | ||||||
|  |         return retVal == 0 ? new byte[0]: pubArr; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * libsecp256k1 Cleanup - This destroys the secp256k1 context object | ||||||
|  |      * This should be called at the end of the program for proper cleanup of the context. | ||||||
|  |      */ | ||||||
|  |     public static synchronized void cleanup() { | ||||||
|  |         w.lock(); | ||||||
|  |         try { | ||||||
|  |           secp256k1_destroy_context(Secp256k1Context.getContext()); | ||||||
|  |         } finally { | ||||||
|  |           w.unlock(); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * libsecp256k1 Secret Key Import - Import a secret key in DER format. | ||||||
|  |      * | ||||||
|  |      * @param seckey DER Sec key | ||||||
|  |      * @param compressed Compressed format | ||||||
|  |      */ | ||||||
|  |     public static byte[] secKeyImport(byte[] seckey) throws AssertFailException{ | ||||||
|  | 
 | ||||||
|  |         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_privkey_import(byteBuff,Secp256k1Context.getContext(), seckey.length); | ||||||
|  |         } 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 Private Key Export - Export a private key in DER format. | ||||||
|  |      * | ||||||
|  |      * @param seckey ECDSA Sec key, 33 or 65 bytes | ||||||
|  |      * @param compressed Compressed format | ||||||
|  |      */ | ||||||
|  |     public static byte[] privKeyExport(byte[] privkey, int compressed) throws AssertFailException{ | ||||||
|  |         Preconditions.checkArgument(privkey.length == 32 && (compressed == 0 || compressed == 1)); | ||||||
|  | 
 | ||||||
|  |         ByteBuffer byteBuff = nativeECDSABuffer.get(); | ||||||
|  |         if (byteBuff == null || byteBuff.capacity() < privkey.length) { | ||||||
|  |             byteBuff = ByteBuffer.allocateDirect(privkey.length); | ||||||
|  |             byteBuff.order(ByteOrder.nativeOrder()); | ||||||
|  |             nativeECDSABuffer.set(byteBuff); | ||||||
|  |         } | ||||||
|  |         byteBuff.rewind(); | ||||||
|  |         byteBuff.put(privkey); | ||||||
|  | 
 | ||||||
|  |         byte[][] retByteArray; | ||||||
|  |         r.lock(); | ||||||
|  |         try { | ||||||
|  |           retByteArray = secp256k1_ec_privkey_export(byteBuff, Secp256k1Context.getContext(), privkey.length, compressed); | ||||||
|  |         } 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, compressed == 1 ? 214 : 279, "Got bad pubkey length."); | ||||||
|  | 
 | ||||||
|  |         assertEquals(retVal, 1, "Failed return value check."); | ||||||
|  | 
 | ||||||
|  |         return privArr; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public static long cloneContext() { | ||||||
|  |        r.lock(); | ||||||
|  |        try { | ||||||
|  |         return secp256k1_ctx_clone(Secp256k1Context.getContext()); | ||||||
|  |        } finally { r.unlock(); } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * libsecp256k1 PrivKey Tweak-Mul - Tweak privkey by multiplying to it | ||||||
|  |      * | ||||||
|  |      * @param tweak some bytes to tweak with | ||||||
|  |      * @param seckey 32-byte seckey | ||||||
|  |      */ | ||||||
|  |     public static byte[] privKeyTweakMul(byte[] privkey, byte[] tweak) throws AssertFailException{ | ||||||
|  |         Preconditions.checkArgument(privkey.length == 32); | ||||||
|  | 
 | ||||||
|  |         ByteBuffer byteBuff = nativeECDSABuffer.get(); | ||||||
|  |         if (byteBuff == null || byteBuff.capacity() < privkey.length + tweak.length) { | ||||||
|  |             byteBuff = ByteBuffer.allocateDirect(privkey.length + tweak.length); | ||||||
|  |             byteBuff.order(ByteOrder.nativeOrder()); | ||||||
|  |             nativeECDSABuffer.set(byteBuff); | ||||||
|  |         } | ||||||
|  |         byteBuff.rewind(); | ||||||
|  |         byteBuff.put(privkey); | ||||||
|  |         byteBuff.put(tweak); | ||||||
|  | 
 | ||||||
|  |         byte[][] retByteArray; | ||||||
|  |         r.lock(); | ||||||
|  |         try { | ||||||
|  |           retByteArray = secp256k1_privkey_tweak_mul(byteBuff,Secp256k1Context.getContext()); | ||||||
|  |         } finally { | ||||||
|  |           r.unlock(); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         byte[] privArr = retByteArray[0]; | ||||||
|  | 
 | ||||||
|  |         int privLen = (byte) new BigInteger(new byte[] { retByteArray[1][0] }).intValue() & 0xFF; | ||||||
|  |         int retVal = new BigInteger(new byte[] { retByteArray[1][1] }).intValue(); | ||||||
|  | 
 | ||||||
|  |         assertEquals(privArr.length, privLen, "Got bad pubkey length."); | ||||||
|  | 
 | ||||||
|  |         assertEquals(retVal, 1, "Failed return value check."); | ||||||
|  | 
 | ||||||
|  |         return privArr; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * libsecp256k1 PrivKey Tweak-Add - Tweak privkey by adding to it | ||||||
|  |      * | ||||||
|  |      * @param tweak some bytes to tweak with | ||||||
|  |      * @param seckey 32-byte seckey | ||||||
|  |      */ | ||||||
|  |     public static byte[] privKeyTweakAdd(byte[] privkey, byte[] tweak) throws AssertFailException{ | ||||||
|  |         Preconditions.checkArgument(privkey.length == 32); | ||||||
|  | 
 | ||||||
|  |         ByteBuffer byteBuff = nativeECDSABuffer.get(); | ||||||
|  |         if (byteBuff == null || byteBuff.capacity() < privkey.length + tweak.length) { | ||||||
|  |             byteBuff = ByteBuffer.allocateDirect(privkey.length + tweak.length); | ||||||
|  |             byteBuff.order(ByteOrder.nativeOrder()); | ||||||
|  |             nativeECDSABuffer.set(byteBuff); | ||||||
|  |         } | ||||||
|  |         byteBuff.rewind(); | ||||||
|  |         byteBuff.put(privkey); | ||||||
|  |         byteBuff.put(tweak); | ||||||
|  | 
 | ||||||
|  |         byte[][] retByteArray; | ||||||
|  |         r.lock(); | ||||||
|  |         try { | ||||||
|  |           retByteArray = secp256k1_privkey_tweak_add(byteBuff,Secp256k1Context.getContext()); | ||||||
|  |         } finally { | ||||||
|  |           r.unlock(); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         byte[] privArr = retByteArray[0]; | ||||||
|  | 
 | ||||||
|  |         int privLen = (byte) new BigInteger(new byte[] { retByteArray[1][0] }).intValue() & 0xFF; | ||||||
|  |         int retVal = new BigInteger(new byte[] { retByteArray[1][1] }).intValue(); | ||||||
|  | 
 | ||||||
|  |         assertEquals(privArr.length, privLen, "Got bad pubkey length."); | ||||||
|  | 
 | ||||||
|  |         assertEquals(retVal, 1, "Failed return value check."); | ||||||
|  | 
 | ||||||
|  |         return privArr; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * libsecp256k1 PubKey Tweak-Add - Tweak pubkey by adding to it | ||||||
|  |      * | ||||||
|  |      * @param tweak some bytes to tweak with | ||||||
|  |      * @param pubkey 32-byte seckey | ||||||
|  |      */ | ||||||
|  |     public static byte[] pubKeyTweakAdd(byte[] pubkey, byte[] tweak) throws AssertFailException{ | ||||||
|  |         Preconditions.checkArgument(pubkey.length == 33 || pubkey.length == 65); | ||||||
|  | 
 | ||||||
|  |         ByteBuffer byteBuff = nativeECDSABuffer.get(); | ||||||
|  |         if (byteBuff == null || byteBuff.capacity() < pubkey.length + tweak.length) { | ||||||
|  |             byteBuff = ByteBuffer.allocateDirect(pubkey.length + tweak.length); | ||||||
|  |             byteBuff.order(ByteOrder.nativeOrder()); | ||||||
|  |             nativeECDSABuffer.set(byteBuff); | ||||||
|  |         } | ||||||
|  |         byteBuff.rewind(); | ||||||
|  |         byteBuff.put(pubkey); | ||||||
|  |         byteBuff.put(tweak); | ||||||
|  | 
 | ||||||
|  |         byte[][] retByteArray; | ||||||
|  |         r.lock(); | ||||||
|  |         try { | ||||||
|  |           retByteArray = secp256k1_pubkey_tweak_add(byteBuff,Secp256k1Context.getContext(), pubkey.length); | ||||||
|  |         } finally { | ||||||
|  |           r.unlock(); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         byte[] pubArr = retByteArray[0]; | ||||||
|  | 
 | ||||||
|  |         int pubLen = (byte) new BigInteger(new byte[] { retByteArray[1][0] }).intValue() & 0xFF; | ||||||
|  |         int retVal = new BigInteger(new byte[] { retByteArray[1][1] }).intValue(); | ||||||
|  | 
 | ||||||
|  |         assertEquals(pubArr.length, pubLen, "Got bad pubkey length."); | ||||||
|  | 
 | ||||||
|  |         assertEquals(retVal, 1, "Failed return value check."); | ||||||
|  | 
 | ||||||
|  |         return pubArr; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * libsecp256k1 PubKey Tweak-Mul - Tweak pubkey by multiplying to it | ||||||
|  |      * | ||||||
|  |      * @param tweak some bytes to tweak with | ||||||
|  |      * @param pubkey 32-byte seckey | ||||||
|  |      */ | ||||||
|  |     public static byte[] pubKeyTweakMul(byte[] pubkey, byte[] tweak) throws AssertFailException{ | ||||||
|  |         Preconditions.checkArgument(pubkey.length == 33 || pubkey.length == 65); | ||||||
|  | 
 | ||||||
|  |         ByteBuffer byteBuff = nativeECDSABuffer.get(); | ||||||
|  |         if (byteBuff == null || byteBuff.capacity() < pubkey.length + tweak.length) { | ||||||
|  |             byteBuff = ByteBuffer.allocateDirect(pubkey.length + tweak.length); | ||||||
|  |             byteBuff.order(ByteOrder.nativeOrder()); | ||||||
|  |             nativeECDSABuffer.set(byteBuff); | ||||||
|  |         } | ||||||
|  |         byteBuff.rewind(); | ||||||
|  |         byteBuff.put(pubkey); | ||||||
|  |         byteBuff.put(tweak); | ||||||
|  | 
 | ||||||
|  |         byte[][] retByteArray; | ||||||
|  |         r.lock(); | ||||||
|  |         try { | ||||||
|  |           retByteArray = secp256k1_pubkey_tweak_mul(byteBuff,Secp256k1Context.getContext(), pubkey.length); | ||||||
|  |         } finally { | ||||||
|  |           r.unlock(); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         byte[] pubArr = retByteArray[0]; | ||||||
|  | 
 | ||||||
|  |         int pubLen = (byte) new BigInteger(new byte[] { retByteArray[1][0] }).intValue() & 0xFF; | ||||||
|  |         int retVal = new BigInteger(new byte[] { retByteArray[1][1] }).intValue(); | ||||||
|  | 
 | ||||||
|  |         assertEquals(pubArr.length, pubLen, "Got bad pubkey length."); | ||||||
|  | 
 | ||||||
|  |         assertEquals(retVal, 1, "Failed return value check."); | ||||||
|  | 
 | ||||||
|  |         return pubArr; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * libsecp256k1 create ECDH secret - constant time ECDH calculation | ||||||
|  |      * | ||||||
|  |      * @param seckey byte array of secret key used in exponentiaion | ||||||
|  |      * @param pubkey byte array of public key used in exponentiaion | ||||||
|  |      */ | ||||||
|  |     //TODO schnorrSign, schnoorVerify, schnorrRecover() | ||||||
|  |     public static byte[] schnoorOps(byte[] pubkey, byte[] msg32) throws AssertFailException{ | ||||||
|  | /* | ||||||
|  |         Preconditions.checkArgument(msg32.length == 32); | ||||||
|  | 
 | ||||||
|  |         ByteBuffer byteBuff = nativeECDSABuffer.get(); | ||||||
|  |         if (byteBuff == null || byteBuff.capacity() < pubkeys.length * 65) { | ||||||
|  |             byteBuff = ByteBuffer.allocateDirect(pubkeys.length * 65); | ||||||
|  |             byteBuff.order(ByteOrder.nativeOrder()); | ||||||
|  |             nativeECDSABuffer.set(byteBuff); | ||||||
|  |         } | ||||||
|  |         byteBuff.rewind(); | ||||||
|  |         byteBuff.put(pubkey); | ||||||
|  | 
 | ||||||
|  |         byte[][] retByteArray; | ||||||
|  |         r.lock(); | ||||||
|  |         try { | ||||||
|  |           retByteArray = secp256k1_ecdsa_recover(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;*/ | ||||||
|  |   return new byte[0]; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * libsecp256k1 create ECDH secret - constant time ECDH calculation | ||||||
|  |      * | ||||||
|  |      * @param seckey byte array of secret key used in exponentiaion | ||||||
|  |      * @param pubkey byte array of public key used in exponentiaion | ||||||
|  |      */ | ||||||
|  |     public static byte[] createECDHSecret(byte[] seckey, byte[] pubkey) throws AssertFailException{ | ||||||
|  |         Preconditions.checkArgument(seckey.length <= 32 && pubkey.length <= 65); | ||||||
|  | 
 | ||||||
|  |         ByteBuffer byteBuff = nativeECDSABuffer.get(); | ||||||
|  |         if (byteBuff == null || byteBuff.capacity() < 32 + pubkey.length) { | ||||||
|  |             byteBuff = ByteBuffer.allocateDirect(32 + pubkey.length); | ||||||
|  |             byteBuff.order(ByteOrder.nativeOrder()); | ||||||
|  |             nativeECDSABuffer.set(byteBuff); | ||||||
|  |         } | ||||||
|  |         byteBuff.rewind(); | ||||||
|  |         byteBuff.put(seckey); | ||||||
|  |         byteBuff.put(pubkey); | ||||||
|  | 
 | ||||||
|  |         byte[][] retByteArray; | ||||||
|  |         r.lock(); | ||||||
|  |         try { | ||||||
|  |           retByteArray = secp256k1_ecdh(byteBuff, Secp256k1Context.getContext(), pubkey.length); | ||||||
|  |         } finally { | ||||||
|  |           r.unlock(); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         byte[] resArr = retByteArray[0]; | ||||||
|  |         int retVal = new BigInteger(new byte[] { retByteArray[1][0] }).intValue(); | ||||||
|  | 
 | ||||||
|  |         assertEquals(resArr.length, 32, "Got bad result length."); | ||||||
|  |         assertEquals(retVal, 1, "Failed return value check."); | ||||||
|  | 
 | ||||||
|  |         return resArr; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * libsecp256k1 createRecoverableSig - create recoverable signature | ||||||
|  |      * | ||||||
|  |      * @param seckey byte array of secret key used in signing | ||||||
|  |      * @param msg32 32-byte signed message hash | ||||||
|  |      */ | ||||||
|  |     //TODO createRecoverableSig() | ||||||
|  |     public static byte[] createRecoverableSig(byte[] pubkey, byte[] msg32) throws AssertFailException{ | ||||||
|  | /* | ||||||
|  |         Preconditions.checkArgument(msg32.length == 32); | ||||||
|  | 
 | ||||||
|  |         ByteBuffer byteBuff = nativeECDSABuffer.get(); | ||||||
|  |         if (byteBuff == null || byteBuff.capacity() < pubkeys.length * 65) { | ||||||
|  |             byteBuff = ByteBuffer.allocateDirect(pubkeys.length * 65); | ||||||
|  |             byteBuff.order(ByteOrder.nativeOrder()); | ||||||
|  |             nativeECDSABuffer.set(byteBuff); | ||||||
|  |         } | ||||||
|  |         byteBuff.rewind(); | ||||||
|  |         byteBuff.put(pubkey); | ||||||
|  | 
 | ||||||
|  |         byte[][] retByteArray; | ||||||
|  |         r.lock(); | ||||||
|  |         try { | ||||||
|  |           retByteArray = secp256k1_ecdsa_recover(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; | ||||||
|  | */ | ||||||
|  |   return new byte[0]; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * libsecp256k1 Recover pubkey - recover pubkey from signature | ||||||
|  |      * | ||||||
|  |      * @param sig byte array of signature | ||||||
|  |      * @param msg32 32-byte signed message hash | ||||||
|  |      */ | ||||||
|  |     //TODO recoverPubkey() | ||||||
|  |     public static byte[] recoverPubkey(byte[] pubkey, byte[] msg32) throws AssertFailException{ | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |   return new byte[0]; | ||||||
|  | /* | ||||||
|  |         Preconditions.checkArgument(msg32.length == 32); | ||||||
|  | 
 | ||||||
|  |         ByteBuffer byteBuff = nativeECDSABuffer.get(); | ||||||
|  |         if (byteBuff == null || byteBuff.capacity() < pubkeys.length * 65) { | ||||||
|  |             byteBuff = ByteBuffer.allocateDirect(pubkeys.length * 65); | ||||||
|  |             byteBuff.order(ByteOrder.nativeOrder()); | ||||||
|  |             nativeECDSABuffer.set(byteBuff); | ||||||
|  |         } | ||||||
|  |         byteBuff.rewind(); | ||||||
|  |         byteBuff.put(pubkey); | ||||||
|  | 
 | ||||||
|  |         byte[][] retByteArray; | ||||||
|  |         r.lock(); | ||||||
|  |         try { | ||||||
|  |           retByteArray = secp256k1_ecdsa_recover(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 combine - add pubkeys together | ||||||
|  |      * | ||||||
|  |      * @param pubkeys byte array of pubkeys | ||||||
|  |      * @param numKeys number of pubkeys to add | ||||||
|  |      */ | ||||||
|  |     //TODO pubkeyCombine | ||||||
|  |     public static byte[] pubKeyCombine(byte[][] pubkeys, int numKeys) throws AssertFailException{ | ||||||
|  | /* | ||||||
|  |         Preconditions.checkArgument(pubkeys.length > 0); | ||||||
|  |         for(int i = 0; i < pubkeys.length; i++) Preconditions.checkArgument(pubkeys[i].length == 65 || pubkeys[i].length == 33); | ||||||
|  | 
 | ||||||
|  |         ByteBuffer byteBuff = nativeECDSABuffer.get(); | ||||||
|  |         if (byteBuff == null || byteBuff.capacity() < pubkeys.length * 65) { | ||||||
|  |             byteBuff = ByteBuffer.allocateDirect(pubkeys.length * 65); | ||||||
|  |             byteBuff.order(ByteOrder.nativeOrder()); | ||||||
|  |             nativeECDSABuffer.set(byteBuff); | ||||||
|  |         } | ||||||
|  |         byteBuff.rewind(); | ||||||
|  |         byteBuff.put(pubkey); | ||||||
|  | 
 | ||||||
|  |         byte[][] retByteArray; | ||||||
|  |         r.lock(); | ||||||
|  |         try { | ||||||
|  |           retByteArray = secp256k1_pubkey_combine(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; | ||||||
|  | */ | ||||||
|  |   return new byte[0]; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * libsecp256k1 randomize - updates the context randomization | ||||||
|  |      * | ||||||
|  |      * @param seed 32-byte random seed | ||||||
|  |      */ | ||||||
|  |     public static synchronized boolean randomize(byte[] seed) throws AssertFailException{ | ||||||
|  |         Preconditions.checkArgument(seed.length == 32 || seed == null); | ||||||
|  | 
 | ||||||
|  |         ByteBuffer byteBuff = nativeECDSABuffer.get(); | ||||||
|  |         if (byteBuff == null || byteBuff.capacity() < seed.length) { | ||||||
|  |             byteBuff = ByteBuffer.allocateDirect(seed.length); | ||||||
|  |             byteBuff.order(ByteOrder.nativeOrder()); | ||||||
|  |             nativeECDSABuffer.set(byteBuff); | ||||||
|  |         } | ||||||
|  |         byteBuff.rewind(); | ||||||
|  |         byteBuff.put(seed); | ||||||
|  | 
 | ||||||
|  |         w.lock(); | ||||||
|  |         try { | ||||||
|  |           return secp256k1_context_randomize(byteBuff, Secp256k1Context.getContext()) == 1; | ||||||
|  |         } finally { | ||||||
|  |           w.unlock(); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public static byte[] schnorrSign(byte[] data, byte[] sec) throws AssertFailException { | ||||||
|  |         Preconditions.checkArgument(data.length == 32 && sec.length <= 32); | ||||||
|  | 
 | ||||||
|  |         ByteBuffer byteBuff = nativeECDSABuffer.get(); | ||||||
|  |         if (byteBuff == null) { | ||||||
|  |             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_schnorr_sign(byteBuff, Secp256k1Context.getContext()); | ||||||
|  |         } finally { | ||||||
|  |           r.unlock(); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         byte[] sigArr = retByteArray[0]; | ||||||
|  |         int retVal = new BigInteger(new byte[] { retByteArray[1][0] }).intValue(); | ||||||
|  | 
 | ||||||
|  |         assertEquals(sigArr.length, 64, "Got bad signature length."); | ||||||
|  | 
 | ||||||
|  |         return retVal == 0 ? new byte[0] : sigArr; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     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_privkey_export(ByteBuffer byteBuff, long context, int privLen, int compressed); | ||||||
|  | 
 | ||||||
|  |     private static native byte[][] secp256k1_ec_privkey_import(ByteBuffer byteBuff, long context, int privLen); | ||||||
|  | 
 | ||||||
|  |     private static native byte[][] secp256k1_ecdsa_signature_parse_der(ByteBuffer byteBuff, long context, int inputLen); | ||||||
|  | 
 | ||||||
|  |     //TODO sigNormalize() | ||||||
|  |     private static native byte[][] secp256k1_ecdsa_signature_normalize(ByteBuffer byteBuff, long context); | ||||||
|  | 
 | ||||||
|  |     private static native byte[][] secp256k1_ec_pubkey_parse(ByteBuffer byteBuff, long context, int inputLen); | ||||||
|  | 
 | ||||||
|  |     private static native long secp256k1_ecdsa_pubkey_combine(ByteBuffer byteBuff, long context, int keys); | ||||||
|  | 
 | ||||||
|  |     private static native byte[][] secp256k1_schnorr_sign(ByteBuffer byteBuff, long context); | ||||||
|  | 
 | ||||||
|  |     private static native byte[][] secp256k1_ecdh(ByteBuffer byteBuff, long context, int inputLen); | ||||||
|  | 
 | ||||||
| } | } | ||||||
|  | |||||||
							
								
								
									
										351
									
								
								src/java/org/bitcoin/NativeSecp256k1Test.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										351
									
								
								src/java/org/bitcoin/NativeSecp256k1Test.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,351 @@ | |||||||
|  | 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()); | ||||||
|  | 
 | ||||||
|  |         result = NativeSecp256k1.verify( data, sig, pub); | ||||||
|  |         assertEquals( result, true , "testVerifyPos"); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |       * This tests verify() for a non-valid signature | ||||||
|  |       */ | ||||||
|  |     public static void testVerifyNeg() throws AssertFailException{ | ||||||
|  |         boolean result = false; | ||||||
|  |         byte[] data = BaseEncoding.base16().lowerCase().decode("CF80CD8AED482D5D1527D7DC72FCEFF84E6326592848447D2DC0B0E87DFC9A91".toLowerCase()); //sha256hash of "testing" | ||||||
|  |         byte[] sig = BaseEncoding.base16().lowerCase().decode("3044022079BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F817980220294F14E883B3F525B5367756C2A11EF6CF84B730B36C17CB0C56F0AAB2C98589".toLowerCase()); | ||||||
|  |         byte[] pub = BaseEncoding.base16().lowerCase().decode("040A629506E1B65CD9D2E0BA9C75DF9C4FED0DB16DC9625ED14397F0AFC836FAE595DC53F8B0EFE61E703075BD9B143BAC75EC0E19F82A2208CAEB32BE53414C40".toLowerCase()); | ||||||
|  | 
 | ||||||
|  |         result = NativeSecp256k1.verify( data, sig, pub); | ||||||
|  |         //System.out.println(" TEST " + new BigInteger(1, resultbytes).toString(16)); | ||||||
|  |         assertEquals( result, false , "testVerifyNeg"); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |       * This tests secret key verify() for a valid secretkey | ||||||
|  |       */ | ||||||
|  |     public static void testSecKeyVerifyPos() throws AssertFailException{ | ||||||
|  |         boolean result = false; | ||||||
|  |         byte[] sec = BaseEncoding.base16().lowerCase().decode("67E56582298859DDAE725F972992A07C6C4FB9F62A8FFF58CE3CA926A1063530".toLowerCase()); | ||||||
|  | 
 | ||||||
|  |         result = NativeSecp256k1.secKeyVerify( sec ); | ||||||
|  |         //System.out.println(" TEST " + new BigInteger(1, resultbytes).toString(16)); | ||||||
|  |         assertEquals( result, true , "testSecKeyVerifyPos"); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |       * This tests secret key verify() for a invalid secretkey | ||||||
|  |       */ | ||||||
|  |     public static void testSecKeyVerifyNeg() throws AssertFailException{ | ||||||
|  |         boolean result = false; | ||||||
|  |         byte[] sec = BaseEncoding.base16().lowerCase().decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF".toLowerCase()); | ||||||
|  | 
 | ||||||
|  |         result = NativeSecp256k1.secKeyVerify( sec ); | ||||||
|  |         //System.out.println(" TEST " + new BigInteger(1, resultbytes).toString(16)); | ||||||
|  |         assertEquals( result, false , "testSecKeyVerifyNeg"); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |       * This tests public key create() for a valid secretkey | ||||||
|  |       */ | ||||||
|  |     public static void testPubKeyCreatePos() throws AssertFailException{ | ||||||
|  |         byte[] sec = BaseEncoding.base16().lowerCase().decode("67E56582298859DDAE725F972992A07C6C4FB9F62A8FFF58CE3CA926A1063530".toLowerCase()); | ||||||
|  | 
 | ||||||
|  |         byte[] resultArr = NativeSecp256k1.computePubkey( sec); | ||||||
|  |         String pubkeyString = javax.xml.bind.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[] resultArr = NativeSecp256k1.computePubkey( sec); | ||||||
|  |        String pubkeyString = javax.xml.bind.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[] resultArr = NativeSecp256k1.sign(data, sec); | ||||||
|  |         String sigString = javax.xml.bind.DatatypeConverter.printHexBinary(resultArr); | ||||||
|  |         assertEquals( sigString, "30440220182A108E1448DC8F1FB467D06A0F3BB8EA0533584CB954EF8DA112F1D60E39A202201C66F36DA211C087F3AF88B50EDF4F9BDAA6CF5FD6817E74DCA34DB12390C6E9" , "testSignPos"); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |       * This tests sign() for a invalid secretkey | ||||||
|  |       */ | ||||||
|  |     public static void testSignNeg() throws AssertFailException{ | ||||||
|  |         byte[] data = BaseEncoding.base16().lowerCase().decode("CF80CD8AED482D5D1527D7DC72FCEFF84E6326592848447D2DC0B0E87DFC9A90".toLowerCase()); //sha256hash of "testing" | ||||||
|  |         byte[] sec = BaseEncoding.base16().lowerCase().decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF".toLowerCase()); | ||||||
|  | 
 | ||||||
|  |         byte[] resultArr = NativeSecp256k1.sign(data, sec); | ||||||
|  |         String sigString = javax.xml.bind.DatatypeConverter.printHexBinary(resultArr); | ||||||
|  |         assertEquals( sigString, "" , "testSignNeg"); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |       * This tests private key export | ||||||
|  |       */ | ||||||
|  |     public static void testPrivKeyExportComp() throws AssertFailException{ | ||||||
|  |         byte[] sec = BaseEncoding.base16().lowerCase().decode("67E56582298859DDAE725F972992A07C6C4FB9F62A8FFF58CE3CA926A1063530".toLowerCase()); | ||||||
|  | 
 | ||||||
|  |         byte[] resultArr = NativeSecp256k1.privKeyExport( sec , 1); | ||||||
|  |         String sigString = javax.xml.bind.DatatypeConverter.printHexBinary(resultArr); | ||||||
|  |         assertEquals( sigString , "3081D3020101042067E56582298859DDAE725F972992A07C6C4FB9F62A8FFF58CE3CA926A1063530A08185308182020101302C06072A8648CE3D0101022100FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F300604010004010704210279BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798022100FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141020101A12403220002C591A8FF19AC9C4E4E5793673B83123437E975285E7B442F4EE2654DFFCA5E2D" , "Case 12"); | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |       * This tests private key export | ||||||
|  |       */ | ||||||
|  |     public static void testPrivKeyExportUncomp() throws AssertFailException{ | ||||||
|  |         byte[] sec = BaseEncoding.base16().lowerCase().decode("67E56582298859DDAE725F972992A07C6C4FB9F62A8FFF58CE3CA926A1063530".toLowerCase()); | ||||||
|  | 
 | ||||||
|  |         byte[] resultArr = NativeSecp256k1.privKeyExport( sec , 0); | ||||||
|  |         String sigString = javax.xml.bind.DatatypeConverter.printHexBinary(resultArr); | ||||||
|  |         assertEquals( sigString , "30820113020101042067E56582298859DDAE725F972992A07C6C4FB9F62A8FFF58CE3CA926A1063530A081A53081A2020101302C06072A8648CE3D0101022100FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F300604010004010704410479BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8022100FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141020101A14403420004C591A8FF19AC9C4E4E5793673B83123437E975285E7B442F4EE2654DFFCA5E2D2103ED494718C697AC9AEBCFD19612E224DB46661011863ED2FC54E71861E2A6" , "Case 13"); | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |       * This tests private key import | ||||||
|  |       */ | ||||||
|  |     public static void testSecKeyImportPos() throws AssertFailException { | ||||||
|  |         byte[] sec = BaseEncoding.base16().lowerCase().decode("3081D3020101042067E56582298859DDAE725F972992A07C6C4FB9F62A8FFF58CE3CA926A1063530A08185308182020101302C06072A8648CE3D0101022100FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F300604010004010704210279BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798022100FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141020101A12403220002C591A8FF19AC9C4E4E5793673B83123437E975285E7B442F4EE2654DFFCA5E2D".toLowerCase()); | ||||||
|  | 
 | ||||||
|  |         byte[] resultArr = NativeSecp256k1.secKeyImport( sec ); | ||||||
|  |         String sigString = javax.xml.bind.DatatypeConverter.printHexBinary(resultArr); | ||||||
|  | 
 | ||||||
|  |         assertEquals( sigString , "67E56582298859DDAE725F972992A07C6C4FB9F62A8FFF58CE3CA926A1063530" , "testSecKeyImport"); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |       * This tests private key export | ||||||
|  |       */ | ||||||
|  |     public static void testSecKeyImportPos2() throws AssertFailException { | ||||||
|  |         byte[] sec = BaseEncoding.base16().lowerCase().decode("30820113020101042067E56582298859DDAE725F972992A07C6C4FB9F62A8FFF58CE3CA926A1063530A081A53081A2020101302C06072A8648CE3D0101022100FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F300604010004010704410479BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8022100FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141020101A14403420004C591A8FF19AC9C4E4E5793673B83123437E975285E7B442F4EE2654DFFCA5E2D2103ED494718C697AC9AEBCFD19612E224DB46661011863ED2FC54E71861E2A6".toLowerCase()); | ||||||
|  | 
 | ||||||
|  |         byte[] resultArr = NativeSecp256k1.secKeyImport( sec ); | ||||||
|  |         String sigString = javax.xml.bind.DatatypeConverter.printHexBinary(resultArr); | ||||||
|  |         assertEquals( sigString , "67E56582298859DDAE725F972992A07C6C4FB9F62A8FFF58CE3CA926A1063530" , "testSecKeyImport2"); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |       * This tests private key tweak-add | ||||||
|  |       */ | ||||||
|  |     public static void testPrivKeyTweakAdd_1() throws AssertFailException { | ||||||
|  |         byte[] sec = BaseEncoding.base16().lowerCase().decode("67E56582298859DDAE725F972992A07C6C4FB9F62A8FFF58CE3CA926A1063530".toLowerCase()); | ||||||
|  |         byte[] data = BaseEncoding.base16().lowerCase().decode("3982F19BEF1615BCCFBB05E321C10E1D4CBA3DF0E841C2E41EEB6016347653C3".toLowerCase()); //sha256hash of "tweak" | ||||||
|  | 
 | ||||||
|  |         byte[] resultArr = NativeSecp256k1.privKeyTweakAdd( sec , data ); | ||||||
|  |         String sigString = javax.xml.bind.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[] resultArr = NativeSecp256k1.privKeyTweakMul( sec , data ); | ||||||
|  |         String sigString = javax.xml.bind.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[] resultArr = NativeSecp256k1.pubKeyTweakAdd( pub , data ); | ||||||
|  |         String sigString = javax.xml.bind.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[] resultArr = NativeSecp256k1.pubKeyTweakMul( pub , data ); | ||||||
|  |         String sigString = javax.xml.bind.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" | ||||||
|  |         boolean result = NativeSecp256k1.randomize(seed); | ||||||
|  |         assertEquals( result, true, "testRandomize"); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public static void testRecover() throws AssertFailException { | ||||||
|  | 
 | ||||||
|  |         /* TODO update this with functions from include/secp256k1_recovery.h | ||||||
|  |         //Case 17 | ||||||
|  |         data = BaseEncoding.base16().lowerCase().decode("CF80CD8AED482D5D1527D7DC72FCEFF84E6326592848447D2DC0B0E87DFC9A91".toLowerCase()); //sha256hash of "testing" | ||||||
|  |         sig = BaseEncoding.base16().lowerCase().decode("A33C093C80B84CA1AFBC8974EE3C42FC1CBC966CAE66612593CD1E44646BABFF00CB69703B98B0103AE22C7F9CCADD8DD98F9505BE7A66B1AE459576E930C4F6".toLowerCase()); | ||||||
|  |         pub = BaseEncoding.base16().lowerCase().decode("040A629506E1B65CD9D2E0BA9C75DF9C4FED0DB16DC9625ED14397F0AFC836FAE595DC53F8B0EFE61E703075BD9B143BAC75EC0E19F82A2208CAEB32BE53414C40".toLowerCase()); | ||||||
|  |         int recid = 1; | ||||||
|  | 
 | ||||||
|  |         resultArr = NativeSecp256k1.recoverCompact( data , sig , 0, recid ); | ||||||
|  |         sigString = javax.xml.bind.DatatypeConverter.printHexBinary(resultArr); | ||||||
|  |         assertEquals( sigString , "04C591A8FF19AC9C4E4E5793673B83123437E975285E7B442F4EE2654DFFCA5E2D2103ED494718C697AC9AEBCFD19612E224DB46661011863ED2FC54E71861E2A6" , "Case 17"); | ||||||
|  | 
 | ||||||
|  |         resultArr = NativeSecp256k1.recoverCompact( data , sig , 1, recid ); | ||||||
|  |         sigString = javax.xml.bind.DatatypeConverter.printHexBinary(resultArr); | ||||||
|  |         assertEquals( sigString , "02C591A8FF19AC9C4E4E5793673B83123437E975285E7B442F4EE2654DFFCA5E2D" , "Case 18"); | ||||||
|  |         */ | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public static void testRecoverCompact() throws AssertFailException { | ||||||
|  | 
 | ||||||
|  |         /* TODO update this with functions from include/secp256k1_recovery.h | ||||||
|  |         //Case 17 | ||||||
|  |         data = BaseEncoding.base16().lowerCase().decode("CF80CD8AED482D5D1527D7DC72FCEFF84E6326592848447D2DC0B0E87DFC9A91".toLowerCase()); //sha256hash of "testing" | ||||||
|  |         sig = BaseEncoding.base16().lowerCase().decode("A33C093C80B84CA1AFBC8974EE3C42FC1CBC966CAE66612593CD1E44646BABFF00CB69703B98B0103AE22C7F9CCADD8DD98F9505BE7A66B1AE459576E930C4F6".toLowerCase()); | ||||||
|  |         pub = BaseEncoding.base16().lowerCase().decode("040A629506E1B65CD9D2E0BA9C75DF9C4FED0DB16DC9625ED14397F0AFC836FAE595DC53F8B0EFE61E703075BD9B143BAC75EC0E19F82A2208CAEB32BE53414C40".toLowerCase()); | ||||||
|  |         int recid = 1; | ||||||
|  | 
 | ||||||
|  |         resultArr = NativeSecp256k1.recoverCompact( data , sig , 0, recid ); | ||||||
|  |         sigString = javax.xml.bind.DatatypeConverter.printHexBinary(resultArr); | ||||||
|  |         assertEquals( sigString , "04C591A8FF19AC9C4E4E5793673B83123437E975285E7B442F4EE2654DFFCA5E2D2103ED494718C697AC9AEBCFD19612E224DB46661011863ED2FC54E71861E2A6" , "Case 17"); | ||||||
|  | 
 | ||||||
|  |         resultArr = NativeSecp256k1.recoverCompact( data , sig , 1, recid ); | ||||||
|  |         sigString = javax.xml.bind.DatatypeConverter.printHexBinary(resultArr); | ||||||
|  |         assertEquals( sigString , "02C591A8FF19AC9C4E4E5793673B83123437E975285E7B442F4EE2654DFFCA5E2D" , "Case 18"); | ||||||
|  |         */ | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |       * This tests signSchnorr() for a valid secretkey | ||||||
|  |       */ | ||||||
|  |     public static void testSchnorrSign() throws AssertFailException{ | ||||||
|  | 
 | ||||||
|  |         byte[] data = BaseEncoding.base16().lowerCase().decode("CF80CD8AED482D5D1527D7DC72FCEFF84E6326592848447D2DC0B0E87DFC9A90".toLowerCase()); //sha256hash of "testing" | ||||||
|  |         byte[] sec = BaseEncoding.base16().lowerCase().decode("67E56582298859DDAE725F972992A07C6C4FB9F62A8FFF58CE3CA926A1063530".toLowerCase()); | ||||||
|  | 
 | ||||||
|  |         byte[] resultArr = NativeSecp256k1.schnorrSign(data, sec); | ||||||
|  |         String sigString = javax.xml.bind.DatatypeConverter.printHexBinary(resultArr); | ||||||
|  |         assertEquals( sigString, "C5E929AA058B982048760422D3B563749B7D0E50C5EBD8CD2FFC23214BD6A2F1B072C13880997EBA847CF20F2F90FCE07C1CA33A890A4127095A351127F8D95F" , "testSchnorrSign"); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |       * This tests signSchnorr() for a valid secretkey | ||||||
|  |       */ | ||||||
|  |     public static void testCreateECDHSecret() throws AssertFailException{ | ||||||
|  | 
 | ||||||
|  |         byte[] sec = BaseEncoding.base16().lowerCase().decode("67E56582298859DDAE725F972992A07C6C4FB9F62A8FFF58CE3CA926A1063530".toLowerCase()); | ||||||
|  |         byte[] pub = BaseEncoding.base16().lowerCase().decode("040A629506E1B65CD9D2E0BA9C75DF9C4FED0DB16DC9625ED14397F0AFC836FAE595DC53F8B0EFE61E703075BD9B143BAC75EC0E19F82A2208CAEB32BE53414C40".toLowerCase()); | ||||||
|  | 
 | ||||||
|  |         byte[] resultArr = NativeSecp256k1.createECDHSecret(sec, pub); | ||||||
|  |         String ecdhString = javax.xml.bind.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 privKeyExport() compressed/uncomp | ||||||
|  |         //testPrivKeyExportComp(); //Now in /contrib | ||||||
|  |         //testPrivKeyExportUncomp(); //Now in /contrib | ||||||
|  | 
 | ||||||
|  |         //Test secKeyImport()/2 | ||||||
|  |         //testSecKeyImportPos();  //Now in /contrib | ||||||
|  |         //testSecKeyImportPos2();  //Now in /contrib | ||||||
|  | 
 | ||||||
|  |         //Test recovery //TODO | ||||||
|  |         //testRecoverCompact(); | ||||||
|  |         //testRecover(); | ||||||
|  |         //testCreateRecoverable(); | ||||||
|  | 
 | ||||||
|  |         //Test ECDH //TODO | ||||||
|  |         //testECDHSecretGen(); | ||||||
|  | 
 | ||||||
|  |         //Test Schnorr (partial support) //TODO | ||||||
|  |         testSchnorrSign(); | ||||||
|  |         //testSchnorrVerify | ||||||
|  |         //testSchnorrRecovery | ||||||
|  | 
 | ||||||
|  |         //Test pubkeyCombine //TODO | ||||||
|  |         //test pubkeyCombine | ||||||
|  | 
 | ||||||
|  |         //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." ); | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										29
									
								
								src/java/org/bitcoin/NativeSecp256k1Util.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								src/java/org/bitcoin/NativeSecp256k1Util.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,29 @@ | |||||||
|  | package org.bitcoin; | ||||||
|  | 
 | ||||||
|  | public class NativeSecp256k1Util{ | ||||||
|  | 
 | ||||||
|  |     public static void assertEquals( int val, int val2, String message ) throws AssertFailException{ | ||||||
|  |       if( val != val2 ) | ||||||
|  |         throw new AssertFailException("FAIL: " + message); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public static void assertEquals( boolean val, boolean val2, String message ) throws AssertFailException{ | ||||||
|  |       if( val != val2 ) | ||||||
|  |         throw new AssertFailException("FAIL: " + message); | ||||||
|  |       else | ||||||
|  |         System.out.println("PASS: " + message); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public static void assertEquals( String val, String val2, String message ) throws AssertFailException{ | ||||||
|  |       if( !val.equals(val2) ) | ||||||
|  |         throw new AssertFailException("FAIL: " + message); | ||||||
|  |       else | ||||||
|  |         System.out.println("PASS: " + message); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public static class AssertFailException extends Exception { | ||||||
|  |       public AssertFailException(String message) { | ||||||
|  |         super( message ); | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										35
									
								
								src/java/org/bitcoin/Secp256k1Context.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								src/java/org/bitcoin/Secp256k1Context.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,35 @@ | |||||||
|  | package org.bitcoin; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * This class holds the context reference used in native methods  | ||||||
|  |    to handle ECDSA operations. | ||||||
|  |  */ | ||||||
|  | public class Secp256k1Context { | ||||||
|  |   private static final boolean enabled; //true if the library is loaded | ||||||
|  |   private static final long context; //ref to pointer to context obj | ||||||
|  | 
 | ||||||
|  |   static { //static initializer | ||||||
|  |       boolean isEnabled = true; | ||||||
|  |       long contextRef = -1; | ||||||
|  |       try { | ||||||
|  |           System.loadLibrary("secp256k1"); | ||||||
|  |           contextRef = secp256k1_init_context(); | ||||||
|  |       } catch (UnsatisfiedLinkError e) { | ||||||
|  |           System.out.println("UnsatisfiedLinkError: " + e.toString()); | ||||||
|  |           isEnabled = false; | ||||||
|  |       } | ||||||
|  |       enabled = isEnabled; | ||||||
|  |       context = contextRef; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   public static boolean isEnabled() { | ||||||
|  |      return enabled; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   public static long getContext() { | ||||||
|  |      if(!enabled) return -1; //sanity check | ||||||
|  |      return context; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   private static native long secp256k1_init_context(); | ||||||
|  | } | ||||||
| @ -1,23 +1,572 @@ | |||||||
|  | #include <stdlib.h> | ||||||
|  | #include <string.h> | ||||||
| #include "org_bitcoin_NativeSecp256k1.h" | #include "org_bitcoin_NativeSecp256k1.h" | ||||||
| #include "include/secp256k1.h" | #include "include/secp256k1.h" | ||||||
|  | #include "include/secp256k1_recovery.h" | ||||||
| 
 | 
 | ||||||
| JNIEXPORT jint JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ecdsa_1verify | 
 | ||||||
|   (JNIEnv* env, jclass classObject, jobject byteBufferObject) | SECP256K1_API jlong JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ctx_1clone | ||||||
|  |   (JNIEnv* env, jclass classObject, jlong ctx_l) | ||||||
| { | { | ||||||
| 	unsigned char* data = (unsigned char*) (*env)->GetDirectBufferAddress(env, byteBufferObject); |   const secp256k1_context *ctx = (secp256k1_context*)ctx_l; | ||||||
| 	int sigLen = *((int*)(data + 32)); | 
 | ||||||
| 	int pubLen = *((int*)(data + 32 + 4)); |   jlong ctx_clone_l = (jlong) secp256k1_context_clone(ctx); | ||||||
|  | 
 | ||||||
|  |   (void)classObject;(void)env; | ||||||
|  | 
 | ||||||
|  |   return (jlong)ctx_clone_l; | ||||||
| 
 | 
 | ||||||
| 	return secp256k1_ecdsa_verify(data, 32, data+32+8, sigLen, data+32+8+sigLen, pubLen); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void __javasecp256k1_attach(void) __attribute__((constructor)); | SECP256K1_API jint JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1context_1randomize | ||||||
| static void __javasecp256k1_detach(void) __attribute__((destructor)); |   (JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l) | ||||||
|  | { | ||||||
|  |   secp256k1_context *ctx = (secp256k1_context*)ctx_l; | ||||||
|  | 
 | ||||||
|  |   const unsigned char* seed = (unsigned char*) (*env)->GetDirectBufferAddress(env, byteBufferObject); | ||||||
|  | 
 | ||||||
|  |   (void)classObject; | ||||||
|  | 
 | ||||||
|  |   return secp256k1_context_randomize(ctx, seed); | ||||||
| 
 | 
 | ||||||
| static void __javasecp256k1_attach(void) { |  | ||||||
| 	secp256k1_start(SECP256K1_START_VERIFY); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void __javasecp256k1_detach(void) { | SECP256K1_API void JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1destroy_1context | ||||||
| 	secp256k1_stop(); |   (JNIEnv* env, jclass classObject, jlong ctx_l) | ||||||
|  | { | ||||||
|  |   secp256k1_context *ctx = (secp256k1_context*)ctx_l; | ||||||
|  | 
 | ||||||
|  |   secp256k1_context_destroy(ctx); | ||||||
|  | 
 | ||||||
|  |   (void)classObject;(void)env; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | SECP256K1_API jint JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ecdsa_1verify | ||||||
|  |   (JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l, jint siglen, jint publen) | ||||||
|  | { | ||||||
|  |   secp256k1_context *ctx = (secp256k1_context*)ctx_l; | ||||||
|  | 
 | ||||||
|  |   int result; | ||||||
|  |   unsigned char* data = (unsigned char*) (*env)->GetDirectBufferAddress(env, byteBufferObject); | ||||||
|  |   const unsigned char* sigdata = {  (unsigned char*) (data + 32) }; | ||||||
|  |   const unsigned char* pubdata = { (unsigned char*) (data + siglen + 32) }; | ||||||
|  | 
 | ||||||
|  |   secp256k1_ecdsa_signature sig; | ||||||
|  |   secp256k1_pubkey pubkey; | ||||||
|  | 
 | ||||||
|  |   int ret = secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigdata, siglen); | ||||||
|  | 
 | ||||||
|  |   if( ret ) { | ||||||
|  |     ret = secp256k1_ec_pubkey_parse(ctx, &pubkey, pubdata, publen); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   /*Debug
 | ||||||
|  |   printf("\nData: "); | ||||||
|  |   int i; | ||||||
|  |   for( i = 0; i < 32; i++) printf("%x", data[i]); | ||||||
|  |   printf("\nSig: "); | ||||||
|  |   for( i = 0; i < 64; i++) printf("%x", sig->data[i]); | ||||||
|  |   printf("\nPub: "); | ||||||
|  |   for( i = 0; i < 64; i++) printf("%x", pub->data[i]); | ||||||
|  |   */ | ||||||
|  | 
 | ||||||
|  |   (void)classObject; | ||||||
|  | 
 | ||||||
|  |   result = secp256k1_ecdsa_verify(ctx, &sig, data, &pubkey); | ||||||
|  | 
 | ||||||
|  |   return result; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ecdsa_1sign | ||||||
|  |   (JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l) | ||||||
|  | { | ||||||
|  |   secp256k1_context *ctx = (secp256k1_context*)ctx_l; | ||||||
|  |   unsigned char* data = (unsigned char*) (*env)->GetDirectBufferAddress(env, byteBufferObject); | ||||||
|  |   unsigned char* secKey = (unsigned char*) (data + 32); | ||||||
|  | 
 | ||||||
|  |   jobjectArray retArray; | ||||||
|  |   jbyteArray sigArray, intsByteArray; | ||||||
|  |   unsigned char intsarray[2]; | ||||||
|  | 
 | ||||||
|  |   secp256k1_ecdsa_signature sig[72]; | ||||||
|  | 
 | ||||||
|  |   int ret = secp256k1_ecdsa_sign(ctx, sig, data, secKey, NULL, NULL ); | ||||||
|  | 
 | ||||||
|  |   unsigned char outputSer[72]; | ||||||
|  |   size_t outputLen = 72; | ||||||
|  | 
 | ||||||
|  |   if( ret ) { | ||||||
|  |     int ret2 = secp256k1_ecdsa_signature_serialize_der(ctx,outputSer, &outputLen, sig ); (void)ret2; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   intsarray[0] = outputLen; | ||||||
|  |   intsarray[1] = ret; | ||||||
|  | 
 | ||||||
|  |   retArray = (*env)->NewObjectArray(env, 2, | ||||||
|  |     (*env)->FindClass(env, "[B"), | ||||||
|  |     (*env)->NewByteArray(env, 1)); | ||||||
|  | 
 | ||||||
|  |   sigArray = (*env)->NewByteArray(env, outputLen); | ||||||
|  |   (*env)->SetByteArrayRegion(env, sigArray, 0, outputLen, (jbyte*)outputSer); | ||||||
|  |   (*env)->SetObjectArrayElement(env, retArray, 0, sigArray); | ||||||
|  | 
 | ||||||
|  |   intsByteArray = (*env)->NewByteArray(env, 2); | ||||||
|  |   (*env)->SetByteArrayRegion(env, intsByteArray, 0, 2, (jbyte*)intsarray); | ||||||
|  |   (*env)->SetObjectArrayElement(env, retArray, 1, intsByteArray); | ||||||
|  | 
 | ||||||
|  |   (void)classObject; | ||||||
|  | 
 | ||||||
|  |   return retArray; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | SECP256K1_API jint JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ec_1seckey_1verify | ||||||
|  |   (JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l) | ||||||
|  | { | ||||||
|  |   secp256k1_context *ctx = (secp256k1_context*)ctx_l; | ||||||
|  |   unsigned char* secKey = (unsigned char*) (*env)->GetDirectBufferAddress(env, byteBufferObject); | ||||||
|  | 
 | ||||||
|  |   (void)classObject; | ||||||
|  | 
 | ||||||
|  |   return secp256k1_ec_seckey_verify(ctx, secKey); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ec_1pubkey_1create | ||||||
|  |   (JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l) | ||||||
|  | { | ||||||
|  |   secp256k1_context *ctx = (secp256k1_context*)ctx_l; | ||||||
|  |   const unsigned char* secKey = (unsigned char*) (*env)->GetDirectBufferAddress(env, byteBufferObject); | ||||||
|  | 
 | ||||||
|  |   secp256k1_pubkey pubkey; | ||||||
|  | 
 | ||||||
|  |   jobjectArray retArray; | ||||||
|  |   jbyteArray pubkeyArray, intsByteArray; | ||||||
|  |   unsigned char intsarray[2]; | ||||||
|  | 
 | ||||||
|  |   int ret = secp256k1_ec_pubkey_create(ctx, &pubkey, secKey); | ||||||
|  | 
 | ||||||
|  |   unsigned char outputSer[65]; | ||||||
|  |   size_t outputLen = 65; | ||||||
|  | 
 | ||||||
|  |   if( ret ) { | ||||||
|  |     int ret2 = secp256k1_ec_pubkey_serialize(ctx,outputSer, &outputLen, &pubkey,SECP256K1_EC_UNCOMPRESSED );(void)ret2; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   intsarray[0] = outputLen; | ||||||
|  |   intsarray[1] = ret; | ||||||
|  | 
 | ||||||
|  |   retArray = (*env)->NewObjectArray(env, 2, | ||||||
|  |     (*env)->FindClass(env, "[B"), | ||||||
|  |     (*env)->NewByteArray(env, 1)); | ||||||
|  | 
 | ||||||
|  |   pubkeyArray = (*env)->NewByteArray(env, outputLen); | ||||||
|  |   (*env)->SetByteArrayRegion(env, pubkeyArray, 0, outputLen, (jbyte*)outputSer); | ||||||
|  |   (*env)->SetObjectArrayElement(env, retArray, 0, pubkeyArray); | ||||||
|  | 
 | ||||||
|  |   intsByteArray = (*env)->NewByteArray(env, 2); | ||||||
|  |   (*env)->SetByteArrayRegion(env, intsByteArray, 0, 2, (jbyte*)intsarray); | ||||||
|  |   (*env)->SetObjectArrayElement(env, retArray, 1, intsByteArray); | ||||||
|  | 
 | ||||||
|  |   (void)classObject; | ||||||
|  | 
 | ||||||
|  |   return retArray; | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* TODO replace with contrib/ code */ | ||||||
|  | SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ec_1privkey_1export | ||||||
|  |   (JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l, jint privLen, jint compressed) | ||||||
|  | { | ||||||
|  |   secp256k1_context *ctx = (secp256k1_context*)ctx_l; | ||||||
|  | 
 | ||||||
|  |   const unsigned char* secKey = (unsigned char*) (*env)->GetDirectBufferAddress(env, byteBufferObject); | ||||||
|  | 
 | ||||||
|  |   int i, ret; | ||||||
|  |   jobjectArray retArray; | ||||||
|  |   jbyteArray privkeyArray, intsByteArray; | ||||||
|  |   unsigned char intsarray[2]; | ||||||
|  | 
 | ||||||
|  |   unsigned char* privkey = (unsigned char*) malloc(sizeof(unsigned char)*279); | ||||||
|  | 
 | ||||||
|  |   for(i = 0; i < privLen; i++) privkey[i] = secKey[i]; | ||||||
|  | 
 | ||||||
|  |   ret = secp256k1_ec_privkey_export(ctx, privkey , (size_t*)&privLen, secKey, compressed); | ||||||
|  | 
 | ||||||
|  |   intsarray[0] = privLen; | ||||||
|  |   intsarray[1] = ret; | ||||||
|  | 
 | ||||||
|  |   retArray = (*env)->NewObjectArray(env, 2, | ||||||
|  |     (*env)->FindClass(env, "[B"), | ||||||
|  |     (*env)->NewByteArray(env, 1)); | ||||||
|  | 
 | ||||||
|  |   privkeyArray = (*env)->NewByteArray(env, privLen); | ||||||
|  |   (*env)->SetByteArrayRegion(env, privkeyArray, 0, privLen, (jbyte*)privkey); | ||||||
|  |   (*env)->SetObjectArrayElement(env, retArray, 0, privkeyArray); | ||||||
|  | 
 | ||||||
|  |   intsByteArray = (*env)->NewByteArray(env, 2); | ||||||
|  |   (*env)->SetByteArrayRegion(env, intsByteArray, 0, 2, (jbyte*)intsarray); | ||||||
|  |   (*env)->SetObjectArrayElement(env, retArray, 1, intsByteArray); | ||||||
|  | 
 | ||||||
|  |   (void)classObject; | ||||||
|  | 
 | ||||||
|  |   return retArray; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* TODO replace with contrib/ code */ | ||||||
|  | SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ec_1privkey_1import | ||||||
|  |   (JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l, jint privLen) | ||||||
|  | { | ||||||
|  |   secp256k1_context *ctx = (secp256k1_context*)ctx_l; | ||||||
|  | 
 | ||||||
|  |   const unsigned char* secKey = (unsigned char*) (*env)->GetDirectBufferAddress(env, byteBufferObject); | ||||||
|  | 
 | ||||||
|  |   jobjectArray retArray; | ||||||
|  |   jbyteArray privkeyArray, intsByteArray; | ||||||
|  |   unsigned char intsarray[2]; | ||||||
|  | 
 | ||||||
|  |   unsigned char privkey[32]; | ||||||
|  | 
 | ||||||
|  |   int ret = secp256k1_ec_privkey_import(ctx, privkey, secKey, privLen); | ||||||
|  | 
 | ||||||
|  |   privLen = 32; | ||||||
|  | 
 | ||||||
|  |   intsarray[0] = privLen; | ||||||
|  |   intsarray[1] = ret; | ||||||
|  | 
 | ||||||
|  |   retArray = (*env)->NewObjectArray(env, 2, | ||||||
|  |     (*env)->FindClass(env, "[B"), | ||||||
|  |     (*env)->NewByteArray(env, 1)); | ||||||
|  | 
 | ||||||
|  |   privkeyArray = (*env)->NewByteArray(env, privLen); | ||||||
|  |   (*env)->SetByteArrayRegion(env, privkeyArray, 0, privLen, (jbyte*)privkey); | ||||||
|  |   (*env)->SetObjectArrayElement(env, retArray, 0, privkeyArray); | ||||||
|  | 
 | ||||||
|  |   intsByteArray = (*env)->NewByteArray(env, 2); | ||||||
|  |   (*env)->SetByteArrayRegion(env, intsByteArray, 0, 2, (jbyte*)intsarray); | ||||||
|  |   (*env)->SetObjectArrayElement(env, retArray, 1, intsByteArray); | ||||||
|  | 
 | ||||||
|  |   (void)classObject; | ||||||
|  | 
 | ||||||
|  |   return retArray; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /* TODO replace with serialize_compact() code */ | ||||||
|  | /*SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ecdsa_1sign_1compact
 | ||||||
|  |   (JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l) | ||||||
|  | { | ||||||
|  |   secp256k1_context *ctx = (secp256k1_context*)ctx_l; | ||||||
|  |   const unsigned char* data = (unsigned char*) (*env)->GetDirectBufferAddress(env, byteBufferObject); | ||||||
|  |   const unsigned char* secKey = (unsigned char*) (data + 32); | ||||||
|  | 
 | ||||||
|  |   jobjectArray retArray; | ||||||
|  |   jbyteArray sigArray, intsByteArray; | ||||||
|  |   unsigned char intsarray[2]; | ||||||
|  | 
 | ||||||
|  |   unsigned char sig[64]; | ||||||
|  |   int siglen = 64; | ||||||
|  |   int recID; | ||||||
|  | 
 | ||||||
|  |   int ret = secp256k1_ecdsa_sign_compact(ctx, data, sig, secKey, NULL, NULL, &recID ); | ||||||
|  | 
 | ||||||
|  |   intsarray[0] = recID; | ||||||
|  |   intsarray[1] = ret; | ||||||
|  | 
 | ||||||
|  |   retArray = (*env)->NewObjectArray(env, 2, | ||||||
|  |     (*env)->FindClass(env, "[B"), | ||||||
|  |     (*env)->NewByteArray(env, 1)); | ||||||
|  | 
 | ||||||
|  |   sigArray = (*env)->NewByteArray(env, siglen); | ||||||
|  |   (*env)->SetByteArrayRegion(env, sigArray, 0, siglen, (jbyte*)sig); | ||||||
|  |   (*env)->SetObjectArrayElement(env, retArray, 0, sigArray); | ||||||
|  | 
 | ||||||
|  |   intsByteArray = (*env)->NewByteArray(env, 2); | ||||||
|  |   (*env)->SetByteArrayRegion(env, intsByteArray, 0, 2, (jbyte*)intsarray); | ||||||
|  |   (*env)->SetObjectArrayElement(env, retArray, 1, intsByteArray); | ||||||
|  | 
 | ||||||
|  |   (void)classObject; | ||||||
|  | 
 | ||||||
|  |   return retArray; | ||||||
|  | }*/ | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /* TODO replace with recover_compact() code */ | ||||||
|  | /*
 | ||||||
|  | SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ecdsa_1recover_1compact | ||||||
|  |   (JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l, jint compressed, jint recid) | ||||||
|  | { | ||||||
|  |   secp256k1_context *ctx = (secp256k1_context*)ctx_l; | ||||||
|  |   const unsigned char* msg = (unsigned char*) (*env)->GetDirectBufferAddress(env, byteBufferObject); | ||||||
|  |   const unsigned char* sig = (unsigned char*) (msg + 32); | ||||||
|  | 
 | ||||||
|  |   jobjectArray retArray; | ||||||
|  |   jbyteArray pubArray, intsByteArray; | ||||||
|  |   unsigned char intsarray[2]; | ||||||
|  | 
 | ||||||
|  |   unsigned char pubkey[64]; | ||||||
|  |   int pubkeylen; | ||||||
|  | 
 | ||||||
|  |   int ret = secp256k1_ecdsa_recover_compact(ctx, msg, sig, pubkey, &pubkeylen, compressed, recid ); | ||||||
|  | 
 | ||||||
|  |   intsarray[0] = pubkeylen; | ||||||
|  |   intsarray[1] = ret; | ||||||
|  | 
 | ||||||
|  |   retArray = (*env)->NewObjectArray(env, 2, | ||||||
|  |     (*env)->FindClass(env, "[B"), | ||||||
|  |     (*env)->NewByteArray(env, 1)); | ||||||
|  | 
 | ||||||
|  |   pubArray = (*env)->NewByteArray(env, pubkeylen); | ||||||
|  |   (*env)->SetByteArrayRegion(env, pubArray, 0, pubkeylen, (jbyte*)pubkey); | ||||||
|  |   (*env)->SetObjectArrayElement(env, retArray, 0, pubArray); | ||||||
|  | 
 | ||||||
|  |   intsByteArray = (*env)->NewByteArray(env, 2); | ||||||
|  |   (*env)->SetByteArrayRegion(env, intsByteArray, 0, 2, (jbyte*)intsarray); | ||||||
|  |   (*env)->SetObjectArrayElement(env, retArray, 1, intsByteArray); | ||||||
|  | 
 | ||||||
|  |   (void)classObject; | ||||||
|  | 
 | ||||||
|  |   return retArray; | ||||||
|  | }*/ | ||||||
|  | 
 | ||||||
|  | SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1privkey_1tweak_1add | ||||||
|  |   (JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l) | ||||||
|  | { | ||||||
|  |   secp256k1_context *ctx = (secp256k1_context*)ctx_l; | ||||||
|  |   unsigned char* privkey = (unsigned char*) (*env)->GetDirectBufferAddress(env, byteBufferObject); | ||||||
|  |   const unsigned char* tweak = (unsigned char*) (privkey + 32); | ||||||
|  | 
 | ||||||
|  |   jobjectArray retArray; | ||||||
|  |   jbyteArray privArray, intsByteArray; | ||||||
|  |   unsigned char intsarray[2]; | ||||||
|  | 
 | ||||||
|  |   int privkeylen = 32; | ||||||
|  | 
 | ||||||
|  |   int ret = secp256k1_ec_privkey_tweak_add(ctx, privkey, tweak); | ||||||
|  | 
 | ||||||
|  |   intsarray[0] = privkeylen; | ||||||
|  |   intsarray[1] = ret; | ||||||
|  | 
 | ||||||
|  |   retArray = (*env)->NewObjectArray(env, 2, | ||||||
|  |     (*env)->FindClass(env, "[B"), | ||||||
|  |     (*env)->NewByteArray(env, 1)); | ||||||
|  | 
 | ||||||
|  |   privArray = (*env)->NewByteArray(env, privkeylen); | ||||||
|  |   (*env)->SetByteArrayRegion(env, privArray, 0, privkeylen, (jbyte*)privkey); | ||||||
|  |   (*env)->SetObjectArrayElement(env, retArray, 0, privArray); | ||||||
|  | 
 | ||||||
|  |   intsByteArray = (*env)->NewByteArray(env, 2); | ||||||
|  |   (*env)->SetByteArrayRegion(env, intsByteArray, 0, 2, (jbyte*)intsarray); | ||||||
|  |   (*env)->SetObjectArrayElement(env, retArray, 1, intsByteArray); | ||||||
|  | 
 | ||||||
|  |   (void)classObject; | ||||||
|  | 
 | ||||||
|  |   return retArray; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1privkey_1tweak_1mul | ||||||
|  |   (JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l) | ||||||
|  | { | ||||||
|  |   secp256k1_context *ctx = (secp256k1_context*)ctx_l; | ||||||
|  |   unsigned char* privkey = (unsigned char*) (*env)->GetDirectBufferAddress(env, byteBufferObject); | ||||||
|  |   const unsigned char* tweak = (unsigned char*) (privkey + 32); | ||||||
|  | 
 | ||||||
|  |   jobjectArray retArray; | ||||||
|  |   jbyteArray privArray, intsByteArray; | ||||||
|  |   unsigned char intsarray[2]; | ||||||
|  | 
 | ||||||
|  |   int privkeylen = 32; | ||||||
|  | 
 | ||||||
|  |   int ret = secp256k1_ec_privkey_tweak_mul(ctx, privkey, tweak); | ||||||
|  | 
 | ||||||
|  |   intsarray[0] = privkeylen; | ||||||
|  |   intsarray[1] = ret; | ||||||
|  | 
 | ||||||
|  |   retArray = (*env)->NewObjectArray(env, 2, | ||||||
|  |     (*env)->FindClass(env, "[B"), | ||||||
|  |     (*env)->NewByteArray(env, 1)); | ||||||
|  | 
 | ||||||
|  |   privArray = (*env)->NewByteArray(env, privkeylen); | ||||||
|  |   (*env)->SetByteArrayRegion(env, privArray, 0, privkeylen, (jbyte*)privkey); | ||||||
|  |   (*env)->SetObjectArrayElement(env, retArray, 0, privArray); | ||||||
|  | 
 | ||||||
|  |   intsByteArray = (*env)->NewByteArray(env, 2); | ||||||
|  |   (*env)->SetByteArrayRegion(env, intsByteArray, 0, 2, (jbyte*)intsarray); | ||||||
|  |   (*env)->SetObjectArrayElement(env, retArray, 1, intsByteArray); | ||||||
|  | 
 | ||||||
|  |   (void)classObject; | ||||||
|  | 
 | ||||||
|  |   return retArray; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1pubkey_1tweak_1add | ||||||
|  |   (JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l, jint publen) | ||||||
|  | { | ||||||
|  |   secp256k1_context *ctx = (secp256k1_context*)ctx_l; | ||||||
|  | /*  secp256k1_pubkey* pubkey = (secp256k1_pubkey*) (*env)->GetDirectBufferAddress(env, byteBufferObject);*/ | ||||||
|  |   unsigned char* pkey = (*env)->GetDirectBufferAddress(env, byteBufferObject); | ||||||
|  |   const unsigned char* tweak = (unsigned char*) (pkey + publen); | ||||||
|  | 
 | ||||||
|  |   jobjectArray retArray; | ||||||
|  |   jbyteArray pubArray, intsByteArray; | ||||||
|  |   unsigned char intsarray[2]; | ||||||
|  |   unsigned char outputSer[65]; | ||||||
|  |   size_t outputLen = 65; | ||||||
|  | 
 | ||||||
|  |   secp256k1_pubkey pubkey; | ||||||
|  |   int ret = secp256k1_ec_pubkey_parse(ctx, &pubkey, pkey, publen); | ||||||
|  | 
 | ||||||
|  |   if( ret ) { | ||||||
|  |     ret = secp256k1_ec_pubkey_tweak_add(ctx, &pubkey, tweak); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   if( ret ) { | ||||||
|  |     int ret2 = secp256k1_ec_pubkey_serialize(ctx,outputSer, &outputLen, &pubkey,SECP256K1_EC_UNCOMPRESSED );(void)ret2; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   intsarray[0] = outputLen; | ||||||
|  |   intsarray[1] = ret; | ||||||
|  | 
 | ||||||
|  |   retArray = (*env)->NewObjectArray(env, 2, | ||||||
|  |     (*env)->FindClass(env, "[B"), | ||||||
|  |     (*env)->NewByteArray(env, 1)); | ||||||
|  | 
 | ||||||
|  |   pubArray = (*env)->NewByteArray(env, outputLen); | ||||||
|  |   (*env)->SetByteArrayRegion(env, pubArray, 0, outputLen, (jbyte*)outputSer); | ||||||
|  |   (*env)->SetObjectArrayElement(env, retArray, 0, pubArray); | ||||||
|  | 
 | ||||||
|  |   intsByteArray = (*env)->NewByteArray(env, 2); | ||||||
|  |   (*env)->SetByteArrayRegion(env, intsByteArray, 0, 2, (jbyte*)intsarray); | ||||||
|  |   (*env)->SetObjectArrayElement(env, retArray, 1, intsByteArray); | ||||||
|  | 
 | ||||||
|  |   (void)classObject; | ||||||
|  | 
 | ||||||
|  |   return retArray; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1pubkey_1tweak_1mul | ||||||
|  |   (JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l, jint publen) | ||||||
|  | { | ||||||
|  |   secp256k1_context *ctx = (secp256k1_context*)ctx_l; | ||||||
|  |   unsigned char* pkey = (*env)->GetDirectBufferAddress(env, byteBufferObject); | ||||||
|  |   const unsigned char* tweak = (unsigned char*) (pkey + publen); | ||||||
|  | 
 | ||||||
|  |   jobjectArray retArray; | ||||||
|  |   jbyteArray pubArray, intsByteArray; | ||||||
|  |   unsigned char intsarray[2]; | ||||||
|  |   unsigned char outputSer[65]; | ||||||
|  |   size_t outputLen = 65; | ||||||
|  | 
 | ||||||
|  |   secp256k1_pubkey pubkey; | ||||||
|  |   int ret = secp256k1_ec_pubkey_parse(ctx, &pubkey, pkey, publen); | ||||||
|  | 
 | ||||||
|  |   if ( ret ) { | ||||||
|  |     ret = secp256k1_ec_pubkey_tweak_mul(ctx, &pubkey, tweak); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   if( ret ) { | ||||||
|  |     int ret2 = secp256k1_ec_pubkey_serialize(ctx,outputSer, &outputLen, &pubkey,SECP256K1_EC_UNCOMPRESSED );(void)ret2; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   intsarray[0] = outputLen; | ||||||
|  |   intsarray[1] = ret; | ||||||
|  | 
 | ||||||
|  |   retArray = (*env)->NewObjectArray(env, 2, | ||||||
|  |     (*env)->FindClass(env, "[B"), | ||||||
|  |     (*env)->NewByteArray(env, 1)); | ||||||
|  | 
 | ||||||
|  |   pubArray = (*env)->NewByteArray(env, outputLen); | ||||||
|  |   (*env)->SetByteArrayRegion(env, pubArray, 0, outputLen, (jbyte*)outputSer); | ||||||
|  |   (*env)->SetObjectArrayElement(env, retArray, 0, pubArray); | ||||||
|  | 
 | ||||||
|  |   intsByteArray = (*env)->NewByteArray(env, 2); | ||||||
|  |   (*env)->SetByteArrayRegion(env, intsByteArray, 0, 2, (jbyte*)intsarray); | ||||||
|  |   (*env)->SetObjectArrayElement(env, retArray, 1, intsByteArray); | ||||||
|  | 
 | ||||||
|  |   (void)classObject; | ||||||
|  | 
 | ||||||
|  |   return retArray; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | SECP256K1_API jlong JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ecdsa_1pubkey_1combine | ||||||
|  |   (JNIEnv * env, jclass classObject, jobject byteBufferObject, jlong ctx_l, jint numkeys) | ||||||
|  | { | ||||||
|  |   (void)classObject;(void)env;(void)byteBufferObject;(void)ctx_l;(void)numkeys; | ||||||
|  | 
 | ||||||
|  |   return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1schnorr_1sign | ||||||
|  |   (JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l) | ||||||
|  | { | ||||||
|  |   secp256k1_context *ctx = (secp256k1_context*)ctx_l; | ||||||
|  |   unsigned char* data = (unsigned char*) (*env)->GetDirectBufferAddress(env, byteBufferObject); | ||||||
|  |   unsigned char* secKey = (unsigned char*) (data + 32); | ||||||
|  | 
 | ||||||
|  |   jobjectArray retArray; | ||||||
|  |   jbyteArray sigArray, intsByteArray; | ||||||
|  |   unsigned char intsarray[1]; | ||||||
|  |   unsigned char sig[64]; | ||||||
|  | 
 | ||||||
|  |   int ret = secp256k1_schnorr_sign(ctx, sig, data, secKey, NULL, NULL); | ||||||
|  | 
 | ||||||
|  |   intsarray[0] = ret; | ||||||
|  | 
 | ||||||
|  |   retArray = (*env)->NewObjectArray(env, 2, | ||||||
|  |     (*env)->FindClass(env, "[B"), | ||||||
|  |     (*env)->NewByteArray(env, 1)); | ||||||
|  | 
 | ||||||
|  |   sigArray = (*env)->NewByteArray(env, 64); | ||||||
|  |   (*env)->SetByteArrayRegion(env, sigArray, 0, 64, (jbyte*)sig); | ||||||
|  |   (*env)->SetObjectArrayElement(env, retArray, 0, sigArray); | ||||||
|  | 
 | ||||||
|  |   intsByteArray = (*env)->NewByteArray(env, 1); | ||||||
|  |   (*env)->SetByteArrayRegion(env, intsByteArray, 0, 1, (jbyte*)intsarray); | ||||||
|  |   (*env)->SetObjectArrayElement(env, retArray, 1, intsByteArray); | ||||||
|  | 
 | ||||||
|  |   (void)classObject; | ||||||
|  | 
 | ||||||
|  |   return retArray; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ecdh | ||||||
|  |   (JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l, jint publen) | ||||||
|  | { | ||||||
|  |   secp256k1_context *ctx = (secp256k1_context*)ctx_l; | ||||||
|  |   const unsigned char* secdata = (*env)->GetDirectBufferAddress(env, byteBufferObject); | ||||||
|  |   const unsigned char* pubdata = (const unsigned char*) (secdata + 32); | ||||||
|  | 
 | ||||||
|  |   jobjectArray retArray; | ||||||
|  |   jbyteArray outArray, intsByteArray; | ||||||
|  |   unsigned char intsarray[1]; | ||||||
|  |   secp256k1_pubkey pubkey; | ||||||
|  |   unsigned char nonce_res[32]; | ||||||
|  |   size_t outputLen = 32; | ||||||
|  | 
 | ||||||
|  |   int ret = secp256k1_ec_pubkey_parse(ctx, &pubkey, pubdata, publen); | ||||||
|  | 
 | ||||||
|  |   if (ret) { | ||||||
|  |     ret = secp256k1_ecdh( | ||||||
|  |       ctx, | ||||||
|  |       nonce_res, | ||||||
|  |       &pubkey, | ||||||
|  |       secdata | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   intsarray[0] = ret; | ||||||
|  | 
 | ||||||
|  |   retArray = (*env)->NewObjectArray(env, 2, | ||||||
|  |     (*env)->FindClass(env, "[B"), | ||||||
|  |     (*env)->NewByteArray(env, 1)); | ||||||
|  | 
 | ||||||
|  |   outArray = (*env)->NewByteArray(env, outputLen); | ||||||
|  |   (*env)->SetByteArrayRegion(env, outArray, 0, 32, (jbyte*)nonce_res); | ||||||
|  |   (*env)->SetObjectArrayElement(env, retArray, 0, outArray); | ||||||
|  | 
 | ||||||
|  |   intsByteArray = (*env)->NewByteArray(env, 1); | ||||||
|  |   (*env)->SetByteArrayRegion(env, intsByteArray, 0, 1, (jbyte*)intsarray); | ||||||
|  |   (*env)->SetObjectArrayElement(env, retArray, 1, intsByteArray); | ||||||
|  | 
 | ||||||
|  |   (void)classObject; | ||||||
|  | 
 | ||||||
|  |   return retArray; | ||||||
| } | } | ||||||
| @ -1,5 +1,6 @@ | |||||||
| /* DO NOT EDIT THIS FILE - it is machine generated */ | /* DO NOT EDIT THIS FILE - it is machine generated */ | ||||||
| #include <jni.h> | #include <jni.h> | ||||||
|  | #include "include/secp256k1.h" | ||||||
| /* Header for class org_bitcoin_NativeSecp256k1 */ | /* Header for class org_bitcoin_NativeSecp256k1 */ | ||||||
| 
 | 
 | ||||||
| #ifndef _Included_org_bitcoin_NativeSecp256k1 | #ifndef _Included_org_bitcoin_NativeSecp256k1 | ||||||
| @ -9,11 +10,139 @@ extern "C" { | |||||||
| #endif | #endif | ||||||
| /*
 | /*
 | ||||||
|  * Class:     org_bitcoin_NativeSecp256k1 |  * Class:     org_bitcoin_NativeSecp256k1 | ||||||
|  * Method:    secp256k1_ecdsa_verify |  * Method:    secp256k1_ctx_clone | ||||||
|  * Signature: (Ljava/nio/ByteBuffer;)I |  * Signature: (J)J | ||||||
|  */ |  */ | ||||||
| JNIEXPORT jint JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ecdsa_1verify | SECP256K1_API jlong JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ctx_1clone | ||||||
|   (JNIEnv *, jclass, jobject); |   (JNIEnv *, jclass, jlong); | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * Class:     org_bitcoin_NativeSecp256k1 | ||||||
|  |  * Method:    secp256k1_context_randomize | ||||||
|  |  * Signature: (Ljava/nio/ByteBuffer;J)I | ||||||
|  |  */ | ||||||
|  | SECP256K1_API jint JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1context_1randomize | ||||||
|  |   (JNIEnv *, jclass, jobject, jlong); | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * Class:     org_bitcoin_NativeSecp256k1 | ||||||
|  |  * Method:    secp256k1_privkey_tweak_add | ||||||
|  |  * Signature: (Ljava/nio/ByteBuffer;J)[[B | ||||||
|  |  */ | ||||||
|  | SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1privkey_1tweak_1add | ||||||
|  |   (JNIEnv *, jclass, jobject, jlong); | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * Class:     org_bitcoin_NativeSecp256k1 | ||||||
|  |  * Method:    secp256k1_privkey_tweak_mul | ||||||
|  |  * Signature: (Ljava/nio/ByteBuffer;J)[[B | ||||||
|  |  */ | ||||||
|  | SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1privkey_1tweak_1mul | ||||||
|  |   (JNIEnv *, jclass, jobject, jlong); | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * Class:     org_bitcoin_NativeSecp256k1 | ||||||
|  |  * Method:    secp256k1_pubkey_tweak_add | ||||||
|  |  * Signature: (Ljava/nio/ByteBuffer;JI)[[B | ||||||
|  |  */ | ||||||
|  | SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1pubkey_1tweak_1add | ||||||
|  |   (JNIEnv *, jclass, jobject, jlong, jint); | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * Class:     org_bitcoin_NativeSecp256k1 | ||||||
|  |  * Method:    secp256k1_pubkey_tweak_mul | ||||||
|  |  * Signature: (Ljava/nio/ByteBuffer;JI)[[B | ||||||
|  |  */ | ||||||
|  | SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1pubkey_1tweak_1mul | ||||||
|  |   (JNIEnv *, jclass, jobject, jlong, jint); | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * Class:     org_bitcoin_NativeSecp256k1 | ||||||
|  |  * Method:    secp256k1_destroy_context | ||||||
|  |  * Signature: (J)V | ||||||
|  |  */ | ||||||
|  | SECP256K1_API void JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1destroy_1context | ||||||
|  |   (JNIEnv *, jclass, jlong); | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * Class:     org_bitcoin_NativeSecp256k1 | ||||||
|  |  * Method:    secp256k1_ecdsa_verify | ||||||
|  |  * Signature: (Ljava/nio/ByteBuffer;JII)I | ||||||
|  |  */ | ||||||
|  | SECP256K1_API jint JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ecdsa_1verify | ||||||
|  |   (JNIEnv *, jclass, jobject, jlong, jint, jint); | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * Class:     org_bitcoin_NativeSecp256k1 | ||||||
|  |  * Method:    secp256k1_ecdsa_sign | ||||||
|  |  * Signature: (Ljava/nio/ByteBuffer;J)[[B | ||||||
|  |  */ | ||||||
|  | SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ecdsa_1sign | ||||||
|  |   (JNIEnv *, jclass, jobject, jlong); | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * Class:     org_bitcoin_NativeSecp256k1 | ||||||
|  |  * Method:    secp256k1_ec_seckey_verify | ||||||
|  |  * Signature: (Ljava/nio/ByteBuffer;J)I | ||||||
|  |  */ | ||||||
|  | SECP256K1_API jint JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ec_1seckey_1verify | ||||||
|  |   (JNIEnv *, jclass, jobject, jlong); | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * Class:     org_bitcoin_NativeSecp256k1 | ||||||
|  |  * Method:    secp256k1_ec_pubkey_create | ||||||
|  |  * Signature: (Ljava/nio/ByteBuffer;J)[[B | ||||||
|  |  */ | ||||||
|  | SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ec_1pubkey_1create | ||||||
|  |   (JNIEnv *, jclass, jobject, jlong); | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * Class:     org_bitcoin_NativeSecp256k1 | ||||||
|  |  * Method:    secp256k1_ec_privkey_export | ||||||
|  |  * Signature: (Ljava/nio/ByteBuffer;JII)[[B | ||||||
|  |  */ | ||||||
|  | SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ec_1privkey_1export | ||||||
|  |   (JNIEnv *, jclass, jobject, jlong, jint, jint); | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * Class:     org_bitcoin_NativeSecp256k1 | ||||||
|  |  * Method:    secp256k1_ec_privkey_import | ||||||
|  |  * Signature: (Ljava/nio/ByteBuffer;JI)[[B | ||||||
|  |  */ | ||||||
|  | SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ec_1privkey_1import | ||||||
|  |   (JNIEnv *, jclass, jobject, jlong, jint); | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * Class:     org_bitcoin_NativeSecp256k1 | ||||||
|  |  * Method:    secp256k1_ecdsa_signature_parse_der | ||||||
|  |  * Signature: (Ljava/nio/ByteBuffer;JI)[[B | ||||||
|  |  */ | ||||||
|  | SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ecdsa_1signature_1parse_1der | ||||||
|  |   (JNIEnv *, jclass, jobject, jlong, jint); | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * Class:     org_bitcoin_NativeSecp256k1 | ||||||
|  |  * Method:    secp256k1_ecdsa_signature_normalize | ||||||
|  |  * Signature: (Ljava/nio/ByteBuffer;J)[[B | ||||||
|  |  */ | ||||||
|  | SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ecdsa_1signature_1normalize | ||||||
|  |   (JNIEnv *, jclass, jobject, jlong); | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * Class:     org_bitcoin_NativeSecp256k1 | ||||||
|  |  * Method:    secp256k1_ec_pubkey_parse | ||||||
|  |  * Signature: (Ljava/nio/ByteBuffer;JI)[[B | ||||||
|  |  */ | ||||||
|  | SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ec_1pubkey_1parse | ||||||
|  |   (JNIEnv *, jclass, jobject, jlong, jint); | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * Class:     org_bitcoin_NativeSecp256k1 | ||||||
|  |  * Method:    secp256k1_ecdsa_pubkey_combine | ||||||
|  |  * Signature: (Ljava/nio/ByteBuffer;JI)J | ||||||
|  |  */ | ||||||
|  | SECP256K1_API jlong JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ecdsa_1pubkey_1combine | ||||||
|  |   (JNIEnv *, jclass, jobject, jlong, jint); | ||||||
| 
 | 
 | ||||||
| #ifdef __cplusplus | #ifdef __cplusplus | ||||||
| } | } | ||||||
|  | |||||||
							
								
								
									
										14
									
								
								src/java/org_bitcoin_Secp256k1Context.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								src/java/org_bitcoin_Secp256k1Context.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,14 @@ | |||||||
|  | #include <stdlib.h> | ||||||
|  | #include "org_bitcoin_Secp256k1Context.h" | ||||||
|  | #include "include/secp256k1.h" | ||||||
|  | 
 | ||||||
|  | SECP256K1_API jlong JNICALL Java_org_bitcoin_Secp256k1Context_secp256k1_1init_1context | ||||||
|  |   (JNIEnv* env, jclass classObject) | ||||||
|  | { | ||||||
|  |   secp256k1_context *ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY); | ||||||
|  | 
 | ||||||
|  |   (void)classObject;(void)env; | ||||||
|  | 
 | ||||||
|  |   return (jlong)ctx; | ||||||
|  | } | ||||||
|  | 
 | ||||||
							
								
								
									
										22
									
								
								src/java/org_bitcoin_Secp256k1Context.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								src/java/org_bitcoin_Secp256k1Context.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,22 @@ | |||||||
|  | /* DO NOT EDIT THIS FILE - it is machine generated */ | ||||||
|  | #include <jni.h> | ||||||
|  | #include "include/secp256k1.h" | ||||||
|  | /* Header for class org_bitcoin_Secp256k1Context */ | ||||||
|  | 
 | ||||||
|  | #ifndef _Included_org_bitcoin_Secp256k1Context | ||||||
|  | #define _Included_org_bitcoin_Secp256k1Context | ||||||
|  | #ifdef __cplusplus | ||||||
|  | extern "C" { | ||||||
|  | #endif | ||||||
|  | /*
 | ||||||
|  |  * Class:     org_bitcoin_Secp256k1Context | ||||||
|  |  * Method:    secp256k1_init_context | ||||||
|  |  * Signature: ()J | ||||||
|  |  */ | ||||||
|  | SECP256K1_API jlong JNICALL Java_org_bitcoin_Secp256k1Context_secp256k1_1init_1context | ||||||
|  |   (JNIEnv *, jclass); | ||||||
|  | 
 | ||||||
|  | #ifdef __cplusplus | ||||||
|  | } | ||||||
|  | #endif | ||||||
|  | #endif | ||||||
| @ -4,8 +4,6 @@ | |||||||
|  * file COPYING or http://www.opensource.org/licenses/mit-license.php.*
 |  * file COPYING or http://www.opensource.org/licenses/mit-license.php.*
 | ||||||
|  **********************************************************************/ |  **********************************************************************/ | ||||||
| 
 | 
 | ||||||
| #define SECP256K1_BUILD (1) |  | ||||||
| 
 |  | ||||||
| #include "include/secp256k1.h" | #include "include/secp256k1.h" | ||||||
| 
 | 
 | ||||||
| #include "util.h" | #include "util.h" | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user