Browse Source

Merge pull request #5220

f9e40fb revert part of 9eda1620b (Cory Fields)
4300876 build: secp256k1 as a subdir, since it's required (Cory Fields)
0dc8613 build: fixup configure to not export anything (Cory Fields)
54566de depends: quit exporting in config.site (Cory Fields)
ff1e5ba depends: add gmp package (Cory Fields)
cf61b54 Don't use bashisms in configure (Pieter Wuille)
dffb8f8 Use libsecp256k1 in key.cpp (Pieter Wuille)
4c97c64 Do not use EC code in global constructors (Pieter Wuille)
07a9901 Always build and link libsecp256k1 (Pieter Wuille)
d48555b Squashed 'src/secp256k1/' content from commit ad2028f (Pieter Wuille)
7a7e109 Delete src/secp256k1 before subtree import (Pieter Wuille)
tags/v0.15.1
Wladimir J. van der Laan 5 years ago
parent
commit
271061242b
No account linked to committer's email address
67 changed files with 8548 additions and 120 deletions
  1. 27
    1
      configure.ac
  2. 21
    16
      depends/config.site.in
  3. 30
    0
      depends/packages/gmp.mk
  4. 1
    1
      depends/packages/packages.mk
  5. 21
    0
      depends/patches/gmp/arm_gmp_build_fix.patch
  6. 29
    0
      depends/patches/gmp/darwin_gmp_build_fix.patch
  7. 12
    23
      src/Makefile.am
  8. 1
    4
      src/Makefile.qt.include
  9. 1
    4
      src/Makefile.qttest.include
  10. 4
    5
      src/Makefile.test.include
  11. 6
    65
      src/key.cpp
  12. 35
    0
      src/secp256k1/.gitignore
  13. 25
    0
      src/secp256k1/.travis.yml
  14. 19
    0
      src/secp256k1/COPYING
  15. 88
    0
      src/secp256k1/Makefile.am
  16. 55
    0
      src/secp256k1/README.md
  17. 3
    0
      src/secp256k1/TODO
  18. 3
    0
      src/secp256k1/autogen.sh
  19. 90
    0
      src/secp256k1/build-aux/m4/bitcoin_secp.m4
  20. 259
    0
      src/secp256k1/configure.ac
  21. 252
    0
      src/secp256k1/include/secp256k1.h
  22. 13
    0
      src/secp256k1/libsecp256k1.pc.in
  23. 57
    0
      src/secp256k1/nasm_lt.sh
  24. 0
    0
      src/secp256k1/obj/.gitignore
  25. 41
    0
      src/secp256k1/src/bench_inv.c
  26. 49
    0
      src/secp256k1/src/bench_sign.c
  27. 44
    0
      src/secp256k1/src/bench_verify.c
  28. 23
    0
      src/secp256k1/src/ecdsa.h
  29. 183
    0
      src/secp256k1/src/ecdsa_impl.h
  30. 25
    0
      src/secp256k1/src/eckey.h
  31. 200
    0
      src/secp256k1/src/eckey_impl.h
  32. 19
    0
      src/secp256k1/src/ecmult.h
  33. 19
    0
      src/secp256k1/src/ecmult_gen.h
  34. 118
    0
      src/secp256k1/src/ecmult_gen_impl.h
  35. 222
    0
      src/secp256k1/src/ecmult_impl.h
  36. 114
    0
      src/secp256k1/src/field.h
  37. 21
    0
      src/secp256k1/src/field_10x26.h
  38. 884
    0
      src/secp256k1/src/field_10x26_impl.h
  39. 21
    0
      src/secp256k1/src/field_5x52.h
  40. 469
    0
      src/secp256k1/src/field_5x52_asm.asm
  41. 13
    0
      src/secp256k1/src/field_5x52_asm_impl.h
  42. 260
    0
      src/secp256k1/src/field_5x52_impl.h
  43. 279
    0
      src/secp256k1/src/field_5x52_int128_impl.h
  44. 18
    0
      src/secp256k1/src/field_gmp.h
  45. 163
    0
      src/secp256k1/src/field_gmp_impl.h
  46. 293
    0
      src/secp256k1/src/field_impl.h
  47. 128
    0
      src/secp256k1/src/group.h
  48. 519
    0
      src/secp256k1/src/group_impl.h
  49. 60
    0
      src/secp256k1/src/java/org/bitcoin/NativeSecp256k1.java
  50. 23
    0
      src/secp256k1/src/java/org_bitcoin_NativeSecp256k1.c
  51. 21
    0
      src/secp256k1/src/java/org_bitcoin_NativeSecp256k1.h
  52. 100
    0
      src/secp256k1/src/num.h
  53. 20
    0
      src/secp256k1/src/num_gmp.h
  54. 376
    0
      src/secp256k1/src/num_gmp_impl.h
  55. 22
    0
      src/secp256k1/src/num_impl.h
  56. 63
    0
      src/secp256k1/src/scalar.h
  57. 17
    0
      src/secp256k1/src/scalar_4x64.h
  58. 359
    0
      src/secp256k1/src/scalar_4x64_impl.h
  59. 17
    0
      src/secp256k1/src/scalar_8x32.h
  60. 572
    0
      src/secp256k1/src/scalar_8x32_impl.h
  61. 184
    0
      src/secp256k1/src/scalar_impl.h
  62. 305
    0
      src/secp256k1/src/secp256k1.c
  63. 26
    0
      src/secp256k1/src/testrand.h
  64. 60
    0
      src/secp256k1/src/testrand_impl.h
  65. 1080
    0
      src/secp256k1/src/tests.c
  66. 64
    0
      src/secp256k1/src/util.h
  67. 2
    1
      src/test/script_tests.cpp

+ 27
- 1
configure.ac View File

@@ -800,7 +800,6 @@ AC_SUBST(CLIENT_VERSION_BUILD, _CLIENT_VERSION_BUILD)
AC_SUBST(CLIENT_VERSION_IS_RELEASE, _CLIENT_VERSION_IS_RELEASE)
AC_SUBST(COPYRIGHT_YEAR, _COPYRIGHT_YEAR)


AC_SUBST(RELDFLAGS)
AC_SUBST(LIBTOOL_LDFLAGS)
AC_SUBST(USE_UPNP)
@@ -816,6 +815,33 @@ AC_SUBST(MINIUPNPC_LIBS)
AC_CONFIG_FILES([Makefile src/Makefile share/setup.nsi share/qt/Info.plist src/test/buildenv.py])
AC_CONFIG_FILES([qa/pull-tester/run-bitcoind-for-test.sh],[chmod +x qa/pull-tester/run-bitcoind-for-test.sh])
AC_CONFIG_FILES([qa/pull-tester/tests-config.sh],[chmod +x qa/pull-tester/tests-config.sh])

dnl boost's m4 checks do something really nasty: they export these vars. As a
dnl result, they leak into secp256k1's configure and crazy things happen.
dnl Until this is fixed upstream and we've synced, we'll just un-export them.
CPPFLAGS_TEMP="$CPPFLAGS"
unset CPPFLAGS
CPPFLAGS="$CPPFLAGS_TEMP"

LDFLAGS_TEMP="$LDFLAGS"
unset LDFLAGS
LDFLAGS="$LDFLAGS_TEMP"

LIBS_TEMP="$LIBS"
unset LIBS
LIBS="$LIBS_TEMP"

PKGCONFIG_PATH_TEMP="$PKG_CONFIG_PATH"
unset PKG_CONFIG_PATH
PKG_CONFIG_PATH="$PKGCONFIG_PATH_TEMP"

PKGCONFIG_LIBDIR_TEMP="$PKG_CONFIG_LIBDIR"
unset PKG_CONFIG_LIBDIR
PKG_CONFIG_LIBDIR="$PKGCONFIG_LIBDIR_TEMP"

ac_configure_args="${ac_configure_args} --disable-shared --with-pic"
AC_CONFIG_SUBDIRS([src/secp256k1])

AC_OUTPUT

dnl Taken from https://wiki.debian.org/RpathIssue

+ 21
- 16
depends/config.site.in View File

@@ -48,32 +48,37 @@ if test x@host_os@ = xmingw32; then
fi
fi

export PATH=$prefix/native/bin:$PATH
export PKG_CONFIG="`which pkg-config` --static"
PATH=$prefix/native/bin:$PATH
PKG_CONFIG="`which pkg-config` --static"

# These two need to remain exported because pkg-config does not see them
# otherwise. That means they must be unexported at the end of configure.ac to
# avoid ruining the cache. Sigh.

export PKG_CONFIG_LIBDIR=$prefix/lib/pkgconfig
export PKG_CONFIG_PATH=$prefix/share/pkgconfig

export CPPFLAGS="-I$prefix/include/ $CPPFLAGS"
export LDFLAGS="-L$prefix/lib $LDFLAGS"
CPPFLAGS="-I$prefix/include/ $CPPFLAGS"
LDFLAGS="-L$prefix/lib $LDFLAGS"

export CC="@CC@"
export CXX="@CXX@"
export OBJC="${CC}"
export OBJCXX="${CXX}"
export CCACHE=$prefix/native/bin/ccache
CC="@CC@"
CXX="@CXX@"
OBJC="${CC}"
OBJCXX="${CXX}"
CCACHE=$prefix/native/bin/ccache

if test -n "@AR@"; then
export AR=@AR@
AR=@AR@
ac_cv_path_ac_pt_AR=${AR}
fi

if test -n "@RANLIB@"; then
export RANLIB=@RANLIB@
RANLIB=@RANLIB@
ac_cv_path_ac_pt_RANLIB=${RANLIB}
fi

if test -n "@NM@"; then
export NM=@NM@
NM=@NM@
ac_cv_path_ac_pt_NM=${NM}
fi

@@ -82,14 +87,14 @@ if test -n "@debug@"; then
fi

if test -n "@CFLAGS@"; then
export CFLAGS="@CFLAGS@ $CFLAGS"
CFLAGS="@CFLAGS@ $CFLAGS"
fi
if test -n "@CXXFLAGS@"; then
export CXXFLAGS="@CXXFLAGS@ $CXXFLAGS"
CXXFLAGS="@CXXFLAGS@ $CXXFLAGS"
fi
if test -n "@CPPFLAGS@"; then
export CPPFLAGS="@CPPFLAGS@ $CPPFLAGS"
CPPFLAGS="@CPPFLAGS@ $CPPFLAGS"
fi
if test -n "@LDFLAGS@"; then
export LDFLAGS="@LDFLAGS@ $LDFLAGS"
LDFLAGS="@LDFLAGS@ $LDFLAGS"
fi

+ 30
- 0
depends/packages/gmp.mk View File

@@ -0,0 +1,30 @@
package=gmp
$(package)_version=6.0.0a
$(package)_download_path=https://gmplib.org/download/gmp
$(package)_file_name=$(package)-$($(package)_version).tar.bz2
$(package)_sha256_hash=7f8e9a804b9c6d07164cf754207be838ece1219425d64e28cfa3e70d5c759aaf
$(package)_patches=arm_gmp_build_fix.patch darwin_gmp_build_fix.patch

define $(package)_preprocess_cmds
patch -p1 < $($(package)_patch_dir)/arm_gmp_build_fix.patch && \
patch -p1 < $($(package)_patch_dir)/darwin_gmp_build_fix.patch
endef

define $(package)_set_vars
$(package)_config_opts=--disable-shared CC_FOR_BUILD=$(build_CC)
$(package)_config_opts_x86_64_darwin=--with-pic
$(package)_config_opts_x86_64_linux=--with-pic
$(package)_config_opts_arm_linux=--with-pic
endef

define $(package)_config_cmds
$($(package)_autoconf)
endef

define $(package)_build_cmds
$(MAKE)
endef

define $(package)_stage_cmds
$(MAKE) DESTDIR=$($(package)_staging_dir) install
endef

+ 1
- 1
depends/packages/packages.mk View File

@@ -1,4 +1,4 @@
packages:=boost openssl
packages:=boost openssl gmp
native_packages := native_ccache native_comparisontool

qt_native_packages = native_protobuf

+ 21
- 0
depends/patches/gmp/arm_gmp_build_fix.patch View File

@@ -0,0 +1,21 @@

# HG changeset patch
# User Torbjorn Granlund <tege@gmplib.org>
# Date 1396602422 -7200
# Node ID 676e2d0f0e4dd301a7066079d2c9326c25c34a40
# Parent 0194a75b56b21a9196626430af86c5bd9110c42d
Conditionalise ARM asm on !__thumb__.

diff -r 0194a75b56b2 -r 676e2d0f0e4d mpn/generic/div_qr_1n_pi1.c
--- a/mpn/generic/div_qr_1n_pi1.c Thu Apr 03 23:58:51 2014 +0200
+++ b/mpn/generic/div_qr_1n_pi1.c Fri Apr 04 11:07:02 2014 +0200
@@ -130,7 +130,7 @@
"%2" ((UDItype)(a0)), "r" ((UDItype)(b0)) __CLOBBER_CC)
#endif
-#if defined (__arm__) && W_TYPE_SIZE == 32
+#if defined (__arm__) && !defined (__thumb__) && W_TYPE_SIZE == 32
#define add_mssaaaa(m, sh, sl, ah, al, bh, bl) \
__asm__ ( "adds %2, %5, %6\n\t" \
"adcs %1, %3, %4\n\t" \


+ 29
- 0
depends/patches/gmp/darwin_gmp_build_fix.patch View File

@@ -0,0 +1,29 @@

# HG changeset patch
# User Torbjorn Granlund <tege@gmplib.org>
# Date 1396470504 -7200
# Node ID 1fab0adc5ff7d9ecddcbda96f407da58347bb49c
# Parent db645603dcdb41afcf78b19b551ecd5a01c3841c
Workaround for Darwin assembler quirk.

diff -r db645603dcdb -r 1fab0adc5ff7 mpn/x86_64/k8/redc_1.asm
--- a/mpn/x86_64/k8/redc_1.asm Mon Mar 31 23:04:32 2014 +0200
+++ b/mpn/x86_64/k8/redc_1.asm Wed Apr 02 22:28:24 2014 +0200
@@ -114,7 +114,7 @@
JUMPTABSECT
ALIGN(8)
-L(tab): JMPENT( L(0m4), L(tab))
+L(tab): JMPENT( L(0), L(tab))
JMPENT( L(1), L(tab))
JMPENT( L(2), L(tab))
JMPENT( L(3), L(tab))
@@ -397,6 +397,7 @@
ALIGN(16)
+L(0):
L(0m4):
L(lo0): mov (mp,nneg,8), %rax
mov nneg, i


+ 12
- 23
src/Makefile.am View File

@@ -1,9 +1,6 @@
DIST_SUBDIRS = secp256k1
AM_LDFLAGS = $(PTHREAD_CFLAGS) $(LIBTOOL_LDFLAGS)

if USE_LIBSECP256K1
secp256k1/libsecp256k1.la: $(wildcard secp256k1/src/*) $(wildcard secp256k1/include/*)
@$(MAKE) $(AM_MAKEFLAGS) -C $(@D) $(@F)
endif

if EMBEDDED_LEVELDB
LEVELDB_CPPFLAGS += -I$(srcdir)/leveldb/include
@@ -23,9 +20,7 @@ endif
BITCOIN_CONFIG_INCLUDES=-I$(builddir)/config
BITCOIN_INCLUDES=-I$(builddir) -I$(builddir)/obj $(BOOST_CPPFLAGS) $(LEVELDB_CPPFLAGS) $(CRYPTO_CFLAGS) $(SSL_CFLAGS)

if USE_LIBSECP256K1
BITCOIN_INCLUDES += -I$(srcdir)/secp256k1/include
endif

LIBBITCOIN_SERVER=libbitcoin_server.a
LIBBITCOIN_WALLET=libbitcoin_wallet.a
@@ -35,6 +30,10 @@ LIBBITCOIN_UTIL=libbitcoin_util.a
LIBBITCOIN_CRYPTO=crypto/libbitcoin_crypto.a
LIBBITCOIN_UNIVALUE=univalue/libbitcoin_univalue.a
LIBBITCOINQT=qt/libbitcoinqt.a
LIBSECP256K1=secp256k1/libsecp256k1.la

$(LIBSECP256K1): $(wildcard secp256k1/src/*) $(wildcard secp256k1/include/*)
$(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C $(@D) $(@F)

# Make is not made aware of per-object dependencies to avoid limiting building parallelization
# But to build the less dependent modules first, we manually select their order here:
@@ -281,11 +280,8 @@ bitcoind_LDADD = \
$(LIBBITCOIN_UTIL) \
$(LIBBITCOIN_CRYPTO) \
$(LIBLEVELDB) \
$(LIBMEMENV)

if USE_LIBSECP256K1
bitcoind_LDADD += secp256k1/libsecp256k1.la
endif
$(LIBMEMENV) \
$(LIBSECP256K1)

if ENABLE_WALLET
bitcoind_LDADD += libbitcoin_wallet.a
@@ -312,9 +308,6 @@ bitcoin_cli_LDADD = \
bitcoin_cli_SOURCES = \
bitcoin-cli.cpp

if USE_LIBSECP256K1
bitcoin_cli_LDADD += secp256k1/libsecp256k1.la
endif
bitcoin_cli_CPPFLAGS = $(BITCOIN_INCLUDES)
#

@@ -323,13 +316,9 @@ bitcoin_tx_LDADD = \
$(LIBBITCOIN_UNIVALUE) \
$(LIBBITCOIN_COMMON) \
$(LIBBITCOIN_UTIL) \
$(LIBBITCOIN_CRYPTO)

if USE_LIBSECP256K1
bitcoin_tx_LDADD += secp256k1/libsecp256k1.la
endif

bitcoin_tx_LDADD += $(BOOST_LIBS) \
$(LIBBITCOIN_CRYPTO) \
$(LIBSECP256K1) \
$(BOOST_LIBS) \
$(CRYPTO_LIBS)

bitcoin_tx_SOURCES = bitcoin-tx.cpp
@@ -346,11 +335,11 @@ CLEANFILES = leveldb/libleveldb.a leveldb/libmemenv.a *.gcda *.gcno

DISTCLEANFILES = obj/build.h

EXTRA_DIST = leveldb secp256k1
EXTRA_DIST = leveldb

clean-local:
-$(MAKE) -C leveldb clean
-$(MAKE) -C secp256k1 clean 2>/dev/null
-$(MAKE) -C secp256k1 clean
rm -f leveldb/*/*.gcno leveldb/helpers/memenv/*.gcno
-rm -f config.h


+ 1
- 4
src/Makefile.qt.include View File

@@ -360,10 +360,7 @@ if ENABLE_WALLET
qt_bitcoin_qt_LDADD += $(LIBBITCOIN_WALLET)
endif
qt_bitcoin_qt_LDADD += $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBBITCOIN_UTIL) $(LIBBITCOIN_CRYPTO) $(LIBBITCOIN_UNIVALUE) $(LIBLEVELDB) $(LIBMEMENV) \
$(BOOST_LIBS) $(QT_LIBS) $(QT_DBUS_LIBS) $(QR_LIBS) $(PROTOBUF_LIBS) $(BDB_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS)
if USE_LIBSECP256K1
qt_bitcoin_qt_LDADD += secp256k1/libsecp256k1.la
endif
$(BOOST_LIBS) $(QT_LIBS) $(QT_DBUS_LIBS) $(QR_LIBS) $(PROTOBUF_LIBS) $(BDB_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS) $(LIBSECP256K1)
qt_bitcoin_qt_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(QT_LDFLAGS)
qt_bitcoin_qt_LIBTOOLFLAGS = --tag CXX


+ 1
- 4
src/Makefile.qttest.include View File

@@ -32,10 +32,7 @@ qt_test_test_bitcoin_qt_LDADD += $(LIBBITCOIN_WALLET)
endif
qt_test_test_bitcoin_qt_LDADD += $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBBITCOIN_UTIL) $(LIBBITCOIN_CRYPTO) $(LIBBITCOIN_UNIVALUE) $(LIBLEVELDB) \
$(LIBMEMENV) $(BOOST_LIBS) $(QT_DBUS_LIBS) $(QT_TEST_LIBS) $(QT_LIBS) \
$(QR_LIBS) $(PROTOBUF_LIBS) $(BDB_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS)
if USE_LIBSECP256K1
qt_test_test_bitcoin_qt_LDADD += secp256k1/libsecp256k1.la
endif
$(QR_LIBS) $(PROTOBUF_LIBS) $(BDB_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS) $(LIBSECP256K1)
qt_test_test_bitcoin_qt_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(QT_LDFLAGS)

CLEAN_BITCOIN_QT_TEST = $(TEST_QT_MOC_CPP) qt/test/*.gcda qt/test/*.gcno

+ 4
- 5
src/Makefile.test.include View File

@@ -80,15 +80,11 @@ endif
test_test_bitcoin_SOURCES = $(BITCOIN_TESTS) $(JSON_TEST_FILES) $(RAW_TEST_FILES)
test_test_bitcoin_CPPFLAGS = $(BITCOIN_INCLUDES) -I$(builddir)/test/ $(TESTDEFS)
test_test_bitcoin_LDADD = $(LIBBITCOIN_SERVER) $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBBITCOIN_UTIL) $(LIBBITCOIN_CRYPTO) $(LIBBITCOIN_UNIVALUE) $(LIBLEVELDB) $(LIBMEMENV) \
$(BOOST_LIBS) $(BOOST_UNIT_TEST_FRAMEWORK_LIB)
$(BOOST_LIBS) $(BOOST_UNIT_TEST_FRAMEWORK_LIB) $(LIBSECP256K1)
if ENABLE_WALLET
test_test_bitcoin_LDADD += $(LIBBITCOIN_WALLET)
endif

if USE_LIBSECP256K1
test_test_bitcoin_LDADD += secp256k1/libsecp256k1.la
endif

test_test_bitcoin_LDADD += $(BDB_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS)
test_test_bitcoin_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS)

@@ -108,6 +104,9 @@ bitcoin_test_check: $(TEST_BINARY) FORCE
bitcoin_test_clean : FORCE
rm -f $(CLEAN_BITCOIN_TEST) $(test_test_bitcoin_OBJECTS) $(TEST_BINARY)

check-local:
$(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C secp256k1 check

%.json.h: %.json
@$(MKDIR_P) $(@D)
@echo "namespace json_tests{" > $@

+ 6
- 65
src/key.cpp View File

@@ -9,21 +9,16 @@
#include "pubkey.h"
#include "random.h"

#ifdef USE_SECP256K1
#include <secp256k1.h>
#else
#include "ecwrapper.h"
#endif

//! anonymous namespace
namespace {

#ifdef USE_SECP256K1
#include <secp256k1.h>
class CSecp256k1Init {
public:
CSecp256k1Init() {
secp256k1_start();
secp256k1_start(SECP256K1_START_SIGN);
}
~CSecp256k1Init() {
secp256k1_stop();
@@ -31,7 +26,6 @@ public:
};
static CSecp256k1Init instance_of_csecp256k1;

#endif
} // anon namespace

bool CKey::Check(const unsigned char *vch) {
@@ -47,15 +41,8 @@ void CKey::MakeNewKey(bool fCompressedIn) {
}

bool CKey::SetPrivKey(const CPrivKey &privkey, bool fCompressedIn) {
#ifdef USE_SECP256K1
if (!secp256k1_ecdsa_privkey_import((unsigned char*)begin(), &privkey[0], privkey.size()))
return false;
#else
CECKey key;
if (!key.SetPrivKey(&privkey[0], privkey.size()))
if (!secp256k1_ec_privkey_import((unsigned char*)begin(), &privkey[0], privkey.size()))
return false;
key.GetSecretBytes(vch);
#endif
fCompressed = fCompressedIn;
fValid = true;
return true;
@@ -65,39 +52,21 @@ CPrivKey CKey::GetPrivKey() const {
assert(fValid);
CPrivKey privkey;
int privkeylen, ret;
#ifdef USE_SECP256K1
privkey.resize(279);
privkeylen = 279;
ret = secp256k1_ecdsa_privkey_export(begin(), (unsigned char*)&privkey[0], &privkeylen, fCompressed);
ret = secp256k1_ec_privkey_export(begin(), (unsigned char*)&privkey[0], &privkeylen, fCompressed);
assert(ret);
privkey.resize(privkeylen);
#else
CECKey key;
key.SetSecretBytes(vch);
privkeylen = key.GetPrivKeySize(fCompressed);
assert(privkeylen);
privkey.resize(privkeylen);
ret = key.GetPrivKey(&privkey[0], fCompressed);
assert(ret == (int)privkey.size());
#endif
return privkey;
}

CPubKey CKey::GetPubKey() const {
assert(fValid);
CPubKey result;
#ifdef USE_SECP256K1
int clen = 65;
int ret = secp256k1_ecdsa_pubkey_create((unsigned char*)result.begin(), &clen, begin(), fCompressed);
int ret = secp256k1_ec_pubkey_create((unsigned char*)result.begin(), &clen, begin(), fCompressed);
assert((int)result.size() == clen);
assert(ret);
#else
std::vector<unsigned char> pubkey;
CECKey key;
key.SetSecretBytes(vch);
key.GetPubKey(pubkey, fCompressed);
result.Set(pubkey.begin(), pubkey.end());
#endif
assert(result.IsValid());
return result;
}
@@ -105,7 +74,6 @@ CPubKey CKey::GetPubKey() const {
bool CKey::Sign(const uint256 &hash, std::vector<unsigned char>& vchSig) const {
if (!fValid)
return false;
#ifdef USE_SECP256K1
vchSig.resize(72);
int nSigLen = 72;
CKey nonce;
@@ -116,11 +84,6 @@ bool CKey::Sign(const uint256 &hash, std::vector<unsigned char>& vchSig) const {
} while(true);
vchSig.resize(nSigLen);
return true;
#else
CECKey key;
key.SetSecretBytes(vch);
return key.Sign(hash, vchSig);
#endif
}

bool CKey::SignCompact(const uint256 &hash, std::vector<unsigned char>& vchSig) const {
@@ -128,34 +91,20 @@ bool CKey::SignCompact(const uint256 &hash, std::vector<unsigned char>& vchSig)
return false;
vchSig.resize(65);
int rec = -1;
#ifdef USE_SECP256K1
CKey nonce;
do {
nonce.MakeNewKey(true);
if (secp256k1_ecdsa_sign_compact((const unsigned char*)&hash, 32, &vchSig[1], begin(), nonce.begin(), &rec))
break;
} while(true);
#else
CECKey key;
key.SetSecretBytes(vch);
if (!key.SignCompact(hash, &vchSig[1], rec))
return false;
#endif
assert(rec != -1);
vchSig[0] = 27 + rec + (fCompressed ? 4 : 0);
return true;
}

bool CKey::Load(CPrivKey &privkey, CPubKey &vchPubKey, bool fSkipCheck=false) {
#ifdef USE_SECP256K1
if (!secp256k1_ecdsa_privkey_import((unsigned char*)begin(), &privkey[0], privkey.size()))
return false;
#else
CECKey key;
if (!key.SetPrivKey(&privkey[0], privkey.size(), fSkipCheck))
if (!secp256k1_ec_privkey_import((unsigned char*)begin(), &privkey[0], privkey.size()))
return false;
key.GetSecretBytes(vch);
#endif
fCompressed = vchPubKey.IsCompressed();
fValid = true;

@@ -182,12 +131,8 @@ bool CKey::Derive(CKey& keyChild, unsigned char ccChild[32], unsigned int nChild
BIP32Hash(cc, nChild, 0, begin(), out);
}
memcpy(ccChild, out+32, 32);
#ifdef USE_SECP256K1
memcpy((unsigned char*)keyChild.begin(), begin(), 32);
bool ret = secp256k1_ecdsa_privkey_tweak_add((unsigned char*)keyChild.begin(), out);
#else
bool ret = CECKey::TweakSecret((unsigned char*)keyChild.begin(), begin(), out);
#endif
bool ret = secp256k1_ec_privkey_tweak_add((unsigned char*)keyChild.begin(), out);
UnlockObject(out);
keyChild.fCompressed = true;
keyChild.fValid = ret;
@@ -245,9 +190,5 @@ void CExtKey::Decode(const unsigned char code[74]) {
}

bool ECC_InitSanityCheck() {
#ifdef USE_SECP256K1
return true;
#else
return CECKey::SanityCheck();
#endif
}

+ 35
- 0
src/secp256k1/.gitignore View File

@@ -0,0 +1,35 @@
bench_inv
bench_sign
bench_verify
tests
*.exe
*.so
*.a
!.gitignore

Makefile
configure
.libs/
Makefile.in
aclocal.m4
autom4te.cache/
config.log
config.status
*.tar.gz
*.la
libtool
.deps/
.dirstamp
build-aux/
*.lo
*.o
*~
src/libsecp256k1-config.h
src/libsecp256k1-config.h.in
m4/libtool.m4
m4/ltoptions.m4
m4/ltsugar.m4
m4/ltversion.m4
m4/lt~obsolete.m4
src/stamp-h1
libsecp256k1.pc

+ 25
- 0
src/secp256k1/.travis.yml View File

@@ -0,0 +1,25 @@
language: cpp
compiler: gcc
install:
- sudo apt-get install -qq libssl-dev
- if [ "$BIGNUM" = "gmp" -o "$BIGNUM" = "auto" -o "$FIELD" = "gmp" ]; then sudo apt-get install -qq libgmp-dev; fi
- if [ "$FIELD" = "64bit_asm" ]; then sudo apt-get install -qq yasm; fi
env:
global:
- FIELD=auto BIGNUM=auto SCALAR=auto ENDOMORPHISM=no BUILD=check EXTRAFLAGS=
matrix:
- SCALAR=32bit
- SCALAR=64bit
- FIELD=gmp
- FIELD=gmp ENDOMORPHISM=yes
- FIELD=64bit_asm
- FIELD=64bit_asm ENDOMORPHISM=yes
- FIELD=64bit
- FIELD=64bit ENDOMORPHISM=yes
- FIELD=32bit
- FIELD=32bit ENDOMORPHISM=yes
- BUILD=distcheck
- EXTRAFLAGS=CFLAGS=-DDETERMINISTIC
before_script: ./autogen.sh
script: ./configure --enable-endomorphism=$ENDOMORPHISM --with-field=$FIELD --with-bignum=$BIGNUM --with-scalar=$SCALAR $EXTRAFLAGS && make -j2 $BUILD
os: linux

+ 19
- 0
src/secp256k1/COPYING View File

@@ -0,0 +1,19 @@
Copyright (c) 2013 Pieter Wuille

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

+ 88
- 0
src/secp256k1/Makefile.am View File

@@ -0,0 +1,88 @@
ACLOCAL_AMFLAGS = -I build-aux/m4

lib_LTLIBRARIES = libsecp256k1.la
if USE_ASM
COMMON_LIB = libsecp256k1_common.la
else
COMMON_LIB =
endif
noinst_LTLIBRARIES = $(COMMON_LIB)
include_HEADERS = include/secp256k1.h
noinst_HEADERS =
noinst_HEADERS += src/scalar.h
noinst_HEADERS += src/scalar_4x64.h
noinst_HEADERS += src/scalar_8x32.h
noinst_HEADERS += src/scalar_impl.h
noinst_HEADERS += src/scalar_4x64_impl.h
noinst_HEADERS += src/scalar_8x32_impl.h
noinst_HEADERS += src/group.h
noinst_HEADERS += src/group_impl.h
noinst_HEADERS += src/num_gmp.h
noinst_HEADERS += src/num_gmp_impl.h
noinst_HEADERS += src/ecdsa.h
noinst_HEADERS += src/ecdsa_impl.h
noinst_HEADERS += src/eckey.h
noinst_HEADERS += src/eckey_impl.h
noinst_HEADERS += src/ecmult.h
noinst_HEADERS += src/ecmult_impl.h
noinst_HEADERS += src/ecmult_gen.h
noinst_HEADERS += src/ecmult_gen_impl.h
noinst_HEADERS += src/num.h
noinst_HEADERS += src/num_impl.h
noinst_HEADERS += src/field_10x26.h
noinst_HEADERS += src/field_10x26_impl.h
noinst_HEADERS += src/field_5x52.h
noinst_HEADERS += src/field_5x52_impl.h
noinst_HEADERS += src/field_5x52_int128_impl.h
noinst_HEADERS += src/field_5x52_asm_impl.h
noinst_HEADERS += src/java/org_bitcoin_NativeSecp256k1.h
noinst_HEADERS += src/util.h
noinst_HEADERS += src/testrand.h
noinst_HEADERS += src/testrand_impl.h
noinst_HEADERS += src/field_gmp.h
noinst_HEADERS += src/field_gmp_impl.h
noinst_HEADERS += src/field.h
noinst_HEADERS += src/field_impl.h

pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = libsecp256k1.pc

if USE_ASM
libsecp256k1_common_la_SOURCES = src/field_5x52_asm.asm
endif

libsecp256k1_la_SOURCES = src/secp256k1.c
libsecp256k1_la_CPPFLAGS = -I$(top_srcdir)/include $(SECP_INCLUDES)
libsecp256k1_la_LIBADD = $(COMMON_LIB) $(SECP_LIBS)


noinst_PROGRAMS =
if USE_BENCHMARK
noinst_PROGRAMS += bench_verify bench_sign bench_inv
bench_verify_SOURCES = src/bench_verify.c
bench_verify_LDADD = libsecp256k1.la $(SECP_LIBS)
bench_verify_LDFLAGS = -static
bench_sign_SOURCES = src/bench_sign.c
bench_sign_LDADD = libsecp256k1.la $(SECP_LIBS)
bench_sign_LDFLAGS = -static
bench_inv_SOURCES = src/bench_inv.c
bench_inv_LDADD = $(COMMON_LIB) $(SECP_LIBS)
bench_inv_LDFLAGS = -static
endif

if USE_TESTS
noinst_PROGRAMS += tests
tests_SOURCES = src/tests.c
tests_CPPFLAGS = -DVERIFY $(SECP_TEST_INCLUDES)
tests_LDADD = $(COMMON_LIB) $(SECP_LIBS) $(SECP_TEST_LIBS)
tests_LDFLAGS = -static
TESTS = tests
endif

EXTRA_DIST = autogen.sh nasm_lt.sh

#x86_64 only
if USE_ASM
.asm.lo:
$(LIBTOOL) --mode=compile --tag YASM $(srcdir)/nasm_lt.sh $(YASM) -f $(YASM_BINFMT) $(YAFLAGS) -I$(srcdir) -I. $< -o $@
endif

+ 55
- 0
src/secp256k1/README.md View File

@@ -0,0 +1,55 @@
libsecp256k1
============

[![Build Status](https://travis-ci.org/bitcoin/secp256k1.svg?branch=master)](https://travis-ci.org/bitcoin/secp256k1)

Optimized C library for EC operations on curve secp256k1.

This library is experimental, so use at your own risk.

Features:
* Low-level field and group operations on secp256k1.
* ECDSA signing/verification and key generation.
* Adding/multiplying private/public keys.
* Serialization/parsing of private keys, public keys, signatures.
* Very efficient implementation.

Implementation details
----------------------

* General
* Avoid dynamic memory usage almost everywhere.
* Field operations
* Optimized implementation of arithmetic modulo the curve's field size (2^256 - 0x1000003D1).
* Using 5 52-bit limbs (including hand-optimized assembly for x86_64, by Diederik Huys).
* Using 10 26-bit limbs.
* Using GMP.
* Field inverses and square roots using a sliding window over blocks of 1s (by Peter Dettman).
* Scalar operations
* Optimized implementation without data-dependent branches of arithmetic modulo the curve's order.
* Using 4 64-bit limbs (relying on __int128 support in the compiler).
* Using 8 32-bit limbs.
* Group operations
* Point addition formula specifically simplified for the curve equation (y^2 = x^3 + 7).
* Use addition between points in Jacobian and affine coordinates where possible.
* Use a unified addition/doubling formula where necessary to avoid data-dependent branches.
* Point multiplication for verification (a*P + b*G).
* Use wNAF notation for point multiplicands.
* Use a much larger window for multiples of G, using precomputed multiples.
* Use Shamir's trick to do the multiplication with the public key and the generator simultaneously.
* Optionally use secp256k1's efficiently-computable endomorphism to split the multiplicands into 4 half-sized ones first.
* Point multiplication for signing
* Use a precomputed table of multiples of powers of 16 multiplied with the generator, so general multiplication becomes a series of additions.
* Slice the precomputed table in memory per byte, so memory access to the table becomes uniform.
* No data-dependent branches
* The precomputed tables add and eventually subtract points for which no known scalar (private key) is known, preventing even an attacker with control over the private key used to control the data internally.

Build steps
-----------

libsecp256k1 is built using autotools:

$ ./autogen.sh
$ ./configure
$ make
$ sudo make install # optional

+ 3
- 0
src/secp256k1/TODO View File

@@ -0,0 +1,3 @@
* Unit tests for fieldelem/groupelem, including ones intended to
trigger fieldelem's boundary cases.
* Complete constant-time operations for signing/keygen

+ 3
- 0
src/secp256k1/autogen.sh View File

@@ -0,0 +1,3 @@
#!/bin/sh
set -e
autoreconf -if --warnings=all

+ 90
- 0
src/secp256k1/build-aux/m4/bitcoin_secp.m4 View File

@@ -0,0 +1,90 @@
dnl libsecp25k1 helper checks
AC_DEFUN([SECP_INT128_CHECK],[
has_int128=$ac_cv_type___int128
if test x"$has_int128" != x"yes" && test x"$set_field" = x"64bit"; then
AC_MSG_ERROR([$set_field field support explicitly requested but is not compatible with this host])
fi
if test x"$has_int128" != x"yes" && test x"$set_scalar" = x"64bit"; then
AC_MSG_ERROR([$set_scalar scalar support explicitly requested but is not compatible with this host])
fi
])

dnl
AC_DEFUN([SECP_64BIT_ASM_CHECK],[
if test x"$host_cpu" == x"x86_64"; then
AC_CHECK_PROG(YASM, yasm, yasm)
else
if test x"$set_field" = x"64bit_asm"; then
AC_MSG_ERROR([$set_field field support explicitly requested but is not compatible with this host])
fi
fi
if test x$YASM = x; then
if test x"$set_field" = x"64bit_asm"; then
AC_MSG_ERROR([$set_field field support explicitly requested but yasm was not found])
fi
has_64bit_asm=no
else
case x"$host_os" in
xdarwin*)
YASM_BINFMT=macho64
;;
x*-gnux32)
YASM_BINFMT=elfx32
;;
*)
YASM_BINFMT=elf64
;;
esac
if $YASM -f help | grep -q $YASM_BINFMT; then
has_64bit_asm=yes
else
if test x"$set_field" = x"64bit_asm"; then
AC_MSG_ERROR([$set_field field support explicitly requested but yasm doesn't support $YASM_BINFMT format])
fi
AC_MSG_WARN([yasm too old for $YASM_BINFMT format])
has_64bit_asm=no
fi
fi
])

dnl
AC_DEFUN([SECP_OPENSSL_CHECK],[
if test x"$use_pkgconfig" = x"yes"; then
: #NOP
m4_ifdef([PKG_CHECK_MODULES],[
PKG_CHECK_MODULES([CRYPTO], [libcrypto], [has_libcrypto=yes; AC_DEFINE(HAVE_LIBCRYPTO,1,[Define this symbol if libcrypto is installed])],[has_libcrypto=no])
: #NOP
])
else
AC_CHECK_HEADER(openssl/crypto.h,[AC_CHECK_LIB(crypto, main,[has_libcrypto=yes; CRYPTO_LIBS=-lcrypto; AC_DEFINE(HAVE_LIBCRYPTO,1,[Define this symbol if libcrypto is installed])]
)])
LIBS=
fi
if test x"$has_libcrypto" == x"yes" && test x"$has_openssl_ec" = x; then
AC_MSG_CHECKING(for EC functions in libcrypto)
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
#include <openssl/ec.h>
#include <openssl/ecdsa.h>
#include <openssl/obj_mac.h>]],[[
EC_KEY *eckey = EC_KEY_new_by_curve_name(NID_secp256k1);
ECDSA_sign(0, NULL, 0, NULL, NULL, eckey);
ECDSA_verify(0, NULL, 0, NULL, 0, eckey);
EC_KEY_free(eckey);
]])],[has_openssl_ec=yes],[has_openssl_ec=no])
AC_MSG_RESULT([$has_openssl_ec])
fi
])

dnl
AC_DEFUN([SECP_GMP_CHECK],[
if test x"$has_gmp" != x"yes"; then
AC_CHECK_HEADER(gmp.h,[AC_CHECK_LIB(gmp, __gmpz_init,[has_gmp=yes; GMP_LIBS=-lgmp; AC_DEFINE(HAVE_LIBGMP,1,[Define this symbol if libgmp is installed])])])
fi
if test x"$set_field" = x"gmp" && test x"$has_gmp" != x"yes"; then
AC_MSG_ERROR([$set_field field support explicitly requested but libgmp was not found])
fi
if test x"$set_bignum" = x"gmp" && test x"$has_gmp" != x"yes"; then
AC_MSG_ERROR([$set_bignum field support explicitly requested but libgmp was not found])
fi
])


+ 259
- 0
src/secp256k1/configure.ac View File

@@ -0,0 +1,259 @@
AC_PREREQ([2.60])
AC_INIT([libsecp256k1],[0.1])
AC_CONFIG_AUX_DIR([build-aux])
AC_CONFIG_MACRO_DIR([build-aux/m4])
AC_CANONICAL_HOST
AH_TOP([#ifndef LIBSECP256K1_CONFIG_H])
AH_TOP([#define LIBSECP256K1_CONFIG_H])
AH_BOTTOM([#endif //LIBSECP256K1_CONFIG_H])
AM_INIT_AUTOMAKE([foreign])
LT_INIT

dnl make the compilation flags quiet unless V=1 is used
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])

PKG_PROG_PKG_CONFIG

AC_PATH_TOOL(AR, ar)
AC_PATH_TOOL(RANLIB, ranlib)
AC_PATH_TOOL(STRIP, strip)

AC_PROG_CC_C99
if test x"$ac_cv_prog_cc_c99" == x"no"; then
AC_MSG_ERROR([c99 compiler support required])
fi

case $host in
*mingw*)
use_pkgconfig=no
;;
*)
use_pkgconfig=yes
;;
esac

case $host_os in
darwin*)
CPPFLAGS="$CPPFLAGS -I/opt/local/include"
LDFLAGS="$LDFLAGS -L/opt/local/lib"
;;
esac

CFLAGS="$CFLAGS -W"

warn_CFLAGS="-Wall -Wextra -Wcast-align -Wnested-externs -Wshadow -Wstrict-prototypes -Wno-unused-function"
saved_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS $warn_CFLAGS"
AC_MSG_CHECKING([if ${CC} supports ${warn_CFLAGS}])
AC_COMPILE_IFELSE([AC_LANG_SOURCE([[char foo;]])],
[ AC_MSG_RESULT([yes]) ],
[ AC_MSG_RESULT([no])
CFLAGS="$saved_CFLAGS"
])


AC_ARG_ENABLE(benchmark,
AS_HELP_STRING([--enable-benchmark],[compile benchmark (default is yes)]),
[use_benchmark=$enableval],
[use_benchmark=yes])

AC_ARG_ENABLE(tests,
AS_HELP_STRING([--enable-tests],[compile tests (default is yes)]),
[use_tests=$enableval],
[use_tests=yes])

AC_ARG_ENABLE(endomorphism,
AS_HELP_STRING([--enable-endomorphism],[enable endomorphism (default is no)]),
[use_endomorphism=$enableval],
[use_endomorphism=no])

AC_ARG_WITH([field], [AS_HELP_STRING([--with-field=gmp|64bit|64bit_asm|32bit|auto],
[Specify Field Implementation. Default is auto])],[req_field=$withval], [req_field=auto])

AC_ARG_WITH([bignum], [AS_HELP_STRING([--with-bignum=gmp|auto],
[Specify Bignum Implementation. Default is auto])],[req_bignum=$withval], [req_bignum=auto])

AC_ARG_WITH([scalar], [AS_HELP_STRING([--with-scalar=64bit|32bit|auto],
[Specify scalar implementation. Default is auto])],[req_scalar=$withval], [req_scalar=auto])

AC_CHECK_TYPES([__int128])

AC_CHECK_DECL(__builtin_expect,AC_DEFINE(HAVE_BUILTIN_EXPECT,1,[Define this symbol if __builtin_expect is available]),,)

if test x"$req_field" = x"auto"; then
SECP_64BIT_ASM_CHECK
if test x"$has_64bit_asm" = x"yes"; then
set_field=64bit_asm
fi

if test x"$set_field" = x; then
SECP_INT128_CHECK
if test x"$has_int128" = x"yes"; then
set_field=64bit
fi
fi

if test x"$set_field" = x; then
SECP_GMP_CHECK
if test x"$has_gmp" = x"yes"; then
set_field=gmp
fi
fi

if test x"$set_field" = x; then
set_field=32bit
fi
else
set_field=$req_field
case $set_field in
64bit_asm)
SECP_64BIT_ASM_CHECK
;;
64bit)
SECP_INT128_CHECK
;;
gmp)
SECP_GMP_CHECK
;;
32bit)
;;
*)
AC_MSG_ERROR([invalid field implementation selection])
;;
esac
fi

if test x"$req_scalar" = x"auto"; then
if test x"$set_scalar" = x; then
SECP_INT128_CHECK
if test x"$has_int128" = x"yes"; then
set_scalar=64bit
fi
fi
if test x"$set_scalar" = x; then
set_scalar=32bit
fi
else
set_scalar=$req_scalar
case $set_scalar in
64bit)
SECP_INT128_CHECK
;;
32bit)
;;
*)
AC_MSG_ERROR([invalid scalar implementation selected])
;;
esac
fi

if test x"$req_bignum" = x"auto"; then
SECP_GMP_CHECK
if test x"$has_gmp" = x"yes"; then
set_bignum=gmp
fi

if test x"$set_bignum" = x; then
AC_MSG_ERROR([no working bignum implementation found])
fi
else
set_bignum=$req_bignum
case $set_bignum in
gmp)
SECP_GMP_CHECK
;;
openssl)
SECP_OPENSSL_CHECK
;;
*)
AC_MSG_ERROR([invalid bignum implementation selection])
;;
esac
fi

# select field implementation
case $set_field in
64bit_asm)
AC_DEFINE(USE_FIELD_5X52_ASM, 1, [Define this symbol to use the assembly version for the 5x52 field implementation])
AC_DEFINE(USE_FIELD_5X52, 1, [Define this symbol to use the FIELD_5X52 implementation])
;;
64bit)
AC_DEFINE(USE_FIELD_5X52_INT128, 1, [Define this symbol to use the __int128 version for the 5x52 field implementation])
AC_DEFINE(USE_FIELD_5X52, 1, [Define this symbol to use the FIELD_5X52 implementation])
;;
gmp)
AC_DEFINE(HAVE_LIBGMP,1,[Define this symbol if libgmp is installed])
AC_DEFINE(USE_FIELD_GMP, 1, [Define this symbol to use the FIELD_GMP implementation])
;;
32bit)
AC_DEFINE(USE_FIELD_10X26, 1, [Define this symbol to use the FIELD_10X26 implementation])
;;
*)
AC_MSG_ERROR([invalid field implementation])
;;
esac

# select bignum implementation
case $set_bignum in
gmp)
AC_DEFINE(HAVE_LIBGMP,1,[Define this symbol if libgmp is installed])
AC_DEFINE(USE_NUM_GMP, 1, [Define this symbol to use the gmp implementation])
AC_DEFINE(USE_FIELD_INV_NUM, 1, [Define this symbol to use the USE_FIELD_INV_NUM implementation])
;;
*)
AC_MSG_ERROR([invalid bignum implementation])
;;
esac

#select scalar implementation
case $set_scalar in
64bit)
AC_DEFINE(USE_SCALAR_4X64, 1, [Define this symbol to use the 4x64 scalar implementation])
;;
32bit)
AC_DEFINE(USE_SCALAR_8X32, 1, [Define this symbol to use the 8x32 scalar implementation])
;;
*)
AC_MSG_ERROR([invalid scalar implementation])
;;
esac

if test x"$use_tests" = x"yes"; then
SECP_OPENSSL_CHECK
if test x"$has_openssl_ec" == x"yes"; then
AC_DEFINE(ENABLE_OPENSSL_TESTS, 1, [Define this symbol if OpenSSL EC functions are available])
SECP_TEST_INCLUDES="$SSL_CFLAGS $CRYPTO_CFLAGS"
SECP_TEST_LIBS="$CRYPTO_LIBS"

case $host in
*mingw*)
SECP_TEST_LIBS="$SECP_TEST_LIBS -lgdi32"
;;
esac

fi
fi

if test x"$set_field" = x"gmp" || test x"$set_bignum" = x"gmp"; then
SECP_LIBS="$SECP_LIBS $GMP_LIBS"
fi

if test x"$use_endomorphism" = x"yes"; then
AC_DEFINE(USE_ENDOMORPHISM, 1, [Define this symbol to use endomorphism])
fi

AC_MSG_NOTICE([Using field implementation: $set_field])
AC_MSG_NOTICE([Using bignum implementation: $set_bignum])
AC_MSG_NOTICE([Using scalar implementation: $set_scalar])

AC_CONFIG_HEADERS([src/libsecp256k1-config.h])
AC_CONFIG_FILES([Makefile libsecp256k1.pc])
AC_SUBST(SECP_INCLUDES)
AC_SUBST(SECP_LIBS)
AC_SUBST(SECP_TEST_LIBS)
AC_SUBST(SECP_TEST_INCLUDES)
AC_SUBST(YASM_BINFMT)
AM_CONDITIONAL([USE_ASM], [test x"$set_field" == x"64bit_asm"])
AM_CONDITIONAL([USE_TESTS], [test x"$use_tests" != x"no"])
AM_CONDITIONAL([USE_BENCHMARK], [test x"$use_benchmark" != x"no"])
AC_OUTPUT

+ 252
- 0
src/secp256k1/include/secp256k1.h View File

@@ -0,0 +1,252 @@
#ifndef _SECP256K1_
# define _SECP256K1_

# ifdef __cplusplus
extern "C" {
# endif

# if !defined(SECP256K1_GNUC_PREREQ)
# if defined(__GNUC__)&&defined(__GNUC_MINOR__)
# define SECP256K1_GNUC_PREREQ(_maj,_min) \
((__GNUC__<<16)+__GNUC_MINOR__>=((_maj)<<16)+(_min))
# else
# define SECP256K1_GNUC_PREREQ(_maj,_min) 0
# endif
# endif

# if (!defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L) )
# if SECP256K1_GNUC_PREREQ(3,0)
# define SECP256K1_RESTRICT __restrict__
# elif (defined(_MSC_VER) && _MSC_VER >= 1400)
# define SECP256K1_RESTRICT __restrict
# else
# define SECP256K1_RESTRICT
# endif
# else
# define SECP256K1_RESTRICT restrict
# endif

# if (!defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L) )
# if SECP256K1_GNUC_PREREQ(2,7)
# define SECP256K1_INLINE __inline__
# elif (defined(_MSC_VER))
# define SECP256K1_INLINE __inline
# else
# define SECP256K1_INLINE
# endif
# else
# define SECP256K1_INLINE inline
# endif

/**Warning attributes
* NONNULL is not used if SECP256K1_BUILD is set to avoid the compiler optimizing out
* some paranoid null checks. */
# if defined(__GNUC__) && SECP256K1_GNUC_PREREQ(3, 4)
# define SECP256K1_WARN_UNUSED_RESULT __attribute__ ((__warn_unused_result__))
# else
# define SECP256K1_WARN_UNUSED_RESULT
# endif
# if !defined(SECP256K1_BUILD) && defined(__GNUC__) && SECP256K1_GNUC_PREREQ(3, 4)
# define SECP256K1_ARG_NONNULL(_x) __attribute__ ((__nonnull__(_x)))
# else
# define SECP256K1_ARG_NONNULL(_x)
# endif


/** Flags to pass to secp256k1_start. */
# define SECP256K1_START_VERIFY (1 << 0)
# define SECP256K1_START_SIGN (1 << 1)

/** Initialize the library. This may take some time (10-100 ms).
* You need to call this before calling any other function.
* It cannot run in parallel with any other functions, but once
* secp256k1_start() returns, all other functions are thread-safe.
*/
void secp256k1_start(unsigned int flags);

/** Free all memory associated with this library. After this, no
* functions can be called anymore, except secp256k1_start()
*/
void secp256k1_stop(void);

/** Verify an ECDSA signature.
* Returns: 1: correct signature
* 0: incorrect signature
* -1: invalid public key
* -2: invalid signature
* In: msg: the message being verified (cannot be NULL)
* msglen: the length of the message (at most 32)
* sig: the signature being verified (cannot be NULL)
* siglen: the length of the signature
* pubkey: the public key to verify with (cannot be NULL)
* pubkeylen: the length of pubkey
* Requires starting using SECP256K1_START_VERIFY.
*/
SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdsa_verify(
const unsigned char *msg,
int msglen,
const unsigned char *sig,
int siglen,
const unsigned char *pubkey,
int pubkeylen
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(5);

/** Create an ECDSA signature.
* Returns: 1: signature created
* 0: nonce invalid, try another one
* In: msg: the message being signed (cannot be NULL)
* msglen: the length of the message being signed (at most 32)
* seckey: pointer to a 32-byte secret key (cannot be NULL, assumed to be valid)
* nonce: pointer to a 32-byte nonce (cannot be NULL, generated with a cryptographic PRNG)
* Out: sig: pointer to an array where the signature will be placed (cannot be NULL)
* In/Out: siglen: pointer to an int with the length of sig, which will be updated
* to contain the actual signature length (<=72).
* Requires starting using SECP256K1_START_SIGN.
*/
SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdsa_sign(
const unsigned char *msg,
int msglen,
unsigned char *sig,
int *siglen,
const unsigned char *seckey,
const unsigned char *nonce
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(5) SECP256K1_ARG_NONNULL(6);

/** Create a compact ECDSA signature (64 byte + recovery id).
* Returns: 1: signature created
* 0: nonce invalid, try another one
* In: msg: the message being signed (cannot be NULL)
* msglen: the length of the message being signed (at most 32)
* seckey: pointer to a 32-byte secret key (cannot be NULL, assumed to be valid)
* nonce: pointer to a 32-byte nonce (cannot be NULL, generated with a cryptographic PRNG)
* Out: sig: pointer to a 64-byte array where the signature will be placed (cannot be NULL)
* recid: pointer to an int, which will be updated to contain the recovery id (can be NULL)
* Requires starting using SECP256K1_START_SIGN.
*/
SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdsa_sign_compact(
const unsigned char *msg,
int msglen,
unsigned char *sig64,
const unsigned char *seckey,
const unsigned char *nonce,
int *recid
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(5);

/** Recover an ECDSA public key from a compact signature.
* Returns: 1: public key successfully recovered (which guarantees a correct signature).
* 0: otherwise.
* In: msg: the message assumed to be signed (cannot be NULL)
* msglen: the length of the message (at most 32)
* sig64: signature as 64 byte array (cannot be NULL)
* compressed: whether to recover a compressed or uncompressed pubkey
* recid: the recovery id (0-3, as returned by ecdsa_sign_compact)
* Out: pubkey: pointer to a 33 or 65 byte array to put the pubkey (cannot be NULL)
* pubkeylen: pointer to an int that will contain the pubkey length (cannot be NULL)
* Requires starting using SECP256K1_START_VERIFY.
*/
SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdsa_recover_compact(
const unsigned char *msg,
int msglen,
const unsigned char *sig64,
unsigned char *pubkey,
int *pubkeylen,
int compressed,
int recid
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4) SECP256K1_ARG_NONNULL(5);

/** Verify an ECDSA secret key.
* Returns: 1: secret key is valid
* 0: secret key is invalid
* In: seckey: pointer to a 32-byte secret key (cannot be NULL)
*/
SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_seckey_verify(const unsigned char *seckey) SECP256K1_ARG_NONNULL(1);

/** Just validate a public key.
* Returns: 1: valid public key
* 0: invalid public key
* In: pubkey: pointer to a 33-byte or 65-byte public key (cannot be NULL).
* pubkeylen: length of pubkey
*/
SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_verify(const unsigned char *pubkey, int pubkeylen) SECP256K1_ARG_NONNULL(1);

/** Compute the public key for a secret key.
* In: compressed: whether the computed public key should be compressed
* seckey: pointer to a 32-byte private key (cannot be NULL)
* Out: pubkey: pointer to a 33-byte (if compressed) or 65-byte (if uncompressed)
* area to store the public key (cannot be NULL)
* pubkeylen: pointer to int that will be updated to contains the pubkey's
* length (cannot be NULL)
* Returns: 1: secret was valid, public key stores
* 0: secret was invalid, try again.
* Requires starting using SECP256K1_START_SIGN.
*/
SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_create(
unsigned char *pubkey,
int *pubkeylen,
const unsigned char *seckey,
int compressed
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);

/** Decompress a public key.
* In/Out: pubkey: pointer to a 65-byte array to put the decompressed public key.
It must contain a 33-byte or 65-byte public key already (cannot be NULL)
* pubkeylen: pointer to the size of the public key pointed to by pubkey (cannot be NULL)
It will be updated to reflect the new size.
* Returns: 0 if the passed public key was invalid, 1 otherwise. If 1 is returned, the
pubkey is replaced with its decompressed version.
*/
SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_decompress(
unsigned char *pubkey,
int *pubkeylen
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2);

/** Export a private key in DER format. */
SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_export(
const unsigned char *seckey,
unsigned char *privkey,
int *privkeylen,
int compressed
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3);

/** Import a private key in DER format. */
SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_import(
unsigned char *seckey,
const unsigned char *privkey,
int privkeylen
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2);

/** Tweak a private key by adding tweak to it. */
SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_tweak_add(
unsigned char *seckey,
const unsigned char *tweak
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2);

/** Tweak a public key by adding tweak times the generator to it.
* Requires starting with SECP256K1_START_VERIFY.
*/
SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_tweak_add(
unsigned char *pubkey,
int pubkeylen,
const unsigned char *tweak
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(3);

/** Tweak a private key by multiplying it with tweak. */
SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_tweak_mul(
unsigned char *seckey,
const unsigned char *tweak
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2);

/** Tweak a public key by multiplying it with tweak.
* Requires starting with SECP256K1_START_VERIFY.
*/
SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_tweak_mul(
unsigned char *pubkey,
int pubkeylen,
const unsigned char *tweak
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(3);

# ifdef __cplusplus
}
# endif

#endif

+ 13
- 0
src/secp256k1/libsecp256k1.pc.in View File

@@ -0,0 +1,13 @@
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@

Name: libsecp256k1
Description: Optimized C library for EC operations on curve secp256k1
URL: https://github.com/bitcoin/secp256k1
Version: @PACKAGE_VERSION@
Cflags: -I${includedir}
Libs.private: @SECP_LIBS@
Libs: -L${libdir} -lsecp256k1


+ 57
- 0
src/secp256k1/nasm_lt.sh View File

@@ -0,0 +1,57 @@
#! /bin/sh
command=""
infile=""
o_opt=no
pic=no
while [ $# -gt 0 ]; do
case "$1" in
-DPIC|-fPIC|-fpic|-Kpic|-KPIC)
if [ "$pic" != "yes" ] ; then
command="$command -DPIC"
pic=yes
fi
;;
-f|-fbin|-faout|-faoutb|-fcoff|-felf|-felf64|-fas86| \
-fobj|-fwin32|-fwin64|-frdf|-fieee|-fmacho|-fmacho64)
# it's a file format specifier for nasm.
command="$command $1"
;;
-f*)
# maybe a code-generation flag for gcc.
;;
-[Ii]*)
incdir=`echo "$1" | sed 's/^-[Ii]//'`
if [ "x$incdir" = x -a "x$2" != x ] ; then
case "$2" in
-*) ;;
*) incdir="$2"; shift;;
esac
fi
if [ "x$incdir" != x ] ; then
# In the case of NASM, the trailing slash is necessary.
incdir=`echo "$incdir" | sed 's%/*$%/%'`
command="$command -I$incdir"
fi
;;
-o*)
o_opt=yes
command="$command $1"
;;
*.asm)
infile=$1
command="$command $1"
;;
*)
command="$command $1"
;;
esac
shift
done
if [ "$o_opt" != yes ] ; then
# By default, NASM creates an output file
# in the same directory as the input file.
outfile="-o `echo $infile | sed -e 's%^.*/%%' -e 's%\.[^.]*$%%'`.o"
command="$command $outfile"
fi
echo $command
exec $command

src/secp256k1/.empty → src/secp256k1/obj/.gitignore View File


+ 41
- 0
src/secp256k1/src/bench_inv.c View File

@@ -0,0 +1,41 @@
/**********************************************************************
* Copyright (c) 2014 Pieter Wuille *
* Distributed under the MIT software license, see the accompanying *
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
**********************************************************************/
#include <stdio.h>

#include "include/secp256k1.h"

#include "util.h"
#include "num_impl.h"
#include "field_impl.h"
#include "group_impl.h"
#include "scalar_impl.h"

int main(void) {
static const unsigned char init[32] = {
0x02, 0x03, 0x05, 0x07, 0x0b, 0x0d, 0x11, 0x13,
0x17, 0x1d, 0x1f, 0x25, 0x29, 0x2b, 0x2f, 0x35,
0x3b, 0x3d, 0x43, 0x47, 0x49, 0x4f, 0x53, 0x59,
0x61, 0x65, 0x67, 0x6b, 0x6d, 0x71, 0x7f, 0x83
};
static const unsigned char fini[32] = {
0xba, 0x28, 0x58, 0xd8, 0xaa, 0x11, 0xd6, 0xf2,
0xfa, 0xce, 0x50, 0xb1, 0x67, 0x19, 0xb1, 0xa6,
0xe0, 0xaa, 0x84, 0x53, 0xf6, 0x80, 0xfc, 0x23,
0x88, 0x3c, 0xd6, 0x74, 0x9f, 0x27, 0x09, 0x03
};
secp256k1_ge_start();
secp256k1_scalar_t base, x;
secp256k1_scalar_set_b32(&base, init, NULL);
secp256k1_scalar_set_b32(&x, init, NULL);
for (int i=0; i<1000000; i++) {
secp256k1_scalar_inverse(&x, &x);
secp256k1_scalar_add(&x, &x, &base);
}
unsigned char res[32];
secp256k1_scalar_get_b32(res, &x);
CHECK(memcmp(res, fini, 32) == 0);
return 0;
}

+ 49
- 0
src/secp256k1/src/bench_sign.c View File

@@ -0,0 +1,49 @@
/**********************************************************************
* Copyright (c) 2014 Pieter Wuille *
* Distributed under the MIT software license, see the accompanying *
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
**********************************************************************/
#include <stdio.h>
#include <string.h>

#include "include/secp256k1.h"
#include "util.h"

int main(void) {
secp256k1_start(SECP256K1_START_SIGN);

unsigned char msg[32];
unsigned char nonce[32];
unsigned char key[32];

for (int i = 0; i < 32; i++) msg[i] = i + 1;
for (int i = 0; i < 32; i++) nonce[i] = i + 33;
for (int i = 0; i < 32; i++) key[i] = i + 65;

unsigned char sig[64];

for (int i=0; i<1000000; i++) {
int recid = 0;
CHECK(secp256k1_ecdsa_sign_compact(msg, 32, sig, key, nonce, &recid));
for (int j = 0; j < 32; j++) {
nonce[j] = key[j]; /* Move former key to nonce */
msg[j] = sig[j]; /* Move former R to message. */
key[j] = sig[j + 32]; /* Move former S to key. */
}
}

static const unsigned char fini[64] = {
0x92, 0x03, 0xef, 0xf1, 0x58, 0x0b, 0x49, 0x8d,
0x22, 0x3d, 0x49, 0x0e, 0xbf, 0x26, 0x50, 0x0e,
0x2d, 0x62, 0x90, 0xd7, 0x82, 0xbd, 0x3d, 0x5c,
0xa9, 0x10, 0xa5, 0x49, 0xb1, 0xd8, 0x8c, 0xc0,
0x5b, 0x5e, 0x9e, 0x68, 0x51, 0x3d, 0xe8, 0xec,
0x82, 0x30, 0x82, 0x88, 0x8c, 0xfd, 0xe7, 0x71,
0x15, 0x92, 0xfc, 0x14, 0x59, 0x78, 0x31, 0xb3,
0xf6, 0x07, 0x91, 0x18, 0x00, 0x8d, 0x4c, 0xb2
};
CHECK(memcmp(sig, fini, 64) == 0);

secp256k1_stop();
return 0;
}

+ 44
- 0
src/secp256k1/src/bench_verify.c View File

@@ -0,0 +1,44 @@
/**********************************************************************
* Copyright (c) 2014 Pieter Wuille *
* Distributed under the MIT software license, see the accompanying *
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
**********************************************************************/

#include <stdio.h>
#include <string.h>

#include "include/secp256k1.h"
#include "util.h"

int main(void) {
secp256k1_start(SECP256K1_START_VERIFY);

unsigned char msg[32];
unsigned char sig[64];

for (int i = 0; i < 32; i++) msg[i] = 1 + i;
for (int i = 0; i < 64; i++) sig[i] = 65 + i;

unsigned char pubkey[33];
for (int i=0; i<1000000; i++) {
int pubkeylen = 33;
CHECK(secp256k1_ecdsa_recover_compact(msg, 32, sig, pubkey, &pubkeylen, 1, i % 2));
for (int j = 0; j < 32; j++) {
sig[j + 32] = msg[j]; /* Move former message to S. */
msg[j] = sig[j]; /* Move former R to message. */
sig[j] = pubkey[j + 1]; /* Move recovered pubkey X coordinate to R (which must be a valid X coordinate). */
}
}

static const unsigned char fini[33] = {
0x02,
0x52, 0x63, 0xae, 0x9a, 0x9d, 0x47, 0x1f, 0x1a,
0xb2, 0x36, 0x65, 0x89, 0x11, 0xe7, 0xcc, 0x86,
0xa3, 0xab, 0x97, 0xb6, 0xf1, 0xaf, 0xfd, 0x8f,
0x9b, 0x38, 0xb6, 0x18, 0x55, 0xe5, 0xc2, 0x43
};
CHECK(memcmp(fini, pubkey, 33) == 0);

secp256k1_stop();
return 0;
}

+ 23
- 0
src/secp256k1/src/ecdsa.h View File

@@ -0,0 +1,23 @@
/**********************************************************************
* Copyright (c) 2013, 2014 Pieter Wuille *
* Distributed under the MIT software license, see the accompanying *
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
**********************************************************************/

#ifndef _SECP256K1_ECDSA_
#define _SECP256K1_ECDSA_

#include "num.h"

typedef struct {
secp256k1_num_t r, s;
} secp256k1_ecdsa_sig_t;

static int secp256k1_ecdsa_sig_parse(secp256k1_ecdsa_sig_t *r, const unsigned char *sig, int size);
static int secp256k1_ecdsa_sig_serialize(unsigned char *sig, int *size, const secp256k1_ecdsa_sig_t *a);
static int secp256k1_ecdsa_sig_verify(const secp256k1_ecdsa_sig_t *sig, const secp256k1_ge_t *pubkey, const secp256k1_num_t *message);
static int secp256k1_ecdsa_sig_sign(secp256k1_ecdsa_sig_t *sig, const secp256k1_scalar_t *seckey, const secp256k1_scalar_t *message, const secp256k1_scalar_t *nonce, int *recid);
static int secp256k1_ecdsa_sig_recover(const secp256k1_ecdsa_sig_t *sig, secp256k1_ge_t *pubkey, const secp256k1_num_t *message, int recid);
static void secp256k1_ecdsa_sig_set_rs(secp256k1_ecdsa_sig_t *sig, const secp256k1_num_t *r, const secp256k1_num_t *s);

#endif

+ 183
- 0
src/secp256k1/src/ecdsa_impl.h View File

@@ -0,0 +1,183 @@
/**********************************************************************
* Copyright (c) 2013, 2014 Pieter Wuille *
* Distributed under the MIT software license, see the accompanying *
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
**********************************************************************/


#ifndef _SECP256K1_ECDSA_IMPL_H_
#define _SECP256K1_ECDSA_IMPL_H_

#include "num.h"
#include "field.h"
#include "group.h"
#include "ecmult.h"
#include "ecmult_gen.h"
#include "ecdsa.h"

static int secp256k1_ecdsa_sig_parse(secp256k1_ecdsa_sig_t *r, const unsigned char *sig, int size) {
if (sig[0] != 0x30) return 0;
int lenr = sig[3];
if (5+lenr >= size) return 0;
int lens = sig[lenr+5];
if (sig[1] != lenr+lens+4) return 0;
if (lenr+lens+6 > size) return 0;
if (sig[2] != 0x02) return 0;
if (lenr == 0) return 0;
if (sig[lenr+4] != 0x02) return 0;
if (lens == 0) return 0;
secp256k1_num_set_bin(&r->r, sig+4, lenr);
secp256k1_num_set_bin(&r->s, sig+6+lenr, lens);
return 1;
}

static int secp256k1_ecdsa_sig_serialize(unsigned char *sig, int *size, const secp256k1_ecdsa_sig_t *a) {
int lenR = (secp256k1_num_bits(&a->r) + 7)/8;
if (lenR == 0 || secp256k1_num_get_bit(&a->r, lenR*8-1))
lenR++;
int lenS = (secp256k1_num_bits(&a->s) + 7)/8;
if (lenS == 0 || secp256k1_num_get_bit(&a->s, lenS*8-1))
lenS++;
if (*size < 6+lenS+lenR)
return 0;
*size = 6 + lenS + lenR;
sig[0] = 0x30;
sig[1] = 4 + lenS + lenR;
sig[2] = 0x02;
sig[3] = lenR;
secp256k1_num_get_bin(sig+4, lenR, &a->r);
sig[4+lenR] = 0x02;
sig[5+lenR] = lenS;
secp256k1_num_get_bin(sig+lenR+6, lenS, &a->s);
return 1;
}

static int secp256k1_ecdsa_sig_recompute(secp256k1_num_t *r2, const secp256k1_ecdsa_sig_t *sig, const secp256k1_ge_t *pubkey, const secp256k1_num_t *message) {
const secp256k1_ge_consts_t *c = secp256k1_ge_consts;

if (secp256k1_num_is_neg(&sig->r) || secp256k1_num_is_neg(&sig->s))
return 0;
if (secp256k1_num_is_zero(&sig->r) || secp256k1_num_is_zero(&sig->s))
return 0;
if (secp256k1_num_cmp(&sig->r, &c->order) >= 0 || secp256k1_num_cmp(&sig->s, &c->order) >= 0)
return 0;

int ret = 0;
secp256k1_num_t sn, u1, u2;
secp256k1_num_init(&sn);
secp256k1_num_init(&u1);
secp256k1_num_init(&u2);
secp256k1_num_mod_inverse(&sn, &sig->s, &c->order);
secp256k1_num_mod_mul(&u1, &sn, message, &c->order);
secp256k1_num_mod_mul(&u2, &sn, &sig->r, &c->order);
secp256k1_gej_t pubkeyj; secp256k1_gej_set_ge(&pubkeyj, pubkey);
secp256k1_gej_t pr; secp256k1_ecmult(&pr, &pubkeyj, &u2, &u1);
if (!secp256k1_gej_is_infinity(&pr)) {
secp256k1_fe_t xr; secp256k1_gej_get_x_var(&xr, &pr);
secp256k1_fe_normalize(&xr);
unsigned char xrb[32]; secp256k1_fe_get_b32(xrb, &xr);
secp256k1_num_set_bin(r2, xrb, 32);
secp256k1_num_mod(r2, &c->order);
ret = 1;
}
secp256k1_num_free(&sn);
secp256k1_num_free(&u1);
secp256k1_num_free(&u2);
return ret;
}

static int secp256k1_ecdsa_sig_recover(const secp256k1_ecdsa_sig_t *sig, secp256k1_ge_t *pubkey, const secp256k1_num_t *message, int recid) {
const secp256k1_ge_consts_t *c = secp256k1_ge_consts;

if (secp256k1_num_is_neg(&sig->r) || secp256k1_num_is_neg(&sig->s))
return 0;
if (secp256k1_num_is_zero(&sig->r) || secp256k1_num_is_zero(&sig->s))
return 0;
if (secp256k1_num_cmp(&sig->r, &c->order) >= 0 || secp256k1_num_cmp(&sig->s, &c->order) >= 0)
return 0;

secp256k1_num_t rx;
secp256k1_num_init(&rx);
secp256k1_num_copy(&rx, &sig->r);
if (recid & 2) {
secp256k1_num_add(&rx, &rx, &c->order);
if (secp256k1_num_cmp(&rx, &secp256k1_fe_consts->p) >= 0)
return 0;
}
unsigned char brx[32];
secp256k1_num_get_bin(brx, 32, &rx);
secp256k1_num_free(&rx);
secp256k1_fe_t fx;
secp256k1_fe_set_b32(&fx, brx);
secp256k1_ge_t x;
if (!secp256k1_ge_set_xo(&x, &fx, recid & 1))
return 0;
secp256k1_gej_t xj;
secp256k1_gej_set_ge(&xj, &x);
secp256k1_num_t rn, u1, u2;
secp256k1_num_init(&rn);
secp256k1_num_init(&u1);
secp256k1_num_init(&u2);
secp256k1_num_mod_inverse(&rn, &sig->r, &c->order);
secp256k1_num_mod_mul(&u1, &rn, message, &c->order);
secp256k1_num_sub(&u1, &c->order, &u1);
secp256k1_num_mod_mul(&u2, &rn, &sig->s, &c->order);
secp256k1_gej_t qj;
secp256k1_ecmult(&qj, &xj, &u2, &u1);
secp256k1_ge_set_gej_var(pubkey, &qj);
secp256k1_num_free(&rn);
secp256k1_num_free(&u1);
secp256k1_num_free(&u2);
return !secp256k1_gej_is_infinity(&qj);
}

static int secp256k1_ecdsa_sig_verify(const secp256k1_ecdsa_sig_t *sig, const secp256k1_ge_t *pubkey, const secp256k1_num_t *message) {
secp256k1_num_t r2;
secp256k1_num_init(&r2);
int ret = 0;
ret = secp256k1_ecdsa_sig_recompute(&r2, sig, pubkey, message) && secp256k1_num_cmp(&sig->r, &r2) == 0;
secp256k1_num_free(&r2);
return ret;
}

static int secp256k1_ecdsa_sig_sign(secp256k1_ecdsa_sig_t *sig, const secp256k1_scalar_t *seckey, const secp256k1_scalar_t *message, const secp256k1_scalar_t *nonce, int *recid) {
secp256k1_gej_t rp;
secp256k1_ecmult_gen(&rp, nonce);
secp256k1_ge_t r;
secp256k1_ge_set_gej(&r, &rp);
unsigned char b[32];
secp256k1_fe_normalize(&r.x);
secp256k1_fe_normalize(&r.y);
secp256k1_fe_get_b32(b, &r.x);
int overflow = 0;
secp256k1_scalar_t sigr;
secp256k1_scalar_set_b32(&sigr, b, &overflow);
if (recid)
*recid = (overflow ? 2 : 0) | (secp256k1_fe_is_odd(&r.y) ? 1 : 0);
secp256k1_scalar_t n;
secp256k1_scalar_mul(&n, &sigr, seckey);
secp256k1_scalar_add(&n, &n, message);
secp256k1_scalar_t sigs;
secp256k1_scalar_inverse(&sigs, nonce);
secp256k1_scalar_mul(&sigs, &sigs, &n);
secp256k1_scalar_clear(&n);
secp256k1_gej_clear(&rp);
secp256k1_ge_clear(&r);
if (secp256k1_scalar_is_zero(&sigs))
return 0;
if (secp256k1_scalar_is_high(&sigs)) {
secp256k1_scalar_negate(&sigs, &sigs);
if (recid)
*recid ^= 1;
}
secp256k1_scalar_get_num(&sig->s, &sigs);
secp256k1_scalar_get_num(&sig->r, &sigr);
return 1;
}

static void secp256k1_ecdsa_sig_set_rs(secp256k1_ecdsa_sig_t *sig, const secp256k1_num_t *r, const secp256k1_num_t *s) {
secp256k1_num_copy(&sig->r, r);
secp256k1_num_copy(&sig->s, s);
}

#endif

+ 25
- 0
src/secp256k1/src/eckey.h View File

@@ -0,0 +1,25 @@
/**********************************************************************
* Copyright (c) 2013, 2014 Pieter Wuille *
* Distributed under the MIT software license, see the accompanying *
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
**********************************************************************/

#ifndef _SECP256K1_ECKEY_
#define _SECP256K1_ECKEY_

#include "group.h"
#include "scalar.h"
#include "num.h"

static int secp256k1_eckey_pubkey_parse(secp256k1_ge_t *elem, const unsigned char *pub, int size);
static int secp256k1_eckey_pubkey_serialize(secp256k1_ge_t *elem, unsigned char *pub, int *size, int compressed);

static int secp256k1_eckey_privkey_parse(secp256k1_scalar_t *key, const unsigned char *privkey, int privkeylen);
static int secp256k1_eckey_privkey_serialize(unsigned char *privkey, int *privkeylen, const secp256k1_scalar_t *key, int compressed);

static int secp256k1_eckey_privkey_tweak_add(secp256k1_scalar_t *key, const secp256k1_scalar_t *tweak);
static int secp256k1_eckey_pubkey_tweak_add(secp256k1_ge_t *key, const secp256k1_num_t *tweak);
static int secp256k1_eckey_privkey_tweak_mul(secp256k1_scalar_t *key, const secp256k1_scalar_t *tweak);
static int secp256k1_eckey_pubkey_tweak_mul(secp256k1_ge_t *key, const secp256k1_num_t *tweak);

#endif

+ 200
- 0
src/secp256k1/src/eckey_impl.h View File

@@ -0,0 +1,200 @@
/**********************************************************************
* Copyright (c) 2013, 2014 Pieter Wuille *
* Distributed under the MIT software license, see the accompanying *
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
**********************************************************************/

#ifndef _SECP256K1_ECKEY_IMPL_H_
#define _SECP256K1_ECKEY_IMPL_H_

#include "eckey.h"

#include "num.h"
#include "field.h"
#include "group.h"
#include "ecmult_gen.h"

static int secp256k1_eckey_pubkey_parse(secp256k1_ge_t *elem, const unsigned char *pub, int size) {
if (size == 33 && (pub[0] == 0x02 || pub[0] == 0x03)) {
secp256k1_fe_t x;
secp256k1_fe_set_b32(&x, pub+1);
return secp256k1_ge_set_xo(elem, &x, pub[0] == 0x03);
} else if (size == 65 && (pub[0] == 0x04 || pub[0] == 0x06 || pub[0] == 0x07)) {
secp256k1_fe_t x, y;
secp256k1_fe_set_b32(&x, pub+1);
secp256k1_fe_set_b32(&y, pub+33);
secp256k1_ge_set_xy(elem, &x, &y);
if ((pub[0] == 0x06 || pub[0] == 0x07) && secp256k1_fe_is_odd(&y) != (pub[0] == 0x07))
return 0;
return secp256k1_ge_is_valid(elem);
} else {
return 0;
}
}

static int secp256k1_eckey_pubkey_serialize(secp256k1_ge_t *elem, unsigned char *pub, int *size, int compressed) {
if (secp256k1_ge_is_infinity(elem)) {
return 0;
}
secp256k1_fe_normalize(&elem->x);
secp256k1_fe_normalize(&elem->y);
secp256k1_fe_get_b32(&pub[1], &elem->x);
if (compressed) {
*size = 33;
pub[0] = 0x02 | (secp256k1_fe_is_odd(&elem->y) ? 0x01 : 0x00);
} else {
*size = 65;
pub[0] = 0x04;
secp256k1_fe_get_b32(&pub[33], &elem->y);
}
return 1;
}

static int secp256k1_eckey_privkey_parse(secp256k1_scalar_t *key, const unsigned char *privkey, int privkeylen) {
const unsigned char *end = privkey + privkeylen;
/* sequence header */
if (end < privkey+1 || *privkey != 0x30)
return 0;
privkey++;
/* sequence length constructor */
int lenb = 0;
if (end < privkey+1 || !(*privkey & 0x80))
return 0;
lenb = *privkey & ~0x80; privkey++;
if (lenb < 1 || lenb > 2)
return 0;
if (end < privkey+lenb)
return 0;
/* sequence length */
int len = 0;
len = privkey[lenb-1] | (lenb > 1 ? privkey[lenb-2] << 8 : 0);
privkey += lenb;
if (end < privkey+len)
return 0;
/* sequence element 0: version number (=1) */
if (end < privkey+3 || privkey[0] != 0x02 || privkey[1] != 0x01 || privkey[2] != 0x01)
return 0;
privkey += 3;
/* sequence element 1: octet string, up to 32 bytes */
if (end < privkey+2 || privkey[0] != 0x04 || privkey[1] > 0x20 || end < privkey+2+privkey[1])
return 0;
int overflow = 0;
unsigned char c[32] = {0};
memcpy(c + 32 - privkey[1], privkey + 2, privkey[1]);
secp256k1_scalar_set_b32(key, c, &overflow);
memset(c, 0, 32);
return !overflow;
}

static int secp256k1_eckey_privkey_serialize(unsigned char *privkey, int *privkeylen, const secp256k1_scalar_t *key, int compressed) {
secp256k1_gej_t rp;
secp256k1_ecmult_gen(&rp, key);
secp256k1_ge_t r;
secp256k1_ge_set_gej(&r, &rp);
if (compressed) {
static const unsigned char begin[] = {
0x30,0x81,0xD3,0x02,0x01,0x01,0x04,0x20
};
static const unsigned char middle[] = {
0xA0,0x81,0x85,0x30,0x81,0x82,0x02,0x01,0x01,0x30,0x2C,0x06,0x07,0x2A,0x86,0x48,
0xCE,0x3D,0x01,0x01,0x02,0x21,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFE,0xFF,0xFF,0xFC,0x2F,0x30,0x06,0x04,0x01,0x00,0x04,0x01,0x07,0x04,
0x21,0x02,0x79,0xBE,0x66,0x7E,0xF9,0xDC,0xBB,0xAC,0x55,0xA0,0x62,0x95,0xCE,0x87,
0x0B,0x07,0x02,0x9B,0xFC,0xDB,0x2D,0xCE,0x28,0xD9,0x59,0xF2,0x81,0x5B,0x16,0xF8,
0x17,0x98,0x02,0x21,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFE,0xBA,0xAE,0xDC,0xE6,0xAF,0x48,0xA0,0x3B,0xBF,0xD2,0x5E,
0x8C,0xD0,0x36,0x41,0x41,0x02,0x01,0x01,0xA1,0x24,0x03,0x22,0x00
};
unsigned char *ptr = privkey;
memcpy(ptr, begin, sizeof(begin)); ptr += sizeof(begin);
secp256k1_scalar_get_b32(ptr, key); ptr += 32;
memcpy(ptr, middle, sizeof(middle)); ptr += sizeof(middle);
int pubkeylen = 0;
if (!secp256k1_eckey_pubkey_serialize(&r, ptr, &pubkeylen, 1)) {
return 0;
}
ptr += pubkeylen;
*privkeylen = ptr - privkey;
} else {
static const unsigned char begin[] = {
0x30,0x82,0x01,0x13,0x02,0x01,0x01,0x04,0x20
};
static const unsigned char middle[] = {
0xA0,0x81,0xA5,0x30,0x81,0xA2,0x02,0x01,0x01,0x30,0x2C,0x06,0x07,0x2A,0x86,0x48,
0xCE,0x3D,0x01,0x01,0x02,0x21,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFE,0xFF,0xFF,0xFC,0x2F,0x30,0x06,0x04,0x01,0x00,0x04,0x01,0x07,0x04,
0x41,0x04,0x79,0xBE,0x66,0x7E,0xF9,0xDC,0xBB,0xAC,0x55,0xA0,0x62,0x95,0xCE,0x87,
0x0B,0x07,0x02,0x9B,0xFC,0xDB,0x2D,0xCE,0x28,0xD9,0x59,0xF2,0x81,0x5B,0x16,0xF8,
0x17,0x98,0x48,0x3A,0xDA,0x77,0x26,0xA3,0xC4,0x65,0x5D,0xA4,0xFB,0xFC,0x0E,0x11,
0x08,0xA8,0xFD,0x17,0xB4,0x48,0xA6,0x85,0x54,0x19,0x9C,0x47,0xD0,0x8F,0xFB,0x10,
0xD4,0xB8,0x02,0x21,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFE,0xBA,0xAE,0xDC,0xE6,0xAF,0x48,0xA0,0x3B,0xBF,0xD2,0x5E,
0x8C,0xD0,0x36,0x41,0x41,0x02,0x01,0x01,0xA1,0x44,0x03,0x42,0x00
};
unsigned char *ptr = privkey;
memcpy(ptr, begin, sizeof(begin)); ptr += sizeof(begin);
secp256k1_scalar_get_b32(ptr, key); ptr += 32;
memcpy(ptr, middle, sizeof(middle)); ptr += sizeof(middle);
int pubkeylen = 0;
if (!secp256k1_eckey_pubkey_serialize(&r, ptr, &pubkeylen, 0)) {
return 0;
}
ptr += pubkeylen;
*privkeylen = ptr - privkey;
}
return 1;
}

static int secp256k1_eckey_privkey_tweak_add(secp256k1_scalar_t *key, const secp256k1_scalar_t *tweak) {
secp256k1_scalar_add(key, key, tweak);
if (secp256k1_scalar_is_zero(key))
return 0;
return 1;
}

static int secp256k1_eckey_pubkey_tweak_add(secp256k1_ge_t *key, const secp256k1_num_t *tweak) {
if (secp256k1_num_cmp(tweak, &secp256k1_ge_consts->order) >= 0)
return 0;

secp256k1_gej_t pt;
secp256k1_gej_set_ge(&pt, key);
secp256k1_num_t one;
secp256k1_num_init(&one);
secp256k1_num_set_int(&one, 1);
secp256k1_ecmult(&pt, &pt, &one, tweak);
secp256k1_num_free(&one);

if (secp256k1_gej_is_infinity(&pt))
return 0;
secp256k1_ge_set_gej(key, &pt);
return 1;
}

static int secp256k1_eckey_privkey_tweak_mul(secp256k1_scalar_t *key, const secp256k1_scalar_t *tweak) {
if (secp256k1_scalar_is_zero(tweak))
return 0;

secp256k1_scalar_mul(key, key, tweak);
return 1;
}

static int secp256k1_eckey_pubkey_tweak_mul(secp256k1_ge_t *key, const secp256k1_num_t *tweak) {
if (secp256k1_num_is_zero(tweak))
return 0;
if (secp256k1_num_cmp(tweak, &secp256k1_ge_consts->order) >= 0)
return 0;

secp256k1_num_t zero;
secp256k1_num_init(&zero);
secp256k1_num_set_int(&zero, 0);
secp256k1_gej_t pt;
secp256k1_gej_set_ge(&pt, key);
secp256k1_ecmult(&pt, &pt, tweak, &zero);
secp256k1_num_free(&zero);
secp256k1_ge_set_gej(key, &pt);
return 1;
}

#endif

+ 19
- 0
src/secp256k1/src/ecmult.h View File

@@ -0,0 +1,19 @@
/**********************************************************************
* Copyright (c) 2013, 2014 Pieter Wuille *
* Distributed under the MIT software license, see the accompanying *
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
**********************************************************************/

#ifndef _SECP256K1_ECMULT_
#define _SECP256K1_ECMULT_

#include "num.h"
#include "group.h"

static void secp256k1_ecmult_start(void);
static void secp256k1_ecmult_stop(void);

/** Double multiply: R = na*A + ng*G */
static void secp256k1_ecmult(secp256k1_gej_t *r, const secp256k1_gej_t *a, const secp256k1_num_t *na, const secp256k1_num_t *ng);

#endif

+ 19
- 0
src/secp256k1/src/ecmult_gen.h View File

@@ -0,0 +1,19 @@
/**********************************************************************
* Copyright (c) 2013, 2014 Pieter Wuille *
* Distributed under the MIT software license, see the accompanying *
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
**********************************************************************/

#ifndef _SECP256K1_ECMULT_GEN_
#define _SECP256K1_ECMULT_GEN_

#include "scalar.h"
#include "group.h"

static void secp256k1_ecmult_gen_start(void);
static void secp256k1_ecmult_gen_stop(void);

/** Multiply with the generator: R = a*G */
static void secp256k1_ecmult_gen(secp256k1_gej_t *r, const secp256k1_scalar_t *a);

#endif

+ 118
- 0
src/secp256k1/src/ecmult_gen_impl.h View File

@@ -0,0 +1,118 @@
/**********************************************************************
* Copyright (c) 2013, 2014 Pieter Wuille *
* Distributed under the MIT software license, see the accompanying *
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
**********************************************************************/

#ifndef _SECP256K1_ECMULT_GEN_IMPL_H_
#define _SECP256K1_ECMULT_GEN_IMPL_H_

#include "scalar.h"