From 67f9783e6a0fa5613a031e05549b92adbee57399 Mon Sep 17 00:00:00 2001
From: obscuren <geffobscura@gmail.com>
Date: Thu, 22 Jan 2015 00:35:00 +0100
Subject: Moved `obscuren` secp256k1-go

---
 crypto/crypto.go                                   |   2 +-
 crypto/crypto_test.go                              |   2 +-
 crypto/keypair.go                                  |   2 +-
 crypto/secp256k1/.gitignore                        |  24 +
 crypto/secp256k1/README.md                         |  22 +
 crypto/secp256k1/notes.go                          | 192 ++++++++
 crypto/secp256k1/secp256.go                        | 304 +++++++++++++
 crypto/secp256k1/secp256_rand.go                   |  96 ++++
 crypto/secp256k1/secp256_test.go                   | 228 ++++++++++
 crypto/secp256k1/secp256k1/COPYING                 |  19 +
 crypto/secp256k1/secp256k1/Makefile                |  55 +++
 crypto/secp256k1/secp256k1/TODO                    |   3 +
 crypto/secp256k1/secp256k1/config.mk               |   9 +
 crypto/secp256k1/secp256k1/configure               | 175 ++++++++
 crypto/secp256k1/secp256k1/include/secp256k1.h     | 121 +++++
 crypto/secp256k1/secp256k1/src/bench.c             |  64 +++
 crypto/secp256k1/secp256k1/src/ecdsa.h             |  28 ++
 crypto/secp256k1/secp256k1/src/ecmult.h            |  19 +
 crypto/secp256k1/secp256k1/src/field.h             | 101 +++++
 crypto/secp256k1/secp256k1/src/field_10x26.h       |  19 +
 crypto/secp256k1/secp256k1/src/field_5x52.h        |  19 +
 crypto/secp256k1/secp256k1/src/field_5x52_asm.asm  | 463 ++++++++++++++++++++
 crypto/secp256k1/secp256k1/src/field_5x64.h        |  19 +
 crypto/secp256k1/secp256k1/src/field_5x64_asm.asm  | 332 ++++++++++++++
 crypto/secp256k1/secp256k1/src/field_gmp.h         |  16 +
 crypto/secp256k1/secp256k1/src/group.h             | 108 +++++
 crypto/secp256k1/secp256k1/src/impl/ecdsa.h        | 309 +++++++++++++
 crypto/secp256k1/secp256k1/src/impl/ecmult.h       | 238 ++++++++++
 crypto/secp256k1/secp256k1/src/impl/field.h        | 175 ++++++++
 crypto/secp256k1/secp256k1/src/impl/field_10x26.h  | 487 +++++++++++++++++++++
 crypto/secp256k1/secp256k1/src/impl/field_5x52.h   | 196 +++++++++
 .../secp256k1/secp256k1/src/impl/field_5x52_asm.h  |  11 +
 .../secp256k1/src/impl/field_5x52_int128.h         | 105 +++++
 crypto/secp256k1/secp256k1/src/impl/field_5x64.h   | 371 ++++++++++++++++
 .../secp256k1/secp256k1/src/impl/field_5x64_asm.h  |  11 +
 crypto/secp256k1/secp256k1/src/impl/field_gmp.h    | 155 +++++++
 crypto/secp256k1/secp256k1/src/impl/group.h        | 397 +++++++++++++++++
 crypto/secp256k1/secp256k1/src/impl/num.h          |  18 +
 crypto/secp256k1/secp256k1/src/impl/num_gmp.h      | 346 +++++++++++++++
 crypto/secp256k1/secp256k1/src/impl/num_openssl.h  | 145 ++++++
 crypto/secp256k1/secp256k1/src/impl/util.h         |  45 ++
 .../src/java/org/bitcoin/NativeSecp256k1.java      |  60 +++
 .../src/java/org_bitcoin_NativeSecp256k1.c         |  23 +
 .../src/java/org_bitcoin_NativeSecp256k1.h         |  21 +
 crypto/secp256k1/secp256k1/src/num.h               |  93 ++++
 crypto/secp256k1/secp256k1/src/num_gmp.h           |  18 +
 crypto/secp256k1/secp256k1/src/num_openssl.h       |  14 +
 crypto/secp256k1/secp256k1/src/secp256k1.c         | 269 ++++++++++++
 crypto/secp256k1/secp256k1/src/tests.c             | 465 ++++++++++++++++++++
 crypto/secp256k1/secp256k1/src/util.h              |  19 +
 50 files changed, 6430 insertions(+), 3 deletions(-)
 create mode 100644 crypto/secp256k1/.gitignore
 create mode 100644 crypto/secp256k1/README.md
 create mode 100644 crypto/secp256k1/notes.go
 create mode 100644 crypto/secp256k1/secp256.go
 create mode 100644 crypto/secp256k1/secp256_rand.go
 create mode 100644 crypto/secp256k1/secp256_test.go
 create mode 100644 crypto/secp256k1/secp256k1/COPYING
 create mode 100644 crypto/secp256k1/secp256k1/Makefile
 create mode 100644 crypto/secp256k1/secp256k1/TODO
 create mode 100644 crypto/secp256k1/secp256k1/config.mk
 create mode 100755 crypto/secp256k1/secp256k1/configure
 create mode 100644 crypto/secp256k1/secp256k1/include/secp256k1.h
 create mode 100644 crypto/secp256k1/secp256k1/src/bench.c
 create mode 100644 crypto/secp256k1/secp256k1/src/ecdsa.h
 create mode 100644 crypto/secp256k1/secp256k1/src/ecmult.h
 create mode 100644 crypto/secp256k1/secp256k1/src/field.h
 create mode 100644 crypto/secp256k1/secp256k1/src/field_10x26.h
 create mode 100644 crypto/secp256k1/secp256k1/src/field_5x52.h
 create mode 100644 crypto/secp256k1/secp256k1/src/field_5x52_asm.asm
 create mode 100644 crypto/secp256k1/secp256k1/src/field_5x64.h
 create mode 100644 crypto/secp256k1/secp256k1/src/field_5x64_asm.asm
 create mode 100644 crypto/secp256k1/secp256k1/src/field_gmp.h
 create mode 100644 crypto/secp256k1/secp256k1/src/group.h
 create mode 100644 crypto/secp256k1/secp256k1/src/impl/ecdsa.h
 create mode 100644 crypto/secp256k1/secp256k1/src/impl/ecmult.h
 create mode 100644 crypto/secp256k1/secp256k1/src/impl/field.h
 create mode 100644 crypto/secp256k1/secp256k1/src/impl/field_10x26.h
 create mode 100644 crypto/secp256k1/secp256k1/src/impl/field_5x52.h
 create mode 100644 crypto/secp256k1/secp256k1/src/impl/field_5x52_asm.h
 create mode 100644 crypto/secp256k1/secp256k1/src/impl/field_5x52_int128.h
 create mode 100644 crypto/secp256k1/secp256k1/src/impl/field_5x64.h
 create mode 100644 crypto/secp256k1/secp256k1/src/impl/field_5x64_asm.h
 create mode 100644 crypto/secp256k1/secp256k1/src/impl/field_gmp.h
 create mode 100644 crypto/secp256k1/secp256k1/src/impl/group.h
 create mode 100644 crypto/secp256k1/secp256k1/src/impl/num.h
 create mode 100644 crypto/secp256k1/secp256k1/src/impl/num_gmp.h
 create mode 100644 crypto/secp256k1/secp256k1/src/impl/num_openssl.h
 create mode 100644 crypto/secp256k1/secp256k1/src/impl/util.h
 create mode 100644 crypto/secp256k1/secp256k1/src/java/org/bitcoin/NativeSecp256k1.java
 create mode 100644 crypto/secp256k1/secp256k1/src/java/org_bitcoin_NativeSecp256k1.c
 create mode 100644 crypto/secp256k1/secp256k1/src/java/org_bitcoin_NativeSecp256k1.h
 create mode 100644 crypto/secp256k1/secp256k1/src/num.h
 create mode 100644 crypto/secp256k1/secp256k1/src/num_gmp.h
 create mode 100644 crypto/secp256k1/secp256k1/src/num_openssl.h
 create mode 100644 crypto/secp256k1/secp256k1/src/secp256k1.c
 create mode 100644 crypto/secp256k1/secp256k1/src/tests.c
 create mode 100644 crypto/secp256k1/secp256k1/src/util.h

(limited to 'crypto')

diff --git a/crypto/crypto.go b/crypto/crypto.go
index 2c5f30905..ac84c6204 100644
--- a/crypto/crypto.go
+++ b/crypto/crypto.go
@@ -7,10 +7,10 @@ import (
 	"crypto/sha256"
 
 	"code.google.com/p/go.crypto/ripemd160"
+	"github.com/ethereum/go-ethereum/crypto/secp256k1"
 	"github.com/ethereum/go-ethereum/crypto/sha3"
 	"github.com/ethereum/go-ethereum/ethutil"
 	"github.com/obscuren/ecies"
-	"github.com/obscuren/secp256k1-go"
 )
 
 func init() {
diff --git a/crypto/crypto_test.go b/crypto/crypto_test.go
index 41c05a242..349bc31ae 100644
--- a/crypto/crypto_test.go
+++ b/crypto/crypto_test.go
@@ -7,8 +7,8 @@ import (
 	"testing"
 	"time"
 
+	"github.com/ethereum/go-ethereum/crypto/secp256k1"
 	"github.com/ethereum/go-ethereum/ethutil"
-	"github.com/obscuren/secp256k1-go"
 )
 
 // These tests are sanity checks.
diff --git a/crypto/keypair.go b/crypto/keypair.go
index d02875ded..da5788437 100644
--- a/crypto/keypair.go
+++ b/crypto/keypair.go
@@ -3,8 +3,8 @@ package crypto
 import (
 	"strings"
 
+	"github.com/ethereum/go-ethereum/crypto/secp256k1"
 	"github.com/ethereum/go-ethereum/ethutil"
-	"github.com/obscuren/secp256k1-go"
 )
 
 type KeyPair struct {
diff --git a/crypto/secp256k1/.gitignore b/crypto/secp256k1/.gitignore
new file mode 100644
index 000000000..802b6744a
--- /dev/null
+++ b/crypto/secp256k1/.gitignore
@@ -0,0 +1,24 @@
+# Compiled Object files, Static and Dynamic libs (Shared Objects)
+*.o
+*.a
+*.so
+
+# Folders
+_obj
+_test
+
+# Architecture specific extensions/prefixes
+*.[568vq]
+[568vq].out
+
+*.cgo1.go
+*.cgo2.c
+_cgo_defun.c
+_cgo_gotypes.go
+_cgo_export.*
+
+_testmain.go
+
+*.exe
+
+*~
diff --git a/crypto/secp256k1/README.md b/crypto/secp256k1/README.md
new file mode 100644
index 000000000..79cdccb38
--- /dev/null
+++ b/crypto/secp256k1/README.md
@@ -0,0 +1,22 @@
+secp256k1-go
+=======
+
+golang secp256k1 library
+
+Implements cryptographic operations for the secp256k1 ECDSA curve used by Bitcoin.
+
+Installing
+===
+```
+sudo apt-get install gmp-dev
+```
+
+Now compiles with cgo!
+
+Test
+===
+
+To run tests do
+```
+go tests
+```
\ No newline at end of file
diff --git a/crypto/secp256k1/notes.go b/crypto/secp256k1/notes.go
new file mode 100644
index 000000000..7ed16caab
--- /dev/null
+++ b/crypto/secp256k1/notes.go
@@ -0,0 +1,192 @@
+package secp256k1
+
+/*
+<HaltingState> sipa, int secp256k1_ecdsa_pubkey_create(unsigned char *pubkey, int *pubkeylen, const unsigned char *seckey, int compressed);
+<HaltingState> is that how i generate private/public keys?
+<sipa> HaltingState: you pass in a random 32-byte string as seckey
+<sipa> HaltingState: if it is valid, the corresponding pubkey is put in pubkey
+<sipa> and true is returned
+<sipa> otherwise, false is returned
+<sipa> around 1 in 2^128 32-byte strings are invalid, so the odds of even ever seeing one is extremely rare
+
+<sipa> private keys are mathematically numbers
+<sipa> each has a corresponding point on the curve as public key
+<sipa> a private key is just a number
+<sipa> a public key is a point with x/y coordinates
+<sipa> almost every 256-bit number is a valid private key (one with a point on the curve corresponding to it)
+<sipa> HaltingState: ok?
+
+<sipa> more than half of random points are not on the curve
+<sipa> and actually, it is less than  the square root, not less than half, sorry :)
+!!!
+<sipa> a private key is a NUMBER
+<sipa> a public key is a POINT
+<gmaxwell> half the x,y values in the field are not on the curve, a private key is an integer.
+
+<sipa> HaltingState: yes, n,q = private keys; N,Q = corresponding public keys (N=n*G, Q=q*G); then it follows that n*Q = n*q*G = q*n*G = q*N
+<sipa> that's the reason ECDH works
+<sipa> multiplication is associative and commutativ
+*/
+
+/*
+<HaltingState> sipa, ok; i am doing compact signatures and I want to know; can someone change the signature to get another valid signature for same message without the private key
+<HaltingState> because i know they can do that for the normal 72 byte signatures that openssl was putting out
+<sipa> HaltingState: if you don't enforce non-malleability, yes
+<sipa> HaltingState: if you force the highest bit of t
+
+<sipa> it _creates_ signatures that already satisfy that condition
+<sipa> but it will accept ones that don't
+<sipa> maybe i should change that, and be strict
+<HaltingState> yes; i want some way to know signature is valid but fails malleability
+<sipa> well if the highest bit of S is 1, you can take its complement
+<sipa> and end up with a valid signature
+<sipa> that is canonical
+*/
+
+/*
+
+<HaltingState> sipa, I am signing messages and highest bit of the compact signature is 1!!!
+<HaltingState>  if (b & 0x80) == 0x80 {
+<HaltingState>   log.Panic("b= %v b2= %v \n", b, b&0x80)
+<HaltingState>  }
+<sipa> what bit?
+* Pengoo has quit (Ping timeout: 272 seconds)
+<HaltingState> the highest bit of the first byte of signature
+<sipa> it's the highest bit of S
+<sipa> so the 32nd byte
+<HaltingState> wtf
+
+*/
+
+/*
+ For instance, nonces are used in HTTP digest access authentication to calculate an MD5 digest
+ of the password. The nonces are different each time the 401 authentication challenge
+ response code is presented, thus making replay attacks virtually impossible.
+
+can verify client/server match without sending password over network
+*/
+
+/*
+<hanihani> one thing I dont get about armory for instance,
+is how the hot-wallet can generate new addresses without
+knowing the master key
+*/
+
+/*
+<HaltingState> i am yelling at the telehash people for using secp256r1
+instead of secp256k1; they thing r1 is "more secure" despite fact that
+there is no implementation that works and wrapping it is now taking
+up massive time, lol
+<gmaxwell> ...
+
+<gmaxwell> You know that the *r curves are selected via an undisclosed
+secret process, right?
+<gmaxwell> HaltingState: telehash is offtopic for this channel.
+*/
+/*
+ For instance, nonces are used in HTTP digest access authentication to calculate an MD5 digest
+ of the password. The nonces are different each time the 401 authentication challenge
+ response code is presented, thus making replay attacks virtually impossible.
+
+can verify client/server match without sending password over network
+*/
+
+/*
+void secp256k1_start(void);
+void secp256k1_stop(void);
+
+ * Verify an ECDSA signature.
+ *  Returns: 1: correct signature
+ *           0: incorrect signature
+ *          -1: invalid public key
+ *          -2: invalid signature
+ *
+int secp256k1_ecdsa_verify(const unsigned char *msg, int msglen,
+                           const unsigned char *sig, int siglen,
+                           const unsigned char *pubkey, int pubkeylen);
+
+http://www.nilsschneider.net/2013/01/28/recovering-bitcoin-private-keys.html
+
+Why did this work? ECDSA requires a random number for each signature. If this random
+number is ever used twice with the same private key it can be recovered.
+This transaction was generated by a hardware bitcoin wallet using a pseudo-random number
+generator that was returning the same “random” number every time.
+
+Nonce is 32 bytes?
+
+ * Create an ECDSA signature.
+ *  Returns: 1: signature created
+ *           0: nonce invalid, try another one
+ *  In:      msg:    the message being signed
+ *           msglen: the length of the message being signed
+ *           seckey: pointer to a 32-byte secret key (assumed to be valid)
+ *           nonce:  pointer to a 32-byte nonce (generated with a cryptographic PRNG)
+ *  Out:     sig:    pointer to a 72-byte array where the signature will be placed.
+ *           siglen: pointer to an int, which will be updated to the signature length (<=72).
+ *
+int secp256k1_ecdsa_sign(const unsigned char *msg, int msglen,
+                         unsigned char *sig, int *siglen,
+                         const unsigned char *seckey,
+                         const unsigned char *nonce);
+
+
+ * 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
+ *           msglen: the length of the message being signed
+ *           seckey: pointer to a 32-byte secret key (assumed to be valid)
+ *           nonce:  pointer to a 32-byte nonce (generated with a cryptographic PRNG)
+ *  Out:     sig:    pointer to a 64-byte array where the signature will be placed.
+ *           recid:  pointer to an int, which will be updated to contain the recovery id.
+ *
+int secp256k1_ecdsa_sign_compact(const unsigned char *msg, int msglen,
+                                 unsigned char *sig64,
+                                 const unsigned char *seckey,
+                                 const unsigned char *nonce,
+                                 int *recid);
+
+ * Recover an ECDSA public key from a compact signature.
+ *  Returns: 1: public key succesfully recovered (which guarantees a correct signature).
+ *           0: otherwise.
+ *  In:      msg:        the message assumed to be signed
+ *           msglen:     the length of the message
+ *           compressed: whether to recover a compressed or uncompressed pubkey
+ *           recid:      the recovery id (as returned by ecdsa_sign_compact)
+ *  Out:     pubkey:     pointer to a 33 or 65 byte array to put the pubkey.
+ *           pubkeylen:  pointer to an int that will contain the pubkey length.
+ *
+
+recovery id is between 0 and 3
+
+int secp256k1_ecdsa_recover_compact(const unsigned char *msg, int msglen,
+                                    const unsigned char *sig64,
+                                    unsigned char *pubkey, int *pubkeylen,
+                                    int compressed, int recid);
+
+
+ * 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
+ *
+int secp256k1_ecdsa_seckey_verify(const unsigned char *seckey);
+
+** Just validate a public key.
+ *  Returns: 1: valid public key
+ *           0: invalid public key
+ *
+int secp256k1_ecdsa_pubkey_verify(const unsigned char *pubkey, int pubkeylen);
+
+** 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.
+ *  Out:    pubkey:     pointer to a 33-byte (if compressed) or 65-byte (if uncompressed)
+ *                      area to store the public key.
+ *          pubkeylen:  pointer to int that will be updated to contains the pubkey's
+ *                      length.
+ *  Returns: 1: secret was valid, public key stores
+ *           0: secret was invalid, try again.
+ *
+int secp256k1_ecdsa_pubkey_create(unsigned char *pubkey, int *pubkeylen, const unsigned char *seckey, int compressed);
+*/
diff --git a/crypto/secp256k1/secp256.go b/crypto/secp256k1/secp256.go
new file mode 100644
index 000000000..53ad9b477
--- /dev/null
+++ b/crypto/secp256k1/secp256.go
@@ -0,0 +1,304 @@
+package secp256k1
+
+/*
+#cgo CFLAGS: -std=gnu99 -Wno-error
+#cgo darwin CFLAGS: -I/usr/local/include
+#cgo LDFLAGS: -lgmp
+#cgo darwin LDFLAGS: -L/usr/local/lib
+#define USE_FIELD_10X26
+#define USE_NUM_GMP
+#define USE_FIELD_INV_BUILTIN
+#include "./secp256k1/src/secp256k1.c"
+*/
+import "C"
+
+import (
+	"bytes"
+	"errors"
+	"unsafe"
+)
+
+//#define USE_FIELD_5X64
+
+/*
+   Todo:
+   > Centralize key management in module
+   > add pubkey/private key struct
+   > Dont let keys leave module; address keys as ints
+
+   > store private keys in buffer and shuffle (deters persistance on swap disc)
+   > Byte permutation (changing)
+   > xor with chaning random block (to deter scanning memory for 0x63) (stream cipher?)
+
+   On Disk
+   > Store keys in wallets
+   > use slow key derivation function for wallet encryption key (2 seconds)
+*/
+
+func init() {
+	C.secp256k1_start() //takes 10ms to 100ms
+}
+
+func Stop() {
+	C.secp256k1_stop()
+}
+
+/*
+int secp256k1_ecdsa_pubkey_create(
+    unsigned char *pubkey, int *pubkeylen,
+    const unsigned char *seckey, int compressed);
+*/
+
+/** 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.
+ *  Out:    pubkey:     pointer to a 33-byte (if compressed) or 65-byte (if uncompressed)
+ *                      area to store the public key.
+ *          pubkeylen:  pointer to int that will be updated to contains the pubkey's
+ *                      length.
+ *  Returns: 1: secret was valid, public key stores
+ *           0: secret was invalid, try again.
+ */
+
+//pubkey, seckey
+
+func GenerateKeyPair() ([]byte, []byte) {
+
+	pubkey_len := C.int(65)
+	const seckey_len = 32
+
+	var pubkey []byte = make([]byte, pubkey_len)
+	var seckey []byte = RandByte(seckey_len)
+
+	var pubkey_ptr *C.uchar = (*C.uchar)(unsafe.Pointer(&pubkey[0]))
+	var seckey_ptr *C.uchar = (*C.uchar)(unsafe.Pointer(&seckey[0]))
+
+	ret := C.secp256k1_ecdsa_pubkey_create(
+		pubkey_ptr, &pubkey_len,
+		seckey_ptr, 0)
+
+	if ret != C.int(1) {
+		return GenerateKeyPair() //invalid secret, try again
+	}
+	return pubkey, seckey
+}
+
+func GeneratePubKey(seckey []byte) ([]byte, error) {
+	pubkey_len := C.int(65)
+	const seckey_len = 32
+
+	var pubkey []byte = make([]byte, pubkey_len)
+
+	var pubkey_ptr *C.uchar = (*C.uchar)(unsafe.Pointer(&pubkey[0]))
+	var seckey_ptr *C.uchar = (*C.uchar)(unsafe.Pointer(&seckey[0]))
+
+	ret := C.secp256k1_ecdsa_pubkey_create(
+		pubkey_ptr, &pubkey_len,
+		seckey_ptr, 0)
+
+	if ret != C.int(1) {
+		return nil, errors.New("Unable to generate pubkey from seckey")
+	}
+
+	return pubkey, nil
+}
+
+/*
+*  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
+*           msglen: the length of the message being signed
+*           seckey: pointer to a 32-byte secret key (assumed to be valid)
+*           nonce:  pointer to a 32-byte nonce (generated with a cryptographic PRNG)
+*  Out:     sig:    pointer to a 64-byte array where the signature will be placed.
+*           recid:  pointer to an int, which will be updated to contain the recovery id.
+ */
+
+/*
+int secp256k1_ecdsa_sign_compact(const unsigned char *msg, int msglen,
+                                 unsigned char *sig64,
+                                 const unsigned char *seckey,
+                                 const unsigned char *nonce,
+                                 int *recid);
+*/
+
+func Sign(msg []byte, seckey []byte) ([]byte, error) {
+	//var nonce []byte = RandByte(32)
+	nonce := make([]byte, 32)
+	for i := range msg {
+		nonce[i] = msg[i] ^ seckey[i]
+	}
+
+	var sig []byte = make([]byte, 65)
+	var recid C.int
+
+	var msg_ptr *C.uchar = (*C.uchar)(unsafe.Pointer(&msg[0]))
+	var seckey_ptr *C.uchar = (*C.uchar)(unsafe.Pointer(&seckey[0]))
+	var nonce_ptr *C.uchar = (*C.uchar)(unsafe.Pointer(&nonce[0]))
+	var sig_ptr *C.uchar = (*C.uchar)(unsafe.Pointer(&sig[0]))
+
+	if C.secp256k1_ecdsa_seckey_verify(seckey_ptr) != C.int(1) {
+		return nil, errors.New("Invalid secret key")
+	}
+
+	ret := C.secp256k1_ecdsa_sign_compact(
+		msg_ptr, C.int(len(msg)),
+		sig_ptr,
+		seckey_ptr,
+		nonce_ptr,
+		&recid)
+
+	sig[64] = byte(int(recid))
+
+	if ret != C.int(1) {
+		// nonce invalid, retry
+		return Sign(msg, seckey)
+	}
+
+	return sig, nil
+
+}
+
+/*
+* 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
+ */
+
+func VerifySeckeyValidity(seckey []byte) error {
+	if len(seckey) != 32 {
+		return errors.New("priv key is not 32 bytes")
+	}
+	var seckey_ptr *C.uchar = (*C.uchar)(unsafe.Pointer(&seckey[0]))
+	ret := C.secp256k1_ecdsa_seckey_verify(seckey_ptr)
+	if int(ret) != 1 {
+		return errors.New("invalid seckey")
+	}
+	return nil
+}
+
+/*
+* Validate a public key.
+*  Returns: 1: valid public key
+*           0: invalid public key
+ */
+
+func VerifyPubkeyValidity(pubkey []byte) error {
+	if len(pubkey) != 65 {
+		return errors.New("pub key is not 65 bytes")
+	}
+	var pubkey_ptr *C.uchar = (*C.uchar)(unsafe.Pointer(&pubkey[0]))
+	ret := C.secp256k1_ecdsa_pubkey_verify(pubkey_ptr, 65)
+	if int(ret) != 1 {
+		return errors.New("invalid pubkey")
+	}
+
+	return nil
+}
+
+func VerifySignatureValidity(sig []byte) bool {
+	//64+1
+	if len(sig) != 65 {
+		return false
+	}
+	//malleability check, highest bit must be 1
+	if (sig[32] & 0x80) == 0x80 {
+		return false
+	}
+	//recovery id check
+	if sig[64] >= 4 {
+		return false
+	}
+
+	return true
+}
+
+//for compressed signatures, does not need pubkey
+func VerifySignature(msg []byte, sig []byte, pubkey1 []byte) error {
+	if msg == nil || sig == nil || pubkey1 == nil {
+		return errors.New("inputs must be non-nil")
+	}
+	if len(sig) != 65 {
+		return errors.New("invalid signature length")
+	}
+	if len(pubkey1) != 65 {
+		return errors.New("Invalid public key length")
+	}
+
+	//to enforce malleability, highest bit of S must be 0
+	//S starts at 32nd byte
+	if (sig[32] & 0x80) == 0x80 { //highest bit must be 1
+		return errors.New("Signature not malleable")
+	}
+
+	if sig[64] >= 4 {
+		return errors.New("Recover byte invalid")
+	}
+
+	// if pubkey recovered, signature valid
+	pubkey2, err := RecoverPubkey(msg, sig)
+	if err != nil {
+		return err
+	}
+	if len(pubkey2) != 65 {
+		return errors.New("Invalid recovered public key length")
+	}
+	if !bytes.Equal(pubkey1, pubkey2) {
+		return errors.New("Public key does not match recovered public key")
+	}
+
+	return nil
+}
+
+/*
+int secp256k1_ecdsa_recover_compact(const unsigned char *msg, int msglen,
+                                    const unsigned char *sig64,
+                                    unsigned char *pubkey, int *pubkeylen,
+                                    int compressed, int recid);
+*/
+
+/*
+ * Recover an ECDSA public key from a compact signature.
+ *  Returns: 1: public key succesfully recovered (which guarantees a correct signature).
+ *           0: otherwise.
+ *  In:      msg:        the message assumed to be signed
+ *           msglen:     the length of the message
+ *           compressed: whether to recover a compressed or uncompressed pubkey
+ *           recid:      the recovery id (as returned by ecdsa_sign_compact)
+ *  Out:     pubkey:     pointer to a 33 or 65 byte array to put the pubkey.
+ *           pubkeylen:  pointer to an int that will contain the pubkey length.
+ */
+
+//recovers the public key from the signature
+//recovery of pubkey means correct signature
+func RecoverPubkey(msg []byte, sig []byte) ([]byte, error) {
+	if len(sig) != 65 {
+		return nil, errors.New("Invalid signature length")
+	}
+
+	var pubkey []byte = make([]byte, 65)
+
+	var msg_ptr *C.uchar = (*C.uchar)(unsafe.Pointer(&msg[0]))
+	var sig_ptr *C.uchar = (*C.uchar)(unsafe.Pointer(&sig[0]))
+	var pubkey_ptr *C.uchar = (*C.uchar)(unsafe.Pointer(&pubkey[0]))
+
+	var pubkeylen C.int
+
+	ret := C.secp256k1_ecdsa_recover_compact(
+		msg_ptr, C.int(len(msg)),
+		sig_ptr,
+		pubkey_ptr, &pubkeylen,
+		C.int(0), C.int(sig[64]),
+	)
+
+	if ret == C.int(0) {
+		return nil, errors.New("Failed to recover public key")
+	} else if pubkeylen != C.int(65) {
+		return nil, errors.New("Impossible Error: Invalid recovered public key length")
+	} else {
+		return pubkey, nil
+	}
+	return nil, errors.New("Impossible Error: func RecoverPubkey has reached an unreachable state")
+}
diff --git a/crypto/secp256k1/secp256_rand.go b/crypto/secp256k1/secp256_rand.go
new file mode 100644
index 000000000..5e8035e0f
--- /dev/null
+++ b/crypto/secp256k1/secp256_rand.go
@@ -0,0 +1,96 @@
+package secp256k1
+
+import (
+	crand "crypto/rand"
+	"io"
+	mrand "math/rand"
+	"os"
+	"strings"
+	"time"
+)
+
+/*
+Note:
+
+- On windows cryto/rand uses CrytoGenRandom which uses RC4 which is insecure
+- Android random number generator is known to be insecure.
+- Linux uses /dev/urandom , which is thought to be secure and uses entropy pool
+
+Therefore the output is salted.
+*/
+
+//finalizer from MurmerHash3
+func mmh3f(key uint64) uint64 {
+	key ^= key >> 33
+	key *= 0xff51afd7ed558ccd
+	key ^= key >> 33
+	key *= 0xc4ceb9fe1a85ec53
+	key ^= key >> 33
+	return key
+}
+
+//knuth hash
+func knuth_hash(in []byte) uint64 {
+	var acc uint64 = 3074457345618258791
+	for i := 0; i < len(in); i++ {
+		acc += uint64(in[i])
+		acc *= 3074457345618258799
+	}
+	return acc
+}
+
+var _rand *mrand.Rand
+
+func init() {
+	var seed1 uint64 = mmh3f(uint64(time.Now().UnixNano()))
+	var seed2 uint64 = knuth_hash([]byte(strings.Join(os.Environ(), "")))
+	var seed3 uint64 = mmh3f(uint64(os.Getpid()))
+
+	_rand = mrand.New(mrand.NewSource(int64(seed1 ^ seed2 ^ seed3)))
+}
+
+func saltByte(buff []byte) []byte {
+	for i := 0; i < len(buff); i++ {
+		var v uint64 = uint64(_rand.Int63())
+		var b byte
+		for j := 0; j < 8; j++ {
+			b ^= byte(v & 0xff)
+			v = v >> 8
+		}
+		buff[i] = b
+	}
+	return buff
+}
+
+//On Unix-like systems, Reader reads from /dev/urandom.
+//On Windows systems, Reader uses the CryptGenRandom API.
+
+//use entropy pool etc and cryptographic random number generator
+//mix in time
+//mix in mix in cpu cycle count
+func RandByte(n int) []byte {
+	buff := make([]byte, n)
+	ret, err := io.ReadFull(crand.Reader, buff)
+	if len(buff) != ret || err != nil {
+		return nil
+	}
+
+	buff2 := RandByteWeakCrypto(n)
+	for i := 0; i < n; i++ {
+		buff[i] ^= buff2[2]
+	}
+	return buff
+}
+
+/*
+	On Unix-like systems, Reader reads from /dev/urandom.
+	On Windows systems, Reader uses the CryptGenRandom API.
+*/
+func RandByteWeakCrypto(n int) []byte {
+	buff := make([]byte, n)
+	ret, err := io.ReadFull(crand.Reader, buff)
+	if len(buff) != ret || err != nil {
+		return nil
+	}
+	return buff
+}
diff --git a/crypto/secp256k1/secp256_test.go b/crypto/secp256k1/secp256_test.go
new file mode 100644
index 000000000..468c50db9
--- /dev/null
+++ b/crypto/secp256k1/secp256_test.go
@@ -0,0 +1,228 @@
+package secp256k1
+
+import (
+	"bytes"
+	"fmt"
+	"log"
+	"testing"
+)
+
+const TESTS = 10000 // how many tests
+const SigSize = 65  //64+1
+
+func Test_Secp256_00(t *testing.T) {
+
+	var nonce []byte = RandByte(32) //going to get bitcoins stolen!
+
+	if len(nonce) != 32 {
+		t.Fatal()
+	}
+
+}
+
+//tests for Malleability
+//highest bit of S must be 0; 32nd byte
+func CompactSigTest(sig []byte) {
+
+	var b int = int(sig[32])
+	if b < 0 {
+		log.Panic()
+	}
+	if ((b >> 7) == 1) != ((b & 0x80) == 0x80) {
+		log.Panic("b= %v b2= %v \n", b, b>>7)
+	}
+	if (b & 0x80) == 0x80 {
+		log.Panic("b= %v b2= %v \n", b, b&0x80)
+	}
+}
+
+//test pubkey/private generation
+func Test_Secp256_01(t *testing.T) {
+	pubkey, seckey := GenerateKeyPair()
+	if err := VerifySeckeyValidity(seckey); err != nil {
+		t.Fatal()
+	}
+	if err := VerifyPubkeyValidity(pubkey); err != nil {
+		t.Fatal()
+	}
+}
+
+//test size of messages
+func Test_Secp256_02s(t *testing.T) {
+	pubkey, seckey := GenerateKeyPair()
+	msg := RandByte(32)
+	sig, _ := Sign(msg, seckey)
+	CompactSigTest(sig)
+	if sig == nil {
+		t.Fatal("Signature nil")
+	}
+	if len(pubkey) != 65 {
+		t.Fail()
+	}
+	if len(seckey) != 32 {
+		t.Fail()
+	}
+	if len(sig) != 64+1 {
+		t.Fail()
+	}
+	if int(sig[64]) > 4 {
+		t.Fail()
+	} //should be 0 to 4
+}
+
+//test signing message
+func Test_Secp256_02(t *testing.T) {
+	pubkey1, seckey := GenerateKeyPair()
+	msg := RandByte(32)
+	sig, _ := Sign(msg, seckey)
+	if sig == nil {
+		t.Fatal("Signature nil")
+	}
+
+	pubkey2, _ := RecoverPubkey(msg, sig)
+	if pubkey2 == nil {
+		t.Fatal("Recovered pubkey invalid")
+	}
+	if bytes.Equal(pubkey1, pubkey2) == false {
+		t.Fatal("Recovered pubkey does not match")
+	}
+
+	err := VerifySignature(msg, sig, pubkey1)
+	if err != nil {
+		t.Fatal("Signature invalid")
+	}
+}
+
+//test pubkey recovery
+func Test_Secp256_02a(t *testing.T) {
+	pubkey1, seckey1 := GenerateKeyPair()
+	msg := RandByte(32)
+	sig, _ := Sign(msg, seckey1)
+
+	if sig == nil {
+		t.Fatal("Signature nil")
+	}
+	err := VerifySignature(msg, sig, pubkey1)
+	if err != nil {
+		t.Fatal("Signature invalid")
+	}
+
+	pubkey2, _ := RecoverPubkey(msg, sig)
+	if len(pubkey1) != len(pubkey2) {
+		t.Fatal()
+	}
+	for i, _ := range pubkey1 {
+		if pubkey1[i] != pubkey2[i] {
+			t.Fatal()
+		}
+	}
+	if bytes.Equal(pubkey1, pubkey2) == false {
+		t.Fatal()
+	}
+}
+
+//test random messages for the same pub/private key
+func Test_Secp256_03(t *testing.T) {
+	_, seckey := GenerateKeyPair()
+	for i := 0; i < TESTS; i++ {
+		msg := RandByte(32)
+		sig, _ := Sign(msg, seckey)
+		CompactSigTest(sig)
+
+		sig[len(sig)-1] %= 4
+		pubkey2, _ := RecoverPubkey(msg, sig)
+		if pubkey2 == nil {
+			t.Fail()
+		}
+	}
+}
+
+//test random messages for different pub/private keys
+func Test_Secp256_04(t *testing.T) {
+	for i := 0; i < TESTS; i++ {
+		pubkey1, seckey := GenerateKeyPair()
+		msg := RandByte(32)
+		sig, _ := Sign(msg, seckey)
+		CompactSigTest(sig)
+
+		if sig[len(sig)-1] >= 4 {
+			t.Fail()
+		}
+		pubkey2, _ := RecoverPubkey(msg, sig)
+		if pubkey2 == nil {
+			t.Fail()
+		}
+		if bytes.Equal(pubkey1, pubkey2) == false {
+			t.Fail()
+		}
+	}
+}
+
+//test random signatures against fixed messages; should fail
+
+//crashes:
+//	-SIPA look at this
+
+func randSig() []byte {
+	sig := RandByte(65)
+	sig[32] &= 0x70
+	sig[64] %= 4
+	return sig
+}
+
+func Test_Secp256_06a_alt0(t *testing.T) {
+	pubkey1, seckey := GenerateKeyPair()
+	msg := RandByte(32)
+	sig, _ := Sign(msg, seckey)
+
+	if sig == nil {
+		t.Fail()
+	}
+	if len(sig) != 65 {
+		t.Fail()
+	}
+	for i := 0; i < TESTS; i++ {
+		sig = randSig()
+		pubkey2, _ := RecoverPubkey(msg, sig)
+
+		if bytes.Equal(pubkey1, pubkey2) == true {
+			t.Fail()
+		}
+
+		if pubkey2 != nil && VerifySignature(msg, sig, pubkey2) != nil {
+			t.Fail()
+		}
+
+		if VerifySignature(msg, sig, pubkey1) == nil {
+			t.Fail()
+		}
+	}
+}
+
+//test random messages against valid signature: should fail
+
+func Test_Secp256_06b(t *testing.T) {
+	pubkey1, seckey := GenerateKeyPair()
+	msg := RandByte(32)
+	sig, _ := Sign(msg, seckey)
+
+	fail_count := 0
+	for i := 0; i < TESTS; i++ {
+		msg = RandByte(32)
+		pubkey2, _ := RecoverPubkey(msg, sig)
+		if bytes.Equal(pubkey1, pubkey2) == true {
+			t.Fail()
+		}
+
+		if pubkey2 != nil && VerifySignature(msg, sig, pubkey2) != nil {
+			t.Fail()
+		}
+
+		if VerifySignature(msg, sig, pubkey1) == nil {
+			t.Fail()
+		}
+	}
+	if fail_count != 0 {
+		fmt.Printf("ERROR: Accepted signature for %v of %v random messages\n", fail_count, TESTS)
+	}
+}
diff --git a/crypto/secp256k1/secp256k1/COPYING b/crypto/secp256k1/secp256k1/COPYING
new file mode 100644
index 000000000..4522a5990
--- /dev/null
+++ b/crypto/secp256k1/secp256k1/COPYING
@@ -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.
diff --git a/crypto/secp256k1/secp256k1/Makefile b/crypto/secp256k1/secp256k1/Makefile
new file mode 100644
index 000000000..21628f308
--- /dev/null
+++ b/crypto/secp256k1/secp256k1/Makefile
@@ -0,0 +1,55 @@
+$(shell CC=$(CC) YASM=$(YASM) ./configure)
+include config.mk
+
+FILES := src/*.h src/impl/*.h
+
+JAVA_FILES := src/java/org_bitcoin_NativeSecp256k1.h src/java/org_bitcoin_NativeSecp256k1.c
+
+OBJS :=
+
+ifeq ($(USE_ASM), 1)
+    OBJS := $(OBJS) obj/field_5x$(HAVE_LIMB)_asm.o
+endif
+STD="gnu99"
+
+default: tests libsecp256k1.a libsecp256k1.so
+
+clean:
+	rm -rf obj/*.o bench tests *.a *.so config.mk
+
+obj/field_5x52_asm.o: src/field_5x52_asm.asm
+	$(YASM) -f elf64 -o obj/field_5x52_asm.o src/field_5x52_asm.asm
+
+obj/field_5x64_asm.o: src/field_5x64_asm.asm
+	$(YASM) -f elf64 -o obj/field_5x64_asm.o src/field_5x64_asm.asm
+
+obj/secp256k1.o: $(FILES) src/secp256k1.c include/secp256k1.h
+	$(CC) -fPIC -std=$(STD) $(CFLAGS) $(CFLAGS_EXTRA) -DNDEBUG -$(OPTLEVEL) src/secp256k1.c -c -o obj/secp256k1.o
+
+bench: $(FILES) src/bench.c $(OBJS)
+	$(CC) -fPIC -std=$(STD) $(CFLAGS) $(CFLAGS_EXTRA) $(CFLAGS_TEST_EXTRA) -DNDEBUG -$(OPTLEVEL) src/bench.c $(OBJS) $(LDFLAGS_EXTRA) $(LDFLAGS_TEST_EXTRA) -o bench
+
+tests: $(FILES) src/tests.c $(OBJS)
+	$(CC) -std=$(STD) $(CFLAGS) $(CFLAGS_EXTRA) $(CFLAGS_TEST_EXTRA) -DVERIFY -fstack-protector-all -$(OPTLEVEL) -ggdb3 src/tests.c $(OBJS) $(LDFLAGS_EXTRA) $(LDFLAGS_TEST_EXTRA) -o tests
+
+tests_fuzzer: $(FILES) src/tests_fuzzer.c obj/secp256k1.o $(OBJS)
+	$(CC) -std=$(STD) $(CFLAGS) $(CFLAGS_EXTRA) $(CFLAGS_TEST_EXTRA) -DVERIFY -fstack-protector-all -$(OPTLEVEL) -ggdb3 src/tests_fuzzer.c $(OBJS) obj/secp256k1.o $(LDFLAGS_EXTRA) $(LDFLAGS_TEST_EXTRA) -o tests_fuzzer
+	
+coverage: $(FILES) src/tests.c $(OBJS)
+	rm -rf tests.gcno tests.gcda tests_cov
+	$(CC) -std=$(STD) $(CFLAGS) $(CFLAGS_EXTRA) $(CFLAGS_TEST_EXTRA) -DVERIFY --coverage -$(OPTLEVEL) -g src/tests.c $(OBJS) $(LDFLAGS_EXTRA) $(LDFLAGS_TEST_EXTRA) -o tests_cov
+	rm -rf lcov
+	mkdir -p lcov
+	cd lcov; lcov --directory ../ --zerocounters
+	cd lcov; ../tests_cov
+	cd lcov; lcov --directory ../ --capture --output-file secp256k1.info
+	cd lcov; genhtml -o . secp256k1.info
+
+libsecp256k1.a: obj/secp256k1.o $(OBJS)
+	$(AR) -rs $@ $(OBJS) obj/secp256k1.o
+
+libsecp256k1.so: obj/secp256k1.o $(OBJS)
+	$(CC) -std=$(STD) $(LDFLAGS_EXTRA) $(OBJS) obj/secp256k1.o -shared -o libsecp256k1.so
+
+libjavasecp256k1.so: $(OBJS) obj/secp256k1.o $(JAVA_FILES)
+	$(CC) -fPIC -std=$(STD) $(CFLAGS) $(CFLAGS_EXTRA) -DNDEBUG -$(OPTLEVEL) -I. src/java/org_bitcoin_NativeSecp256k1.c $(LDFLAGS_EXTRA) $(OBJS) obj/secp256k1.o -shared -o libjavasecp256k1.so
diff --git a/crypto/secp256k1/secp256k1/TODO b/crypto/secp256k1/secp256k1/TODO
new file mode 100644
index 000000000..a300e1c5e
--- /dev/null
+++ b/crypto/secp256k1/secp256k1/TODO
@@ -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
diff --git a/crypto/secp256k1/secp256k1/config.mk b/crypto/secp256k1/secp256k1/config.mk
new file mode 100644
index 000000000..3386b7bcb
--- /dev/null
+++ b/crypto/secp256k1/secp256k1/config.mk
@@ -0,0 +1,9 @@
+CC=cc
+YASM=yasm
+CFLAGS_EXTRA=-DUSE_FIELD_5X52 -DUSE_FIELD_5X52_ASM -DUSE_NUM_GMP -DUSE_FIELD_INV_NUM
+CFLAGS_TEST_EXTRA=-DENABLE_OPENSSL_TESTS
+LDFLAGS_EXTRA=-lgmp
+LDFLAGS_TEST_EXTRA=-lcrypto
+USE_ASM=1
+HAVE_LIMB=52
+OPTLEVEL=O2
diff --git a/crypto/secp256k1/secp256k1/configure b/crypto/secp256k1/secp256k1/configure
new file mode 100755
index 000000000..cb69239b7
--- /dev/null
+++ b/crypto/secp256k1/secp256k1/configure
@@ -0,0 +1,175 @@
+#!/bin/sh
+
+if test -f config.mk; then
+    exit 0
+fi
+
+if test -z "$CC"; then
+    CC=cc
+fi
+
+if test -z "$YASM"; then
+    YASM=yasm
+fi
+
+# test yasm
+$YASM -f elf64 -o /tmp/secp256k1-$$.o - <<EOF
+	BITS 64
+	GLOBAL testyasm
+	ALIGN 32
+testyasm:
+	xor r9,r9
+EOF
+if [ "$?" = 0 ]; then
+    $CC $CFLAGS -std=c99 -x c -c - -o /tmp/secp256k1-$$-2.o 2>/dev/null <<EOF
+void __attribute__ ((sysv_abi)) testyasm(void);
+int main() {
+    testyasm();
+    return 0;
+}
+EOF
+    $CC $CFLAGS -std=c99 /tmp/secp256k1-$$-2.o /tmp/secp256k1-$$.o -o /dev/null 2>/dev/null
+    if [ "$?" = 0 ]; then
+        HAVE_YASM=1
+    fi
+    rm -rf /tmp/secp256k1-$$-2.o /tmp/secp256k1-$$.o
+fi
+
+# test openssl
+HAVE_OPENSSL=0
+$CC $CFLAGS -std=c99 -x c - -o /dev/null -lcrypto 2>/dev/null <<EOF
+#include <openssl/bn.h>
+int main() {
+    BN_CTX *ctx = BN_CTX_new();
+    BN_CTX_free(ctx);
+    return 0;
+}
+EOF
+if [ "$?" = 0 ]; then
+    HAVE_OPENSSL=1
+fi
+
+# test openssl/EC
+HAVE_OPENSSL_EC=0
+if [ "$HAVE_OPENSSL" = "1" ]; then
+$CC $CFLAGS -std=c99 -x c - -o /dev/null -lcrypto 2>/dev/null <<EOF
+#include <openssl/ec.h>
+#include <openssl/ecdsa.h>
+#include <openssl/obj_mac.h>
+int main() {
+    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);
+    return 0;
+}
+EOF
+if [ "$?" = 0 ]; then
+    HAVE_OPENSSL_EC=1
+fi
+fi
+
+# test gmp
+HAVE_GMP=0
+$CC $CFLAGS -std=c99 -x c - -o /dev/null -lgmp 2>/dev/null <<EOF
+#include <gmp.h>
+int main() {
+    mpz_t n;
+    mpz_init(n);
+    mpz_clear(n);
+    return 0;
+}
+EOF
+if [ "$?" = 0 ]; then
+    HAVE_GMP=1
+fi
+
+# test __int128
+HAVE_INT128=0
+$CC $CFLAGS -std=c99 -x c - -o /dev/null 2>/dev/null <<EOF
+#include <stdint.h>
+int main() {
+    __int128 x = 0;
+    return 0;
+}
+EOF
+if [ "$?" = 0 ]; then
+    HAVE_INT128=1
+fi
+
+#default limb size
+HAVE_LIMB=52
+
+for arg in "$@"; do
+    case "$arg" in
+        --no-yasm)
+            HAVE_YASM=0
+            ;;
+        --no-gmp)
+            HAVE_GMP=0
+            ;;
+        --no-openssl)
+            HAVE_OPENSSL=0
+	    ;;
+	--use-5x64)
+	    HAVE_LIMB=64
+            ;;
+    esac
+done
+
+LINK_OPENSSL=0
+LINK_GMP=0
+USE_ASM=0
+
+# select field implementation
+if [ "$HAVE_YASM" = "1" ]; then
+    CFLAGS_FIELD="-DUSE_FIELD_5X$HAVE_LIMB -DUSE_FIELD_5X${HAVE_LIMB}_ASM"
+    USE_ASM=1
+elif [ "$HAVE_INT128" = "1" ]; then
+    CFLAGS_FIELD="-DUSE_FIELD_5X$HAVE_LIMB -DUSE_FIELD_5X${HAVE_LIMB}_INT128"
+elif [ "$HAVE_GMP" = "1" ]; then
+    CFLAGS_FIELD="-DUSE_FIELD_GMP"
+    LINK_GMP=1
+else
+    CFLAGS_FIELD="-DUSE_FIELD_10X26"
+fi
+
+# select num implementation
+if [ "$HAVE_GMP" = "1" ]; then
+    CFLAGS_NUM="-DUSE_NUM_GMP -DUSE_FIELD_INV_NUM"
+    LINK_GMP=1
+elif [ "$HAVE_OPENSSL" =  "1" ]; then
+    CFLAGS_NUM="-DUSE_NUM_OPENSSL -DUSE_FIELD_INV_BUILTIN"
+    LINK_OPENSSL=1
+else
+    echo "No usable num implementation found" >&2
+    exit 1
+fi
+
+CFLAGS_EXTRA="$CFLAGS_FIELD $CFLAGS_NUM"
+LDFLAGS_EXTRA=""
+if [ "$LINK_GMP" = "1" ]; then
+    LDFLAGS_EXTRA="-lgmp"
+fi
+if [ "$LINK_OPENSSL" = "1" ]; then
+    LDFLAGS_EXTRA="-lcrypto"
+else
+    if [ "$HAVE_OPENSSL_EC" = "1" ]; then
+        LDFLAGS_TEST_EXTRA="-lcrypto"
+    fi
+fi
+
+CFLAGS_TEST_EXTRA=""
+if [ "$HAVE_OPENSSL_EC" = "1" ]; then
+    CFLAGS_TEST_EXTRA="-DENABLE_OPENSSL_TESTS"
+fi
+
+echo "CC=$CC" > config.mk
+echo "YASM=$YASM" >>config.mk
+echo "CFLAGS_EXTRA=$CFLAGS_EXTRA" >> config.mk
+echo "CFLAGS_TEST_EXTRA=$CFLAGS_TEST_EXTRA" >> config.mk
+echo "LDFLAGS_EXTRA=$LDFLAGS_EXTRA" >> config.mk
+echo "LDFLAGS_TEST_EXTRA=$LDFLAGS_TEST_EXTRA" >> config.mk
+echo "USE_ASM=$USE_ASM" >>config.mk
+echo "HAVE_LIMB=$HAVE_LIMB" >>config.mk
+echo "OPTLEVEL=O2" >>config.mk
diff --git a/crypto/secp256k1/secp256k1/include/secp256k1.h b/crypto/secp256k1/secp256k1/include/secp256k1.h
new file mode 100644
index 000000000..fd6d6b1f4
--- /dev/null
+++ b/crypto/secp256k1/secp256k1/include/secp256k1.h
@@ -0,0 +1,121 @@
+#ifndef _SECP256K1_
+#define _SECP256K1_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** 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(void);
+
+/** 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
+ */
+int secp256k1_ecdsa_verify(const unsigned char *msg, int msglen,
+                           const unsigned char *sig, int siglen,
+                           const unsigned char *pubkey, int pubkeylen);
+
+/** Create an ECDSA signature.
+ *  Returns: 1: signature created
+ *           0: nonce invalid, try another one
+ *  In:      msg:    the message being signed
+ *           msglen: the length of the message being signed
+ *           seckey: pointer to a 32-byte secret key (assumed to be valid)
+ *           nonce:  pointer to a 32-byte nonce (generated with a cryptographic PRNG)
+ *  Out:     sig:    pointer to a 72-byte array where the signature will be placed.
+ *           siglen: pointer to an int, which will be updated to the signature length (<=72).
+ */
+int secp256k1_ecdsa_sign(const unsigned char *msg, int msglen,
+                         unsigned char *sig, int *siglen,
+                         const unsigned char *seckey,
+                         const unsigned char *nonce);
+
+/** 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
+ *           msglen: the length of the message being signed
+ *           seckey: pointer to a 32-byte secret key (assumed to be valid)
+ *           nonce:  pointer to a 32-byte nonce (generated with a cryptographic PRNG)
+ *  Out:     sig:    pointer to a 64-byte array where the signature will be placed.
+ *           recid:  pointer to an int, which will be updated to contain the recovery id.
+ */
+int secp256k1_ecdsa_sign_compact(const unsigned char *msg, int msglen,
+                                 unsigned char *sig64,
+                                 const unsigned char *seckey,
+                                 const unsigned char *nonce,
+                                 int *recid);
+
+/** Recover an ECDSA public key from a compact signature.
+ *  Returns: 1: public key succesfully recovered (which guarantees a correct signature).
+ *           0: otherwise.
+ *  In:      msg:        the message assumed to be signed
+ *           msglen:     the length of the message
+ *           sig64:      signature as 64 byte array
+ *           compressed: whether to recover a compressed or uncompressed pubkey
+ *           recid:      the recovery id (as returned by ecdsa_sign_compact)
+ *  Out:     pubkey:     pointer to a 33 or 65 byte array to put the pubkey.
+ *           pubkeylen:  pointer to an int that will contain the pubkey length.
+ */
+
+int secp256k1_ecdsa_recover_compact(const unsigned char *msg, int msglen,
+                                    const unsigned char *sig64,
+                                    unsigned char *pubkey, int *pubkeylen,
+                                    int compressed, int recid);
+
+/** 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
+ */
+int secp256k1_ecdsa_seckey_verify(const unsigned char *seckey);
+
+/** Just validate a public key.
+ *  Returns: 1: valid public key
+ *           0: invalid public key
+ */
+int secp256k1_ecdsa_pubkey_verify(const unsigned char *pubkey, int pubkeylen);
+
+/** 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.
+ *  Out:    pubkey:     pointer to a 33-byte (if compressed) or 65-byte (if uncompressed)
+ *                      area to store the public key.
+ *          pubkeylen:  pointer to int that will be updated to contains the pubkey's
+ *                      length.
+ *  Returns: 1: secret was valid, public key stores
+ *           0: secret was invalid, try again.
+ */
+int secp256k1_ecdsa_pubkey_create(unsigned char *pubkey, int *pubkeylen, const unsigned char *seckey, int compressed);
+
+int secp256k1_ecdsa_pubkey_decompress(unsigned char *pubkey, int *pubkeylen);
+
+int secp256k1_ecdsa_privkey_export(const unsigned char *seckey,
+                                   unsigned char *privkey, int *privkeylen,
+                                   int compressed);
+
+int secp256k1_ecdsa_privkey_import(unsigned char *seckey,
+                                   const unsigned char *privkey, int privkeylen);
+
+int secp256k1_ecdsa_privkey_tweak_add(unsigned char *seckey, const unsigned char *tweak);
+int secp256k1_ecdsa_pubkey_tweak_add(unsigned char *pubkey, int pubkeylen, const unsigned char *tweak);
+int secp256k1_ecdsa_privkey_tweak_mul(unsigned char *seckey, const unsigned char *tweak);
+int secp256k1_ecdsa_pubkey_tweak_mul(unsigned char *pubkey, int pubkeylen, const unsigned char *tweak);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/crypto/secp256k1/secp256k1/src/bench.c b/crypto/secp256k1/secp256k1/src/bench.c
new file mode 100644
index 000000000..eeb71343f
--- /dev/null
+++ b/crypto/secp256k1/secp256k1/src/bench.c
@@ -0,0 +1,64 @@
+// Copyright (c) 2013 Pieter Wuille
+// Distributed under the MIT/X11 software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <stdio.h>
+
+#include "impl/num.h"
+#include "impl/field.h"
+#include "impl/group.h"
+#include "impl/ecmult.h"
+#include "impl/ecdsa.h"
+#include "impl/util.h"
+
+void random_num_order(secp256k1_num_t *num) {
+    do {
+        unsigned char b32[32];
+        secp256k1_rand256(b32);
+        secp256k1_num_set_bin(num, b32, 32);
+        if (secp256k1_num_is_zero(num))
+            continue;
+        if (secp256k1_num_cmp(num, &secp256k1_ge_consts->order) >= 0)
+            continue;
+        break;
+    } while(1);
+}
+
+int main() {
+    secp256k1_fe_start();
+    secp256k1_ge_start();
+    secp256k1_ecmult_start();
+
+    secp256k1_fe_t x;
+    const secp256k1_num_t *order = &secp256k1_ge_consts->order;
+    secp256k1_num_t r, s, m;
+    secp256k1_num_init(&r);
+    secp256k1_num_init(&s);
+    secp256k1_num_init(&m);
+    secp256k1_ecdsa_sig_t sig;
+    secp256k1_ecdsa_sig_init(&sig);
+    secp256k1_fe_set_hex(&x, "a357ae915c4a65281309edf20504740f0eb3343990216b4f81063cb65f2f7e0f", 64);
+    int cnt = 0;
+    int good = 0;
+    for (int i=0; i<1000000; i++) {
+        random_num_order(&r);
+        random_num_order(&s);
+        random_num_order(&m);
+        secp256k1_ecdsa_sig_set_rs(&sig, &r, &s);
+        secp256k1_ge_t pubkey; secp256k1_ge_set_xo(&pubkey, &x, 1);
+        if (secp256k1_ge_is_valid(&pubkey)) {
+            cnt++;
+            good += secp256k1_ecdsa_sig_verify(&sig, &pubkey, &m);
+        }
+     }
+    printf("%i/%i\n", good, cnt);
+    secp256k1_num_free(&r);
+    secp256k1_num_free(&s);
+    secp256k1_num_free(&m);
+    secp256k1_ecdsa_sig_free(&sig);
+
+    secp256k1_ecmult_stop();
+    secp256k1_ge_stop();
+    secp256k1_fe_stop();
+    return 0;
+}
diff --git a/crypto/secp256k1/secp256k1/src/ecdsa.h b/crypto/secp256k1/secp256k1/src/ecdsa.h
new file mode 100644
index 000000000..d9faaa3e8
--- /dev/null
+++ b/crypto/secp256k1/secp256k1/src/ecdsa.h
@@ -0,0 +1,28 @@
+// Copyright (c) 2013 Pieter Wuille
+// Distributed under the MIT/X11 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;
+
+void static secp256k1_ecdsa_sig_init(secp256k1_ecdsa_sig_t *r);
+void static secp256k1_ecdsa_sig_free(secp256k1_ecdsa_sig_t *r);
+
+int static secp256k1_ecdsa_pubkey_parse(secp256k1_ge_t *elem, const unsigned char *pub, int size);
+void static secp256k1_ecdsa_pubkey_serialize(secp256k1_ge_t *elem, unsigned char *pub, int *size, int compressed);
+int static secp256k1_ecdsa_sig_parse(secp256k1_ecdsa_sig_t *r, const unsigned char *sig, int size);
+int static secp256k1_ecdsa_sig_serialize(unsigned char *sig, int *size, const secp256k1_ecdsa_sig_t *a);
+int static secp256k1_ecdsa_sig_verify(const secp256k1_ecdsa_sig_t *sig, const secp256k1_ge_t *pubkey, const secp256k1_num_t *message);
+int static secp256k1_ecdsa_sig_sign(secp256k1_ecdsa_sig_t *sig, const secp256k1_num_t *seckey, const secp256k1_num_t *message, const secp256k1_num_t *nonce, int *recid);
+int static secp256k1_ecdsa_sig_recover(const secp256k1_ecdsa_sig_t *sig, secp256k1_ge_t *pubkey, const secp256k1_num_t *message, int recid);
+void static secp256k1_ecdsa_sig_set_rs(secp256k1_ecdsa_sig_t *sig, const secp256k1_num_t *r, const secp256k1_num_t *s);
+int static secp256k1_ecdsa_privkey_parse(secp256k1_num_t *key, const unsigned char *privkey, int privkeylen);
+int static secp256k1_ecdsa_privkey_serialize(unsigned char *privkey, int *privkeylen, const secp256k1_num_t *key, int compressed);
+
+#endif
diff --git a/crypto/secp256k1/secp256k1/src/ecmult.h b/crypto/secp256k1/secp256k1/src/ecmult.h
new file mode 100644
index 000000000..856bd284f
--- /dev/null
+++ b/crypto/secp256k1/secp256k1/src/ecmult.h
@@ -0,0 +1,19 @@
+// Copyright (c) 2013 Pieter Wuille
+// Distributed under the MIT/X11 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);
+
+/** Multiply with the generator: R = a*G */
+static void secp256k1_ecmult_gen(secp256k1_gej_t *r, const secp256k1_num_t *a);
+/** 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
diff --git a/crypto/secp256k1/secp256k1/src/field.h b/crypto/secp256k1/secp256k1/src/field.h
new file mode 100644
index 000000000..4e0f26179
--- /dev/null
+++ b/crypto/secp256k1/secp256k1/src/field.h
@@ -0,0 +1,101 @@
+// Copyright (c) 2013 Pieter Wuille
+// Distributed under the MIT/X11 software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef _SECP256K1_FIELD_
+#define _SECP256K1_FIELD_
+
+/** Field element module.
+ *
+ *  Field elements can be represented in several ways, but code accessing
+ *  it (and implementations) need to take certain properaties into account:
+ *  - Each field element can be normalized or not.
+ *  - Each field element has a magnitude, which represents how far away
+ *    its representation is away from normalization. Normalized elements
+ *    always have a magnitude of 1, but a magnitude of 1 doesn't imply
+ *    normality.
+ */
+
+#if defined(USE_FIELD_GMP)
+#include "field_gmp.h"
+#elif defined(USE_FIELD_10X26)
+#include "field_10x26.h"
+#elif defined(USE_FIELD_5X52)
+#include "field_5x52.h"
+#elif defined(USE_FIELD_5X64)
+#include "field_5x64.h"
+#else
+#error "Please select field implementation"
+#endif
+
+typedef struct {
+    secp256k1_num_t p;
+} secp256k1_fe_consts_t;
+
+static const secp256k1_fe_consts_t *secp256k1_fe_consts = NULL;
+
+/** Initialize field element precomputation data. */
+void static secp256k1_fe_start(void);
+
+/** Unload field element precomputation data. */
+void static secp256k1_fe_stop(void);
+
+/** Normalize a field element. */
+void static secp256k1_fe_normalize(secp256k1_fe_t *r);
+
+/** Set a field element equal to a small integer. Resulting field element is normalized. */
+void static secp256k1_fe_set_int(secp256k1_fe_t *r, int a);
+
+/** Verify whether a field element is zero. Requires the input to be normalized. */
+int  static secp256k1_fe_is_zero(const secp256k1_fe_t *a);
+
+/** Check the "oddness" of a field element. Requires the input to be normalized. */
+int  static secp256k1_fe_is_odd(const secp256k1_fe_t *a);
+
+/** Compare two field elements. Requires both inputs to be normalized */
+int  static secp256k1_fe_equal(const secp256k1_fe_t *a, const secp256k1_fe_t *b);
+
+/** Set a field element equal to 32-byte big endian value. Resulting field element is normalized. */
+void static secp256k1_fe_set_b32(secp256k1_fe_t *r, const unsigned char *a);
+
+/** Convert a field element to a 32-byte big endian value. Requires the input to be normalized */
+void static secp256k1_fe_get_b32(unsigned char *r, const secp256k1_fe_t *a);
+
+/** Set a field element equal to the additive inverse of another. Takes a maximum magnitude of the input
+ *  as an argument. The magnitude of the output is one higher. */
+void static secp256k1_fe_negate(secp256k1_fe_t *r, const secp256k1_fe_t *a, int m);
+
+/** Multiplies the passed field element with a small integer constant. Multiplies the magnitude by that
+ *  small integer. */
+void static secp256k1_fe_mul_int(secp256k1_fe_t *r, int a);
+
+/** Adds a field element to another. The result has the sum of the inputs' magnitudes as magnitude. */
+void static secp256k1_fe_add(secp256k1_fe_t *r, const secp256k1_fe_t *a);
+
+/** Sets a field element to be the product of two others. Requires the inputs' magnitudes to be at most 8.
+ *  The output magnitude is 1 (but not guaranteed to be normalized). */
+void static secp256k1_fe_mul(secp256k1_fe_t *r, const secp256k1_fe_t *a, const secp256k1_fe_t *b);
+
+/** Sets a field element to be the square of another. Requires the input's magnitude to be at most 8.
+ *  The output magnitude is 1 (but not guaranteed to be normalized). */
+void static secp256k1_fe_sqr(secp256k1_fe_t *r, const secp256k1_fe_t *a);
+
+/** Sets a field element to be the (modular) square root of another. Requires the inputs' magnitude to
+ *  be at most 8. The output magnitude is 1 (but not guaranteed to be normalized). */
+void static secp256k1_fe_sqrt(secp256k1_fe_t *r, const secp256k1_fe_t *a);
+
+/** Sets a field element to be the (modular) inverse of another. Requires the input's magnitude to be
+ *  at most 8. The output magnitude is 1 (but not guaranteed to be normalized). */
+void static secp256k1_fe_inv(secp256k1_fe_t *r, const secp256k1_fe_t *a);
+
+/** Potentially faster version of secp256k1_fe_inv, without constant-time guarantee. */
+void static secp256k1_fe_inv_var(secp256k1_fe_t *r, const secp256k1_fe_t *a);
+
+
+/** Convert a field element to a hexadecimal string. */
+void static secp256k1_fe_get_hex(char *r, int *rlen, const secp256k1_fe_t *a);
+
+/** Convert a hexadecimal string to a field element. */
+void static secp256k1_fe_set_hex(secp256k1_fe_t *r, const char *a, int alen);
+
+#endif
diff --git a/crypto/secp256k1/secp256k1/src/field_10x26.h b/crypto/secp256k1/secp256k1/src/field_10x26.h
new file mode 100644
index 000000000..d544139e8
--- /dev/null
+++ b/crypto/secp256k1/secp256k1/src/field_10x26.h
@@ -0,0 +1,19 @@
+// Copyright (c) 2013 Pieter Wuille
+// Distributed under the MIT/X11 software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef _SECP256K1_FIELD_REPR_
+#define _SECP256K1_FIELD_REPR_
+
+#include <stdint.h>
+
+typedef struct {
+    // X = sum(i=0..9, elem[i]*2^26) mod n
+    uint32_t n[10];
+#ifdef VERIFY
+    int magnitude;
+    int normalized;
+#endif
+} secp256k1_fe_t;
+
+#endif
diff --git a/crypto/secp256k1/secp256k1/src/field_5x52.h b/crypto/secp256k1/secp256k1/src/field_5x52.h
new file mode 100644
index 000000000..9d5de2cc4
--- /dev/null
+++ b/crypto/secp256k1/secp256k1/src/field_5x52.h
@@ -0,0 +1,19 @@
+// Copyright (c) 2013 Pieter Wuille
+// Distributed under the MIT/X11 software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef _SECP256K1_FIELD_REPR_
+#define _SECP256K1_FIELD_REPR_
+
+#include <stdint.h>
+
+typedef struct {
+    // X = sum(i=0..4, elem[i]*2^52) mod n
+    uint64_t n[5];
+#ifdef VERIFY
+    int magnitude;
+    int normalized;
+#endif
+} secp256k1_fe_t;
+
+#endif
diff --git a/crypto/secp256k1/secp256k1/src/field_5x52_asm.asm b/crypto/secp256k1/secp256k1/src/field_5x52_asm.asm
new file mode 100644
index 000000000..9237b3687
--- /dev/null
+++ b/crypto/secp256k1/secp256k1/src/field_5x52_asm.asm
@@ -0,0 +1,463 @@
+	;; Added by Diederik Huys, March 2013
+	;;
+	;; Provided public procedures:
+	;; 	secp256k1_fe_mul_inner
+	;; 	secp256k1_fe_sqr_inner
+	;;
+	;; Needed tools: YASM (http://yasm.tortall.net)
+	;;
+	;; 
+
+	BITS 64
+
+	;;  Procedure ExSetMult
+	;;  Register Layout:
+	;;  INPUT: 	rdi	= a->n
+	;; 	   	rsi  	= b->n
+	;; 	   	rdx  	= r->a
+	;; 
+	;;  INTERNAL:	rdx:rax  = multiplication accumulator
+	;; 		r9:r8    = c
+	;; 		r10-r13  = t0-t3
+	;; 		r14	 = b.n[0] / t4
+	;; 		r15	 = b.n[1] / t5
+	;; 		rbx	 = b.n[2] / t6
+	;; 		rcx	 = b.n[3] / t7
+	;; 		rbp	 = Constant 0FFFFFFFFFFFFFh / t8
+	;; 		rsi	 = b.n / b.n[4] / t9
+
+	GLOBAL secp256k1_fe_mul_inner
+	ALIGN 32
+secp256k1_fe_mul_inner:
+	push rbp
+	push rbx
+	push r12
+	push r13
+	push r14
+	push r15
+	push rdx
+	mov r14,[rsi+8*0]	; preload b.n[0]. This will be the case until
+				; b.n[0] is no longer needed, then we reassign
+				; r14 to t4
+	;; c=a.n[0] * b.n[0]
+   	mov rax,[rdi+0*8]	; load a.n[0]
+	mov rbp,0FFFFFFFFFFFFFh
+	mul r14			; rdx:rax=a.n[0]*b.n[0]
+	mov r15,[rsi+1*8]
+	mov r10,rbp		; load modulus into target register for t0
+	mov r8,rax
+	and r10,rax		; only need lower qword of c
+	shrd r8,rdx,52
+	xor r9,r9		; c < 2^64, so we ditch the HO part 
+
+	;; c+=a.n[0] * b.n[1] + a.n[1] * b.n[0]
+	mov rax,[rdi+0*8]
+	mul r15			
+	add r8,rax
+	adc r9,rdx
+
+	mov rax,[rdi+1*8]
+	mul r14			
+	mov r11,rbp
+	mov rbx,[rsi+2*8]
+	add r8,rax
+	adc r9,rdx
+	and r11,r8
+	shrd r8,r9,52
+	xor r9,r9
+	
+	;; c+=a.n[0 1 2] * b.n[2 1 0]
+	mov rax,[rdi+0*8]
+	mul rbx			
+	add r8,rax
+	adc r9,rdx
+
+	mov rax,[rdi+1*8]
+	mul r15			
+	add r8,rax
+	adc r9,rdx
+
+	mov rax,[rdi+2*8]
+	mul r14
+	mov r12,rbp		
+	mov rcx,[rsi+3*8]
+	add r8,rax
+	adc r9,rdx
+	and r12,r8		
+	shrd r8,r9,52
+	xor r9,r9		
+
+	;; c+=a.n[0 1 2 3] * b.n[3 2 1 0]
+	mov rax,[rdi+0*8]
+	mul rcx			
+	add r8,rax
+	adc r9,rdx
+
+	mov rax,[rdi+1*8]
+	mul rbx			
+	add r8,rax
+	adc r9,rdx
+
+	mov rax,[rdi+2*8]
+	mul r15			
+	add r8,rax
+	adc r9,rdx
+	
+	mov rax,[rdi+3*8]
+	mul r14			
+	mov r13,rbp             
+	mov rsi,[rsi+4*8]	; load b.n[4] and destroy pointer
+	add r8,rax
+	adc r9,rdx
+	and r13,r8
+
+	shrd r8,r9,52
+	xor r9,r9		
+
+
+	;; c+=a.n[0 1 2 3 4] * b.n[4 3 2 1 0]
+	mov rax,[rdi+0*8]
+	mul rsi
+	add r8,rax
+	adc r9,rdx
+
+	mov rax,[rdi+1*8]
+	mul rcx
+	add r8,rax
+	adc r9,rdx
+
+	mov rax,[rdi+2*8]
+	mul rbx			
+	add r8,rax
+	adc r9,rdx
+
+	mov rax,[rdi+3*8]
+	mul r15			
+	add r8,rax
+	adc r9,rdx
+
+	mov rax,[rdi+4*8]
+	mul r14			
+	mov r14,rbp             ; load modulus into t4 and destroy a.n[0]
+	add r8,rax
+	adc r9,rdx
+	and r14,r8
+	shrd r8,r9,52
+	xor r9,r9		
+
+	;; c+=a.n[1 2 3 4] * b.n[4 3 2 1]
+	mov rax,[rdi+1*8]
+	mul rsi
+	add r8,rax
+	adc r9,rdx
+
+	mov rax,[rdi+2*8]
+	mul rcx
+	add r8,rax
+	adc r9,rdx
+
+	mov rax,[rdi+3*8]
+	mul rbx
+	add r8,rax
+	adc r9,rdx
+
+	mov rax,[rdi+4*8]
+	mul r15
+	mov r15,rbp		
+	add r8,rax
+	adc r9,rdx
+
+	and r15,r8
+	shrd r8,r9,52
+	xor r9,r9		
+
+	;; c+=a.n[2 3 4] * b.n[4 3 2]
+	mov rax,[rdi+2*8]
+	mul rsi
+	add r8,rax
+	adc r9,rdx
+
+	mov rax,[rdi+3*8]
+	mul rcx
+	add r8,rax
+	adc r9,rdx
+
+	mov rax,[rdi+4*8]
+	mul rbx
+	mov rbx,rbp		
+	add r8,rax
+	adc r9,rdx
+
+	and rbx,r8		
+	shrd r8,r9,52
+	xor r9,r9		
+
+	;; c+=a.n[3 4] * b.n[4 3]
+	mov rax,[rdi+3*8]
+	mul rsi
+	add r8,rax
+	adc r9,rdx
+
+	mov rax,[rdi+4*8]
+	mul rcx
+	mov rcx,rbp		
+	add r8,rax
+	adc r9,rdx
+	and rcx,r8		
+	shrd r8,r9,52
+	xor r9,r9		
+
+	;; c+=a.n[4] * b.n[4]
+	mov rax,[rdi+4*8]
+	mul rsi
+	;; mov rbp,rbp		; modulus already there!
+	add r8,rax
+	adc r9,rdx
+	and rbp,r8 
+	shrd r8,r9,52
+	xor r9,r9		
+
+	mov rsi,r8		; load c into t9 and destroy b.n[4]
+
+	;; *******************************************************
+common_exit_norm:
+	mov rdi,01000003D10h	; load constant
+
+	mov rax,r15		; get t5
+	mul rdi
+	add rax,r10    		; +t0
+	adc rdx,0
+	mov r10,0FFFFFFFFFFFFFh ; modulus. Sadly, we ran out of registers!
+	mov r8,rax		; +c
+	and r10,rax
+	shrd r8,rdx,52
+	xor r9,r9
+
+	mov rax,rbx		; get t6
+	mul rdi
+	add rax,r11		; +t1
+	adc rdx,0
+	mov r11,0FFFFFFFFFFFFFh ; modulus
+	add r8,rax		; +c
+	adc r9,rdx
+	and r11,r8
+	shrd r8,r9,52
+	xor r9,r9
+
+	mov rax,rcx    		; get t7
+	mul rdi
+	add rax,r12		; +t2
+	adc rdx,0
+	pop rbx			; retrieve pointer to this.n	
+	mov r12,0FFFFFFFFFFFFFh ; modulus
+	add r8,rax		; +c
+	adc r9,rdx
+	and r12,r8
+	mov [rbx+2*8],r12	; mov into this.n[2]
+	shrd r8,r9,52
+	xor r9,r9
+	
+	mov rax,rbp    		; get t8
+	mul rdi
+	add rax,r13    		; +t3
+	adc rdx,0
+	mov r13,0FFFFFFFFFFFFFh ; modulus
+	add r8,rax		; +c
+	adc r9,rdx
+	and r13,r8
+	mov [rbx+3*8],r13	; -> this.n[3]
+	shrd r8,r9,52
+	xor r9,r9
+	
+	mov rax,rsi    		; get t9
+	mul rdi
+	add rax,r14    		; +t4
+	adc rdx,0
+	mov r14,0FFFFFFFFFFFFh	; !!!
+	add r8,rax		; +c
+	adc r9,rdx
+	and r14,r8
+	mov [rbx+4*8],r14	; -> this.n[4]
+	shrd r8,r9,48		; !!!
+	xor r9,r9
+	
+	mov rax,01000003D1h
+	mul r8		
+	add rax,r10
+	adc rdx,0
+	mov r10,0FFFFFFFFFFFFFh ; modulus
+	mov r8,rax
+	and rax,r10
+	shrd r8,rdx,52
+	mov [rbx+0*8],rax	; -> this.n[0]
+	add r8,r11
+	mov [rbx+1*8],r8	; -> this.n[1]
+
+	pop r15
+	pop r14
+	pop r13
+	pop r12
+	pop rbx
+	pop rbp
+	ret
+
+	
+	;;  PROC ExSetSquare
+	;;  Register Layout:
+	;;  INPUT: 	rdi	 = a.n
+	;; 	   	rsi  	 = this.a
+	;;  INTERNAL:	rdx:rax  = multiplication accumulator
+	;; 		r9:r8    = c
+	;; 		r10-r13  = t0-t3
+	;; 		r14	 = a.n[0] / t4
+	;; 		r15	 = a.n[1] / t5
+	;; 		rbx	 = a.n[2] / t6
+	;; 		rcx	 = a.n[3] / t7
+	;; 		rbp	 = 0FFFFFFFFFFFFFh / t8
+	;; 		rsi	 = a.n[4] / t9
+	GLOBAL secp256k1_fe_sqr_inner
+	ALIGN 32
+secp256k1_fe_sqr_inner:
+	push rbp
+	push rbx
+	push r12
+	push r13
+	push r14
+	push r15
+	push rsi
+	mov rbp,0FFFFFFFFFFFFFh
+	
+	;; c=a.n[0] * a.n[0]
+   	mov r14,[rdi+0*8]	; r14=a.n[0]
+	mov r10,rbp		; modulus 
+	mov rax,r14
+	mul rax
+	mov r15,[rdi+1*8]	; a.n[1]
+	add r14,r14		; r14=2*a.n[0]
+	mov r8,rax
+	and r10,rax		; only need lower qword
+	shrd r8,rdx,52
+	xor r9,r9
+
+	;; c+=2*a.n[0] * a.n[1]
+	mov rax,r14		; r14=2*a.n[0]
+	mul r15
+	mov rbx,[rdi+2*8]	; rbx=a.n[2]
+	mov r11,rbp 		; modulus
+	add r8,rax
+	adc r9,rdx
+	and r11,r8
+	shrd r8,r9,52
+	xor r9,r9
+	
+	;; c+=2*a.n[0]*a.n[2]+a.n[1]*a.n[1]
+	mov rax,r14
+	mul rbx
+	add r8,rax
+	adc r9,rdx
+
+	mov rax,r15
+	mov r12,rbp		; modulus
+	mul rax
+	mov rcx,[rdi+3*8]	; rcx=a.n[3]
+	add r15,r15		; r15=a.n[1]*2
+	add r8,rax
+	adc r9,rdx
+	and r12,r8		; only need lower dword
+	shrd r8,r9,52
+	xor r9,r9		
+
+	;; c+=2*a.n[0]*a.n[3]+2*a.n[1]*a.n[2]
+	mov rax,r14
+	mul rcx
+	add r8,rax
+	adc r9,rdx
+
+	mov rax,r15		; rax=2*a.n[1]
+	mov r13,rbp		; modulus
+	mul rbx
+	mov rsi,[rdi+4*8]	; rsi=a.n[4]
+	add r8,rax
+	adc r9,rdx
+	and r13,r8
+	shrd r8,r9,52
+	xor r9,r9		
+
+	;; c+=2*a.n[0]*a.n[4]+2*a.n[1]*a.n[3]+a.n[2]*a.n[2]
+	mov rax,r14		; last time we need 2*a.n[0]
+	mul rsi
+	add r8,rax
+	adc r9,rdx
+
+	mov rax,r15
+	mul rcx
+	mov r14,rbp		; modulus
+	add r8,rax
+	adc r9,rdx
+
+	mov rax,rbx
+	mul rax
+	add rbx,rbx		; rcx=2*a.n[2]
+	add r8,rax
+	adc r9,rdx
+	and r14,r8
+	shrd r8,r9,52
+	xor r9,r9		
+
+	;; c+=2*a.n[1]*a.n[4]+2*a.n[2]*a.n[3]
+	mov rax,r15		; last time we need 2*a.n[1]
+	mul rsi
+	add r8,rax
+	adc r9,rdx
+
+	mov rax,rbx
+	mul rcx
+	mov r15,rbp		; modulus
+	add r8,rax
+	adc r9,rdx
+	and r15,r8
+	shrd r8,r9,52
+	xor r9,r9		
+
+	;; c+=2*a.n[2]*a.n[4]+a.n[3]*a.n[3]
+	mov rax,rbx		; last time we need 2*a.n[2]
+	mul rsi
+	add r8,rax
+	adc r9,rdx
+
+	mov rax,rcx		; a.n[3]
+	mul rax
+	mov rbx,rbp		; modulus
+	add r8,rax
+	adc r9,rdx
+	and rbx,r8		; only need lower dword
+	lea rax,[2*rcx]
+	shrd r8,r9,52
+	xor r9,r9		
+
+	;; c+=2*a.n[3]*a.n[4]
+	mul rsi
+	mov rcx,rbp		; modulus
+	add r8,rax
+	adc r9,rdx
+	and rcx,r8		; only need lower dword
+	shrd r8,r9,52
+	xor r9,r9		
+
+	;; c+=a.n[4]*a.n[4]
+	mov rax,rsi
+	mul rax
+	;; mov rbp,rbp		; modulus is already there!
+	add r8,rax
+	adc r9,rdx
+	and rbp,r8 
+	shrd r8,r9,52
+	xor r9,r9		
+
+	mov rsi,r8
+
+	;; *******************************************************
+	jmp common_exit_norm
+	end
+
+	
diff --git a/crypto/secp256k1/secp256k1/src/field_5x64.h b/crypto/secp256k1/secp256k1/src/field_5x64.h
new file mode 100644
index 000000000..f3d47f547
--- /dev/null
+++ b/crypto/secp256k1/secp256k1/src/field_5x64.h
@@ -0,0 +1,19 @@
+// Copyright (c) 2013 Pieter Wuille
+// Distributed under the MIT/X11 software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef _SECP256K1_FIELD_REPR_
+#define _SECP256K1_FIELD_REPR_
+
+#include <stdint.h>
+
+typedef struct {
+    // X = sum(i=0..4, elem[i]*2^64) mod n
+    uint64_t n[5];
+#ifdef VERIFY
+    int reduced; // n[4] == 0
+    int normalized; // reduced and X < 2^256 - 0x100003D1
+#endif
+} secp256k1_fe_t;
+
+#endif
diff --git a/crypto/secp256k1/secp256k1/src/field_5x64_asm.asm b/crypto/secp256k1/secp256k1/src/field_5x64_asm.asm
new file mode 100644
index 000000000..d449185c7
--- /dev/null
+++ b/crypto/secp256k1/secp256k1/src/field_5x64_asm.asm
@@ -0,0 +1,332 @@
+	;; Added by Diederik Huys, March 2013
+	;;
+	;; Provided public procedures:
+	;; 	secp256k1_fe_mul_inner
+	;; 	secp256k1_fe_sqr_inner
+	;;
+	;; Needed tools: YASM (http://yasm.tortall.net)
+	;;
+	;; 
+
+	BITS 64
+
+COMP_LIMB EQU 000000001000003D1h
+	
+	;;  Procedure ExSetMult
+	;;  Register Layout:
+	;;  INPUT: 	rdi	= a->n
+	;; 	   	rsi  	= b->n
+	;; 	   	rdx  	= r->a
+	;; 
+	;;  INTERNAL:	rdx:rax  = multiplication accumulator
+	;; 		r8-r10   = c0-c2
+	;; 		r11-r15  = b.n[0]-b.n[4] / r3 - r7
+	;; 		rbx	 = r0
+	;; 		rcx	 = r1
+	;; 		rbp	 = r2
+	;; 	  
+	GLOBAL secp256k1_fe_mul_inner
+	ALIGN 32
+secp256k1_fe_mul_inner:
+	push rbp
+	push rbx
+	push r12
+	push r13
+	push r14
+	push r15
+	push rdx
+
+	mov r11,[rsi+8*0]	; preload b.n[0]
+
+	;;  step 1: mul_c2
+   	mov rax,[rdi+0*8]	; load a.n[0]
+	mul r11			; rdx:rax=a.n[0]*b.n[0]
+	mov r12,[rsi+1*8]	; preload b.n[1]
+	mov rbx,rax		; retire LO qword (r[0])
+	mov r8,rdx		; save overflow
+	xor r9,r9		; overflow HO qwords
+	xor r10,r10
+	
+	;; c+=a.n[0] * b.n[1] + a.n[1] * b.n[0]
+	mov rax,[rdi+0*8]
+	mul r12				
+	mov r13,[rsi+2*8]	; preload b.n[2]
+	add r8,rax		; still the same :-)
+	adc r9,rdx		; 
+	adc r10,0		; mmm...
+	
+	mov rax,[rdi+1*8]
+	mul r11			
+	add r8,rax
+	adc r9,rdx
+	adc r10,0
+	mov rcx,r8	; retire r[1]
+	xor r8,r8
+	
+	;; c+=a.n[0 1 2] * b.n[2 1 0]
+	mov rax,[rdi+0*8]
+	mul r13			
+	mov r14,[rsi+3*8]	; preload b.n[3]
+	add r9,rax
+	adc r10,rdx
+	adc r8,0
+	
+	mov rax,[rdi+1*8]
+	mul r12			
+	add r9,rax
+	adc r10,rdx
+	adc r8,0
+	
+	mov rax,[rdi+2*8]
+	mul r11
+	add r9,rax
+	adc r10,rdx
+	adc r8,0
+	mov rbp,r9		; retire r[2]
+	xor r9,r9
+
+	;; c+=a.n[0 1 2 3] * b.n[3 2 1 0]
+	mov rax,[rdi+0*8]
+	mul r14		
+	add r10,rax
+	adc r8,rdx
+	adc r9,0
+
+	mov rax,[rdi+1*8]
+	mul r13
+	add r10,rax
+	adc r8,rdx
+	adc r9,0
+
+	mov rax,[rdi+2*8]
+	mul r12
+	add r10,rax
+	adc r8,rdx
+	adc r9,0
+	
+	mov rax,[rdi+3*8]
+	mul r11			
+	add r10,rax
+	adc r8,rdx
+	adc r9,0
+	mov r11,r10		; retire r[3]
+	xor r10,r10
+
+	;; c+=a.n[1 2 3] * b.n[3 2 1]
+	mov rax,[rdi+1*8]
+	mul r14		
+	add r8,rax
+	adc r9,rdx
+	adc r10,0
+	
+	mov rax,[rdi+2*8]
+	mul r13		
+	add r8,rax
+	adc r9,rdx
+	adc r10,0
+	
+	mov rax,[rdi+3*8]
+	mul r12
+	add r8,rax
+	adc r9,rdx
+	adc r10,0
+	mov r12,r8		; retire r[4]
+	xor r8,r8		
+
+	;; c+=a.n[2 3] * b.n[3 2]
+	mov rax,[rdi+2*8]
+	mul r14
+	add r9,rax		; still the same :-)
+	adc r10,rdx		; 
+	adc r8,0		; mmm...
+	
+	mov rax,[rdi+3*8]
+	mul r13		
+	add r9,rax
+	adc r10,rdx
+	adc r8,0
+	mov r13,r9		; retire r[5]
+	xor r9,r9
+
+	;; c+=a.n[3] * b.n[3]
+	mov rax,[rdi+3*8]
+	mul r14
+	add r10,rax
+	adc r8,rdx
+	
+	mov r14,r10
+	mov r15,r8
+	
+
+	;; *******************************************************
+common_exit_norm:
+	mov rdi,COMP_LIMB
+	mov rax,r12
+	mul rdi
+	add rax,rbx
+	adc rcx,rdx
+	pop rbx
+	mov [rbx],rax
+
+	mov rax,r13		; get r5
+	mul rdi
+	add rax,rcx    		; +r1
+	adc rbp,rdx
+	mov [rbx+1*8],rax
+	
+	mov rax,r14		; get r6
+	mul rdi
+	add rax,rbp    		; +r2
+	adc r11,rdx
+	mov [rbx+2*8],rax
+	
+	mov rax,r15		; get r7
+	mul rdi
+	add rax,r11    		; +r3
+	adc rdx,0
+	mov [rbx+3*8],rax
+	mov [rbx+4*8],rdx
+	
+	pop r15
+	pop r14
+	pop r13
+	pop r12
+	pop rbx
+	pop rbp
+	ret
+
+	
+	;;  PROC ExSetSquare
+	;;  Register Layout:
+	;;  INPUT: 	rdi	 = a.n
+	;; 	   	rsi  	 = this.a
+	;;  INTERNAL:	rdx:rax  = multiplication accumulator
+	;; 		r8-r10   = c
+	;; 		r11-r15  = a.n[0]-a.n[4] / r3-r7
+	;; 		rbx	 = r0
+	;; 		rcx	 = r1
+	;; 		rbp	 = r2
+	GLOBAL secp256k1_fe_sqr_inner
+	
+	ALIGN 32
+secp256k1_fe_sqr_inner:
+	push rbp
+	push rbx
+	push r12
+	push r13
+	push r14
+	push r15
+	push rsi
+
+	mov r11,[rdi+8*0]	; preload a.n[0]
+	
+	;;  step 1: mul_c2
+   	mov rax,r11		; load a.n[0]
+	mul rax			; rdx:rax=a.n[0]²
+	mov r12,[rdi+1*8]	; preload a.n[1]
+	mov rbx,rax		; retire LO qword (r[0])
+	mov r8,rdx		; save overflow
+	xor r9,r9		; overflow HO qwords
+	xor r10,r10
+	
+	;; c+=2*a.n[0] * a.n[1]
+	mov rax,r11		; load a.n[0]
+	mul r12			; rdx:rax=a.n[0] * a.n[1]
+	mov r13,[rdi+2*8]	; preload a.n[2]
+	add rax,rax		; rdx:rax*=2
+	adc rdx,rdx
+	adc r10,0
+	add r8,rax		; still the same :-)
+	adc r9,rdx		
+	adc r10,0		; mmm...
+	
+	mov rcx,r8		; retire r[1]
+	xor r8,r8
+
+	;; c+=2*a.n[0]*a.n[2]+a.n[1]*a.n[1]
+	mov rax,r11		; load a.n[0]
+	mul r13			; * a.n[2]
+	mov r14,[rdi+3*8]	; preload a.n[3]
+	add rax,rax		; rdx:rax*=2
+	adc rdx,rdx
+	adc r8,0
+	add r9,rax
+	adc r10,rdx
+	adc r8,0
+
+	mov rax,r12
+	mul rax
+	add r9,rax
+	adc r10,rdx
+	adc r8,0
+	
+	
+	mov rbp,r9
+	xor r9,r9
+	
+	;; c+=2*a.n[0]*a.n[3]+2*a.n[1]*a.n[2]
+	mov rax,r11		; load a.n[0]
+	mul r14			; * a.n[3]
+	add rax,rax		; rdx:rax*=2
+	adc rdx,rdx
+	adc r9,0
+	add r10,rax
+	adc r8,rdx
+	adc r9,0
+
+	mov rax,r12		; load a.n[1]
+	mul r13			; * a.n[2]
+	add rax,rax
+	adc rdx,rdx
+	adc r9,0
+	add r10,rax
+	adc r8,rdx
+	adc r9,0
+		
+	mov r11,r10
+	xor r10,r10
+
+	;; c+=2*a.n[1]*a.n[3]+a.n[2]*a.n[2]
+	mov rax,r12		; load a.n[1]
+	mul r14			; * a.n[3]
+	add rax,rax		; rdx:rax*=2
+	adc rdx,rdx
+	adc r10,0
+	add r8,rax
+	adc r9,rdx
+	adc r10,0
+
+	mov rax,r13
+	mul rax
+	add r8,rax
+	adc r9,rdx
+	adc r10,0
+
+	mov r12,r8
+	xor r8,r8
+	;; c+=2*a.n[2]*a.n[3]
+	mov rax,r13		; load a.n[2]
+	mul r14			; * a.n[3]
+	add rax,rax		; rdx:rax*=2
+	adc rdx,rdx
+	adc r8,0
+	add r9,rax
+	adc r10,rdx
+	adc r8,0
+
+	mov r13,r9
+	xor r9,r9
+
+	;; c+=a.n[3]²
+	mov rax,r14
+	mul rax
+	add r10,rax
+	adc r8,rdx
+	
+	mov r14,r10
+	mov r15,r8
+	
+	jmp common_exit_norm
+	end
+
+	
diff --git a/crypto/secp256k1/secp256k1/src/field_gmp.h b/crypto/secp256k1/secp256k1/src/field_gmp.h
new file mode 100644
index 000000000..d51dea0af
--- /dev/null
+++ b/crypto/secp256k1/secp256k1/src/field_gmp.h
@@ -0,0 +1,16 @@
+// Copyright (c) 2013 Pieter Wuille
+// Distributed under the MIT/X11 software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef _SECP256K1_FIELD_REPR_
+#define _SECP256K1_FIELD_REPR_
+
+#include <gmp.h>
+
+#define FIELD_LIMBS ((256 + GMP_NUMB_BITS - 1) / GMP_NUMB_BITS)
+
+typedef struct {
+    mp_limb_t n[FIELD_LIMBS+1];
+} secp256k1_fe_t;
+
+#endif
diff --git a/crypto/secp256k1/secp256k1/src/group.h b/crypto/secp256k1/secp256k1/src/group.h
new file mode 100644
index 000000000..ae291c6ca
--- /dev/null
+++ b/crypto/secp256k1/secp256k1/src/group.h
@@ -0,0 +1,108 @@
+// Copyright (c) 2013 Pieter Wuille
+// Distributed under the MIT/X11 software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef _SECP256K1_GROUP_
+#define _SECP256K1_GROUP_
+
+#include "num.h"
+#include "field.h"
+
+/** A group element of the secp256k1 curve, in affine coordinates. */
+typedef struct {
+    secp256k1_fe_t x;
+    secp256k1_fe_t y;
+    int infinity; // whether this represents the point at infinity
+} secp256k1_ge_t;
+
+/** A group element of the secp256k1 curve, in jacobian coordinates. */
+typedef struct {
+    secp256k1_fe_t x; // actual X: x/z^2
+    secp256k1_fe_t y; // actual Y: y/z^3
+    secp256k1_fe_t z;
+    int infinity; // whether this represents the point at infinity
+} secp256k1_gej_t;
+
+/** Global constants related to the group */
+typedef struct {
+    secp256k1_num_t order; // the order of the curve (= order of its generator)
+    secp256k1_num_t half_order; // half the order of the curve (= order of its generator)
+    secp256k1_ge_t g; // the generator point
+
+    // constants related to secp256k1's efficiently computable endomorphism
+    secp256k1_fe_t beta;
+    secp256k1_num_t lambda, a1b2, b1, a2;
+} secp256k1_ge_consts_t;
+
+static const secp256k1_ge_consts_t *secp256k1_ge_consts = NULL;
+
+/** Initialize the group module. */
+void static secp256k1_ge_start(void);
+
+/** De-initialize the group module. */
+void static secp256k1_ge_stop(void);
+
+/** Set a group element equal to the point at infinity */
+void static secp256k1_ge_set_infinity(secp256k1_ge_t *r);
+
+/** Set a group element equal to the point with given X and Y coordinates */
+void static secp256k1_ge_set_xy(secp256k1_ge_t *r, const secp256k1_fe_t *x, const secp256k1_fe_t *y);
+
+/** Set a group element (jacobian) equal to the point with given X coordinate, and given oddness for Y.
+    The result is not guaranteed to be valid. */
+void static secp256k1_ge_set_xo(secp256k1_ge_t *r, const secp256k1_fe_t *x, int odd);
+
+/** Check whether a group element is the point at infinity. */
+int  static secp256k1_ge_is_infinity(const secp256k1_ge_t *a);
+
+/** Check whether a group element is valid (i.e., on the curve). */
+int  static secp256k1_ge_is_valid(const secp256k1_ge_t *a);
+
+void static secp256k1_ge_neg(secp256k1_ge_t *r, const secp256k1_ge_t *a);
+
+/** Get a hex representation of a point. *rlen will be overwritten with the real length. */
+void static secp256k1_ge_get_hex(char *r, int *rlen, const secp256k1_ge_t *a);
+
+/** Set a group element equal to another which is given in jacobian coordinates */
+void static secp256k1_ge_set_gej(secp256k1_ge_t *r, secp256k1_gej_t *a);
+
+
+/** Set a group element (jacobian) equal to the point at infinity. */
+void static secp256k1_gej_set_infinity(secp256k1_gej_t *r);
+
+/** Set a group element (jacobian) equal to the point with given X and Y coordinates. */
+void static secp256k1_gej_set_xy(secp256k1_gej_t *r, const secp256k1_fe_t *x, const secp256k1_fe_t *y);
+
+/** Set a group element (jacobian) equal to another which is given in affine coordinates. */
+void static secp256k1_gej_set_ge(secp256k1_gej_t *r, const secp256k1_ge_t *a);
+
+/** Get the X coordinate of a group element (jacobian). */
+void static secp256k1_gej_get_x(secp256k1_fe_t *r, const secp256k1_gej_t *a);
+
+/** Set r equal to the inverse of a (i.e., mirrored around the X axis) */
+void static secp256k1_gej_neg(secp256k1_gej_t *r, const secp256k1_gej_t *a);
+
+/** Check whether a group element is the point at infinity. */
+int  static secp256k1_gej_is_infinity(const secp256k1_gej_t *a);
+
+/** Set r equal to the double of a. */
+void static secp256k1_gej_double(secp256k1_gej_t *r, const secp256k1_gej_t *a);
+
+/** Set r equal to the sum of a and b. */
+void static secp256k1_gej_add(secp256k1_gej_t *r, const secp256k1_gej_t *a, const secp256k1_gej_t *b);
+
+/** Set r equal to the sum of a and b (with b given in jacobian coordinates). This is more efficient
+    than secp256k1_gej_add. */
+void static secp256k1_gej_add_ge(secp256k1_gej_t *r, const secp256k1_gej_t *a, const secp256k1_ge_t *b);
+
+/** Get a hex representation of a point. *rlen will be overwritten with the real length. */
+void static secp256k1_gej_get_hex(char *r, int *rlen, const secp256k1_gej_t *a);
+
+/** Set r to be equal to lambda times a, where lambda is chosen in a way such that this is very fast. */
+void static secp256k1_gej_mul_lambda(secp256k1_gej_t *r, const secp256k1_gej_t *a);
+
+/** Find r1 and r2 such that r1+r2*lambda = a, and r1 and r2 are maximum 128 bits long (given that a is
+    not more than 256 bits). */
+void static secp256k1_gej_split_exp(secp256k1_num_t *r1, secp256k1_num_t *r2, const secp256k1_num_t *a);
+
+#endif
diff --git a/crypto/secp256k1/secp256k1/src/impl/ecdsa.h b/crypto/secp256k1/secp256k1/src/impl/ecdsa.h
new file mode 100644
index 000000000..dd26cfd11
--- /dev/null
+++ b/crypto/secp256k1/secp256k1/src/impl/ecdsa.h
@@ -0,0 +1,309 @@
+// Copyright (c) 2013 Pieter Wuille
+// Distributed under the MIT/X11 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 "../ecdsa.h"
+
+void static secp256k1_ecdsa_sig_init(secp256k1_ecdsa_sig_t *r) {
+    secp256k1_num_init(&r->r);
+    secp256k1_num_init(&r->s);
+}
+
+void static secp256k1_ecdsa_sig_free(secp256k1_ecdsa_sig_t *r) {
+    secp256k1_num_free(&r->r);
+    secp256k1_num_free(&r->s);
+}
+
+int static secp256k1_ecdsa_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);
+        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;
+    } else {
+        return 0;
+    }
+    return secp256k1_ge_is_valid(elem);
+}
+
+int static 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;
+}
+
+int static 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;
+}
+
+int static 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(&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;
+}
+
+int static 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;
+    secp256k1_ge_set_xo(&x, &fx, recid & 1);
+    if (!secp256k1_ge_is_valid(&x))
+        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);
+    if (secp256k1_gej_is_infinity(&qj))
+        return 0;
+    secp256k1_ge_set_gej(pubkey, &qj);
+    secp256k1_num_free(&rn);
+    secp256k1_num_free(&u1);
+    secp256k1_num_free(&u2);
+    return 1;
+}
+
+int static 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;
+}
+
+int static secp256k1_ecdsa_sig_sign(secp256k1_ecdsa_sig_t *sig, const secp256k1_num_t *seckey, const secp256k1_num_t *message, const secp256k1_num_t *nonce, int *recid) {
+    const secp256k1_ge_consts_t *c = secp256k1_ge_consts;
+
+    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);
+    secp256k1_num_set_bin(&sig->r, b, 32);
+    if (recid)
+        *recid = (secp256k1_num_cmp(&sig->r, &c->order) >= 0 ? 2 : 0) | (secp256k1_fe_is_odd(&r.y) ? 1 : 0);
+    secp256k1_num_mod(&sig->r, &c->order);
+    secp256k1_num_t n;
+    secp256k1_num_init(&n);
+    secp256k1_num_mod_mul(&n, &sig->r, seckey, &c->order);
+    secp256k1_num_add(&n, &n, message);
+    secp256k1_num_mod(&n, &c->order);
+    secp256k1_num_mod_inverse(&sig->s, nonce, &c->order);
+    secp256k1_num_mod_mul(&sig->s, &sig->s, &n, &c->order);
+    secp256k1_num_free(&n);
+    if (secp256k1_num_is_zero(&sig->s))
+        return 0;
+    if (secp256k1_num_cmp(&sig->s, &c->half_order) > 0) {
+        secp256k1_num_sub(&sig->s, &c->order, &sig->s);
+        if (recid)
+            *recid ^= 1;
+    }
+    return 1;
+}
+
+void static 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);
+}
+
+void static secp256k1_ecdsa_pubkey_serialize(secp256k1_ge_t *elem, unsigned char *pub, int *size, int compressed) {
+    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);
+    }
+}
+
+int static secp256k1_ecdsa_privkey_parse(secp256k1_num_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;
+    secp256k1_num_set_bin(key, privkey+2, privkey[1]);
+    return 1;
+}
+
+int static secp256k1_ecdsa_privkey_serialize(unsigned char *privkey, int *privkeylen, const secp256k1_num_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_num_get_bin(ptr, 32, key); ptr += 32;
+        memcpy(ptr, middle, sizeof(middle)); ptr += sizeof(middle);
+        int pubkeylen = 0;
+        secp256k1_ecdsa_pubkey_serialize(&r, ptr, &pubkeylen, 1); 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_num_get_bin(ptr, 32, key); ptr += 32;
+        memcpy(ptr, middle, sizeof(middle)); ptr += sizeof(middle);
+        int pubkeylen = 0;
+        secp256k1_ecdsa_pubkey_serialize(&r, ptr, &pubkeylen, 0); ptr += pubkeylen;
+        *privkeylen = ptr - privkey;
+    }
+    return 1;
+}
+
+#endif
diff --git a/crypto/secp256k1/secp256k1/src/impl/ecmult.h b/crypto/secp256k1/secp256k1/src/impl/ecmult.h
new file mode 100644
index 000000000..6acb4c408
--- /dev/null
+++ b/crypto/secp256k1/secp256k1/src/impl/ecmult.h
@@ -0,0 +1,238 @@
+// Copyright (c) 2013 Pieter Wuille
+// Distributed under the MIT/X11 software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef _SECP256K1_ECMULT_IMPL_H_
+#define _SECP256K1_ECMULT_IMPL_H_
+
+#include "../num.h"
+#include "../group.h"
+#include "../ecmult.h"
+
+// optimal for 128-bit and 256-bit exponents.
+#define WINDOW_A 5
+
+// larger numbers may result in slightly better performance, at the cost of
+// exponentially larger precomputed tables. WINDOW_G == 14 results in 640 KiB.
+#define WINDOW_G 14
+
+/** Fill a table 'pre' with precomputed odd multiples of a. W determines the size of the table.
+ *  pre will contains the values [1*a,3*a,5*a,...,(2^(w-1)-1)*a], so it needs place for
+ *  2^(w-2) entries.
+ *
+ *  There are two versions of this function:
+ *  - secp256k1_ecmult_precomp_wnaf_gej, which operates on group elements in jacobian notation,
+ *    fast to precompute, but slower to use in later additions.
+ *  - secp256k1_ecmult_precomp_wnaf_ge, which operates on group elements in affine notations,
+ *    (much) slower to precompute, but a bit faster to use in later additions.
+ *  To compute a*P + b*G, we use the jacobian version for P, and the affine version for G, as
+ *  G is constant, so it only needs to be done once in advance.
+ */
+void static secp256k1_ecmult_table_precomp_gej(secp256k1_gej_t *pre, const secp256k1_gej_t *a, int w) {
+    pre[0] = *a;
+    secp256k1_gej_t d; secp256k1_gej_double(&d, &pre[0]);
+    for (int i=1; i<(1 << (w-2)); i++)
+        secp256k1_gej_add(&pre[i], &d, &pre[i-1]);
+}
+
+void static secp256k1_ecmult_table_precomp_ge(secp256k1_ge_t *pre, const secp256k1_ge_t *a, int w) {
+    pre[0] = *a;
+    secp256k1_gej_t x; secp256k1_gej_set_ge(&x, a);
+    secp256k1_gej_t d; secp256k1_gej_double(&d, &x);
+    for (int i=1; i<(1 << (w-2)); i++) {
+        secp256k1_gej_add_ge(&x, &d, &pre[i-1]);
+        secp256k1_ge_set_gej(&pre[i], &x);
+    }
+}
+
+/** The number of entries a table with precomputed multiples needs to have. */
+#define ECMULT_TABLE_SIZE(w) (1 << ((w)-2))
+
+/** The following two macro retrieves a particular odd multiple from a table
+ *  of precomputed multiples. */
+#define ECMULT_TABLE_GET(r,pre,n,w,neg) do { \
+    assert(((n) & 1) == 1); \
+    assert((n) >= -((1 << ((w)-1)) - 1)); \
+    assert((n) <=  ((1 << ((w)-1)) - 1)); \
+    if ((n) > 0) \
+        *(r) = (pre)[((n)-1)/2]; \
+    else \
+        (neg)((r), &(pre)[(-(n)-1)/2]); \
+} while(0)
+
+#define ECMULT_TABLE_GET_GEJ(r,pre,n,w) ECMULT_TABLE_GET((r),(pre),(n),(w),secp256k1_gej_neg)
+#define ECMULT_TABLE_GET_GE(r,pre,n,w)  ECMULT_TABLE_GET((r),(pre),(n),(w),secp256k1_ge_neg)
+
+typedef struct {
+    secp256k1_ge_t pre_g[ECMULT_TABLE_SIZE(WINDOW_G)];    // odd multiples of the generator
+    secp256k1_ge_t pre_g_128[ECMULT_TABLE_SIZE(WINDOW_G)]; // odd multiples of 2^128*generator
+    secp256k1_ge_t prec[64][16]; // prec[j][i] = 16^j * (i+1) * G
+    secp256k1_ge_t fin; // -(sum(prec[j][0], j=0..63))
+} secp256k1_ecmult_consts_t;
+
+static const secp256k1_ecmult_consts_t *secp256k1_ecmult_consts = NULL;
+
+static void secp256k1_ecmult_start(void) {
+    if (secp256k1_ecmult_consts != NULL)
+        return;
+
+    secp256k1_ecmult_consts_t *ret = (secp256k1_ecmult_consts_t*)malloc(sizeof(secp256k1_ecmult_consts_t));
+    secp256k1_ecmult_consts = ret;
+
+    // get the generator
+    const secp256k1_ge_t *g = &secp256k1_ge_consts->g;
+
+    // calculate 2^128*generator
+    secp256k1_gej_t g_128j; secp256k1_gej_set_ge(&g_128j, g);
+    for (int i=0; i<128; i++)
+        secp256k1_gej_double(&g_128j, &g_128j);
+    secp256k1_ge_t g_128; secp256k1_ge_set_gej(&g_128, &g_128j);
+
+    // precompute the tables with odd multiples
+    secp256k1_ecmult_table_precomp_ge(ret->pre_g, g, WINDOW_G);
+    secp256k1_ecmult_table_precomp_ge(ret->pre_g_128, &g_128, WINDOW_G);
+
+    // compute prec and fin
+    secp256k1_gej_t gg; secp256k1_gej_set_ge(&gg, g);
+    secp256k1_ge_t ad = *g;
+    secp256k1_gej_t fn; secp256k1_gej_set_infinity(&fn);
+    for (int j=0; j<64; j++) {
+        secp256k1_ge_set_gej(&ret->prec[j][0], &gg);
+        secp256k1_gej_add(&fn, &fn, &gg);
+        for (int i=1; i<16; i++) {
+            secp256k1_gej_add_ge(&gg, &gg, &ad);
+            secp256k1_ge_set_gej(&ret->prec[j][i], &gg);
+        }
+        ad = ret->prec[j][15];
+    }
+    secp256k1_ge_set_gej(&ret->fin, &fn);
+    secp256k1_ge_neg(&ret->fin, &ret->fin);
+}
+
+static void secp256k1_ecmult_stop(void) {
+    if (secp256k1_ecmult_consts == NULL)
+        return;
+
+    secp256k1_ecmult_consts_t *c = (secp256k1_ecmult_consts_t*)secp256k1_ecmult_consts;
+    free(c);
+    secp256k1_ecmult_consts = NULL;
+}
+
+/** Convert a number to WNAF notation. The number becomes represented by sum(2^i * wnaf[i], i=0..bits),
+ *  with the following guarantees:
+ *  - each wnaf[i] is either 0, or an odd integer between -(1<<(w-1) - 1) and (1<<(w-1) - 1)
+ *  - two non-zero entries in wnaf are separated by at least w-1 zeroes.
+ *  - the index of the highest non-zero entry in wnaf (=return value-1) is at most bits, where
+ *    bits is the number of bits necessary to represent the absolute value of the input.
+ */
+static int secp256k1_ecmult_wnaf(int *wnaf, const secp256k1_num_t *a, int w) {
+    int ret = 0;
+    int zeroes = 0;
+    secp256k1_num_t x;
+    secp256k1_num_init(&x);
+    secp256k1_num_copy(&x, a);
+    int sign = 1;
+    if (secp256k1_num_is_neg(&x)) {
+        sign = -1;
+        secp256k1_num_negate(&x);
+    }
+    while (!secp256k1_num_is_zero(&x)) {
+        while (!secp256k1_num_is_odd(&x)) {
+            zeroes++;
+            secp256k1_num_shift(&x, 1);
+        }
+        int word = secp256k1_num_shift(&x, w);
+        while (zeroes) {
+            wnaf[ret++] = 0;
+            zeroes--;
+        }
+        if (word & (1 << (w-1))) {
+            secp256k1_num_inc(&x);
+            wnaf[ret++] = sign * (word - (1 << w));
+        } else {
+            wnaf[ret++] = sign * word;
+        }
+        zeroes = w-1;
+    }
+    secp256k1_num_free(&x);
+    return ret;
+}
+
+void static secp256k1_ecmult_gen(secp256k1_gej_t *r, const secp256k1_num_t *gn) {
+    secp256k1_num_t n;
+    secp256k1_num_init(&n);
+    secp256k1_num_copy(&n, gn);
+    const secp256k1_ecmult_consts_t *c = secp256k1_ecmult_consts;
+    secp256k1_gej_set_ge(r, &c->prec[0][secp256k1_num_shift(&n, 4)]);
+    for (int j=1; j<64; j++)
+        secp256k1_gej_add_ge(r, r, &c->prec[j][secp256k1_num_shift(&n, 4)]);
+    secp256k1_num_free(&n);
+    secp256k1_gej_add_ge(r, r, &c->fin);
+}
+
+void static secp256k1_ecmult(secp256k1_gej_t *r, const secp256k1_gej_t *a, const secp256k1_num_t *na, const secp256k1_num_t *ng) {
+    const secp256k1_ecmult_consts_t *c = secp256k1_ecmult_consts;
+
+    secp256k1_num_t na_1, na_lam;
+    secp256k1_num_t ng_1, ng_128;
+    secp256k1_num_init(&na_1);
+    secp256k1_num_init(&na_lam);
+    secp256k1_num_init(&ng_1);
+    secp256k1_num_init(&ng_128);
+
+    // split na into na_1 and na_lam (where na = na_1 + na_lam*lambda, and na_1 and na_lam are ~128 bit)
+    secp256k1_gej_split_exp(&na_1, &na_lam, na);
+    // split ng into ng_1 and ng_128 (where gn = gn_1 + gn_128*2^128, and gn_1 and gn_128 are ~128 bit)
+    secp256k1_num_split(&ng_1, &ng_128, ng, 128);
+
+    // build wnaf representation for na_1, na_lam, ng_1, ng_128
+    int wnaf_na_1[129];   int bits_na_1   = secp256k1_ecmult_wnaf(wnaf_na_1,   &na_1,   WINDOW_A);
+    int wnaf_na_lam[129]; int bits_na_lam = secp256k1_ecmult_wnaf(wnaf_na_lam, &na_lam, WINDOW_A);
+    int wnaf_ng_1[129];   int bits_ng_1   = secp256k1_ecmult_wnaf(wnaf_ng_1,   &ng_1,   WINDOW_G);
+    int wnaf_ng_128[129]; int bits_ng_128 = secp256k1_ecmult_wnaf(wnaf_ng_128, &ng_128, WINDOW_G);
+
+    // calculate a_lam = a*lambda
+    secp256k1_gej_t a_lam; secp256k1_gej_mul_lambda(&a_lam, a);
+
+    // calculate odd multiples of a and a_lam
+    secp256k1_gej_t pre_a_1[ECMULT_TABLE_SIZE(WINDOW_A)], pre_a_lam[ECMULT_TABLE_SIZE(WINDOW_A)];
+    secp256k1_ecmult_table_precomp_gej(pre_a_1,   a,      WINDOW_A);
+    secp256k1_ecmult_table_precomp_gej(pre_a_lam, &a_lam, WINDOW_A);
+
+    int bits = bits_na_1;
+    if (bits_na_lam > bits) bits = bits_na_lam;
+    if (bits_ng_1 > bits) bits = bits_ng_1;
+    if (bits_ng_128 > bits) bits = bits_ng_128;
+
+    secp256k1_gej_set_infinity(r);
+    secp256k1_gej_t tmpj;
+    secp256k1_ge_t tmpa;
+
+    for (int i=bits-1; i>=0; i--) {
+        secp256k1_gej_double(r, r);
+        int n;
+        if (i < bits_na_1 && (n = wnaf_na_1[i])) {
+            ECMULT_TABLE_GET_GEJ(&tmpj, pre_a_1, n, WINDOW_A);
+            secp256k1_gej_add(r, r, &tmpj);
+        }
+        if (i < bits_na_lam && (n = wnaf_na_lam[i])) {
+            ECMULT_TABLE_GET_GEJ(&tmpj, pre_a_lam, n, WINDOW_A);
+            secp256k1_gej_add(r, r, &tmpj);
+        }
+        if (i < bits_ng_1 && (n = wnaf_ng_1[i])) {
+            ECMULT_TABLE_GET_GE(&tmpa, c->pre_g, n, WINDOW_G);
+            secp256k1_gej_add_ge(r, r, &tmpa);
+        }
+        if (i < bits_ng_128 && (n = wnaf_ng_128[i])) {
+            ECMULT_TABLE_GET_GE(&tmpa, c->pre_g_128, n, WINDOW_G);
+            secp256k1_gej_add_ge(r, r, &tmpa);
+        }
+    }
+
+    secp256k1_num_free(&na_1);
+    secp256k1_num_free(&na_lam);
+    secp256k1_num_free(&ng_1);
+    secp256k1_num_free(&ng_128);
+}
+
+#endif
diff --git a/crypto/secp256k1/secp256k1/src/impl/field.h b/crypto/secp256k1/secp256k1/src/impl/field.h
new file mode 100644
index 000000000..edb2acadc
--- /dev/null
+++ b/crypto/secp256k1/secp256k1/src/impl/field.h
@@ -0,0 +1,175 @@
+// Copyright (c) 2013 Pieter Wuille
+// Distributed under the MIT/X11 software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef _SECP256K1_FIELD_IMPL_H_
+#define _SECP256K1_FIELD_IMPL_H_
+
+#if defined(USE_FIELD_GMP)
+#include "field_gmp.h"
+#elif defined(USE_FIELD_10X26)
+#include "field_10x26.h"
+#elif defined(USE_FIELD_5X52)
+#include "field_5x52.h"
+#elif defined(USE_FIELD_5X64)
+#include "field_5x64.h"
+#else
+#error "Please select field implementation"
+#endif
+
+void static secp256k1_fe_get_hex(char *r, int *rlen, const secp256k1_fe_t *a) {
+    if (*rlen < 65) {
+        *rlen = 65;
+        return;
+    }
+    *rlen = 65;
+    unsigned char tmp[32];
+    secp256k1_fe_t b = *a;
+    secp256k1_fe_normalize(&b);
+    secp256k1_fe_get_b32(tmp, &b);
+    for (int i=0; i<32; i++) {
+        static const char *c = "0123456789ABCDEF";
+        r[2*i]   = c[(tmp[i] >> 4) & 0xF];
+        r[2*i+1] = c[(tmp[i]) & 0xF];
+    }
+    r[64] = 0x00;
+}
+
+void static secp256k1_fe_set_hex(secp256k1_fe_t *r, const char *a, int alen) {
+    unsigned char tmp[32] = {};
+    static const int cvt[256] = {0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,
+                                 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,
+                                 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,
+                                 0, 1, 2, 3, 4, 5, 6,7,8,9,0,0,0,0,0,0,
+                                 0,10,11,12,13,14,15,0,0,0,0,0,0,0,0,0,
+                                 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,
+                                 0,10,11,12,13,14,15,0,0,0,0,0,0,0,0,0,
+                                 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,
+                                 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,
+                                 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,
+                                 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,
+                                 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,
+                                 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,
+                                 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,
+                                 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,
+                                 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0};
+    for (int i=0; i<32; i++) {
+        if (alen > i*2)
+            tmp[32 - alen/2 + i] = (cvt[(unsigned char)a[2*i]] << 4) + cvt[(unsigned char)a[2*i+1]];
+    }
+    secp256k1_fe_set_b32(r, tmp);
+}
+
+void static secp256k1_fe_sqrt(secp256k1_fe_t *r, const secp256k1_fe_t *a) {
+    // calculate a^p, with p={15,780,1022,1023}
+    secp256k1_fe_t a2; secp256k1_fe_sqr(&a2, a);
+    secp256k1_fe_t a3; secp256k1_fe_mul(&a3, &a2, a);
+    secp256k1_fe_t a6; secp256k1_fe_sqr(&a6, &a3);
+    secp256k1_fe_t a12; secp256k1_fe_sqr(&a12, &a6);
+    secp256k1_fe_t a15; secp256k1_fe_mul(&a15, &a12, &a3);
+    secp256k1_fe_t a30; secp256k1_fe_sqr(&a30, &a15);
+    secp256k1_fe_t a60; secp256k1_fe_sqr(&a60, &a30);
+    secp256k1_fe_t a120; secp256k1_fe_sqr(&a120, &a60);
+    secp256k1_fe_t a240; secp256k1_fe_sqr(&a240, &a120);
+    secp256k1_fe_t a255; secp256k1_fe_mul(&a255, &a240, &a15);
+    secp256k1_fe_t a510; secp256k1_fe_sqr(&a510, &a255);
+    secp256k1_fe_t a750; secp256k1_fe_mul(&a750, &a510, &a240);
+    secp256k1_fe_t a780; secp256k1_fe_mul(&a780, &a750, &a30);
+    secp256k1_fe_t a1020; secp256k1_fe_sqr(&a1020, &a510);
+    secp256k1_fe_t a1022; secp256k1_fe_mul(&a1022, &a1020, &a2);
+    secp256k1_fe_t a1023; secp256k1_fe_mul(&a1023, &a1022, a);
+    secp256k1_fe_t x = a15;
+    for (int i=0; i<21; i++) {
+        for (int j=0; j<10; j++) secp256k1_fe_sqr(&x, &x);
+        secp256k1_fe_mul(&x, &x, &a1023);
+    }
+    for (int j=0; j<10; j++) secp256k1_fe_sqr(&x, &x);
+    secp256k1_fe_mul(&x, &x, &a1022);
+    for (int i=0; i<2; i++) {
+        for (int j=0; j<10; j++) secp256k1_fe_sqr(&x, &x);
+        secp256k1_fe_mul(&x, &x, &a1023);
+    }
+    for (int j=0; j<10; j++) secp256k1_fe_sqr(&x, &x);
+    secp256k1_fe_mul(r, &x, &a780);
+}
+
+void static secp256k1_fe_inv(secp256k1_fe_t *r, const secp256k1_fe_t *a) {
+    // calculate a^p, with p={45,63,1019,1023}
+    secp256k1_fe_t a2; secp256k1_fe_sqr(&a2, a);
+    secp256k1_fe_t a3; secp256k1_fe_mul(&a3, &a2, a);
+    secp256k1_fe_t a4; secp256k1_fe_sqr(&a4, &a2);
+    secp256k1_fe_t a5; secp256k1_fe_mul(&a5, &a4, a);
+    secp256k1_fe_t a10; secp256k1_fe_sqr(&a10, &a5);
+    secp256k1_fe_t a11; secp256k1_fe_mul(&a11, &a10, a);
+    secp256k1_fe_t a21; secp256k1_fe_mul(&a21, &a11, &a10);
+    secp256k1_fe_t a42; secp256k1_fe_sqr(&a42, &a21);
+    secp256k1_fe_t a45; secp256k1_fe_mul(&a45, &a42, &a3);
+    secp256k1_fe_t a63; secp256k1_fe_mul(&a63, &a42, &a21);
+    secp256k1_fe_t a126; secp256k1_fe_sqr(&a126, &a63);
+    secp256k1_fe_t a252; secp256k1_fe_sqr(&a252, &a126);
+    secp256k1_fe_t a504; secp256k1_fe_sqr(&a504, &a252);
+    secp256k1_fe_t a1008; secp256k1_fe_sqr(&a1008, &a504);
+    secp256k1_fe_t a1019; secp256k1_fe_mul(&a1019, &a1008, &a11);
+    secp256k1_fe_t a1023; secp256k1_fe_mul(&a1023, &a1019, &a4);
+    secp256k1_fe_t x = a63;
+    for (int i=0; i<21; i++) {
+        for (int j=0; j<10; j++) secp256k1_fe_sqr(&x, &x);
+        secp256k1_fe_mul(&x, &x, &a1023);
+    }
+    for (int j=0; j<10; j++) secp256k1_fe_sqr(&x, &x);
+    secp256k1_fe_mul(&x, &x, &a1019);
+    for (int i=0; i<2; i++) {
+        for (int j=0; j<10; j++) secp256k1_fe_sqr(&x, &x);
+        secp256k1_fe_mul(&x, &x, &a1023);
+    }
+    for (int j=0; j<10; j++) secp256k1_fe_sqr(&x, &x);
+    secp256k1_fe_mul(r, &x, &a45);
+}
+
+void static secp256k1_fe_inv_var(secp256k1_fe_t *r, const secp256k1_fe_t *a) {
+#if defined(USE_FIELD_INV_BUILTIN)
+    secp256k1_fe_inv(r, a);
+#elif defined(USE_FIELD_INV_NUM)
+    unsigned char b[32];
+    secp256k1_fe_t c = *a;
+    secp256k1_fe_normalize(&c);
+    secp256k1_fe_get_b32(b, &c);
+    secp256k1_num_t n; 
+    secp256k1_num_init(&n);
+    secp256k1_num_set_bin(&n, b, 32);
+    secp256k1_num_mod_inverse(&n, &n, &secp256k1_fe_consts->p);
+    secp256k1_num_get_bin(b, 32, &n);
+    secp256k1_num_free(&n);
+    secp256k1_fe_set_b32(r, b);
+#else
+#error "Please select field inverse implementation"
+#endif
+}
+
+void static secp256k1_fe_start(void) {
+    static const unsigned char secp256k1_fe_consts_p[] = {
+        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
+    };
+    if (secp256k1_fe_consts == NULL) {
+        secp256k1_fe_inner_start();
+        secp256k1_fe_consts_t *ret = (secp256k1_fe_consts_t*)malloc(sizeof(secp256k1_fe_consts_t));
+        secp256k1_num_init(&ret->p);
+        secp256k1_num_set_bin(&ret->p, secp256k1_fe_consts_p, sizeof(secp256k1_fe_consts_p));
+        secp256k1_fe_consts = ret;
+    }
+}
+
+void static secp256k1_fe_stop(void) {
+    if (secp256k1_fe_consts != NULL) {
+        secp256k1_fe_consts_t *c = (secp256k1_fe_consts_t*)secp256k1_fe_consts;
+        secp256k1_num_free(&c->p);
+        free((void*)c);
+        secp256k1_fe_consts = NULL;
+        secp256k1_fe_inner_stop();
+    }
+}
+
+#endif
diff --git a/crypto/secp256k1/secp256k1/src/impl/field_10x26.h b/crypto/secp256k1/secp256k1/src/impl/field_10x26.h
new file mode 100644
index 000000000..449769254
--- /dev/null
+++ b/crypto/secp256k1/secp256k1/src/impl/field_10x26.h
@@ -0,0 +1,487 @@
+// Copyright (c) 2013 Pieter Wuille
+// Distributed under the MIT/X11 software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef _SECP256K1_FIELD_REPR_IMPL_H_
+#define _SECP256K1_FIELD_REPR_IMPL_H_
+
+#include <stdio.h>
+#include <assert.h>
+#include <string.h>
+#include "../num.h"
+#include "../field.h"
+
+void static secp256k1_fe_inner_start(void) {}
+void static secp256k1_fe_inner_stop(void) {}
+
+void static secp256k1_fe_normalize(secp256k1_fe_t *r) {
+//    fog("normalize in: ", r);
+    uint32_t c;
+    c = r->n[0];
+    uint32_t t0 = c & 0x3FFFFFFUL;
+    c = (c >> 26) + r->n[1];
+    uint32_t t1 = c & 0x3FFFFFFUL;
+    c = (c >> 26) + r->n[2];
+    uint32_t t2 = c & 0x3FFFFFFUL;
+    c = (c >> 26) + r->n[3];
+    uint32_t t3 = c & 0x3FFFFFFUL;
+    c = (c >> 26) + r->n[4];
+    uint32_t t4 = c & 0x3FFFFFFUL;
+    c = (c >> 26) + r->n[5];
+    uint32_t t5 = c & 0x3FFFFFFUL;
+    c = (c >> 26) + r->n[6];
+    uint32_t t6 = c & 0x3FFFFFFUL;
+    c = (c >> 26) + r->n[7];
+    uint32_t t7 = c & 0x3FFFFFFUL;
+    c = (c >> 26) + r->n[8];
+    uint32_t t8 = c & 0x3FFFFFFUL;
+    c = (c >> 26) + r->n[9];
+    uint32_t t9 = c & 0x03FFFFFUL;
+    c >>= 22;
+/*    r->n[0] = t0; r->n[1] = t1; r->n[2] = t2; r->n[3] = t3; r->n[4] = t4;
+    r->n[5] = t5; r->n[6] = t6; r->n[7] = t7; r->n[8] = t8; r->n[9] = t9;
+    fog("         tm1: ", r);
+    fprintf(stderr, "out c= %08lx\n", (unsigned long)c);*/
+
+    // The following code will not modify the t's if c is initially 0.
+    uint32_t d = c * 0x3D1UL + t0;
+    t0 = d & 0x3FFFFFFULL;
+    d = (d >> 26) + t1 + c*0x40;
+    t1 = d & 0x3FFFFFFULL;
+    d = (d >> 26) + t2;
+    t2 = d & 0x3FFFFFFULL;
+    d = (d >> 26) + t3;
+    t3 = d & 0x3FFFFFFULL;
+    d = (d >> 26) + t4;
+    t4 = d & 0x3FFFFFFULL;
+    d = (d >> 26) + t5;
+    t5 = d & 0x3FFFFFFULL;
+    d = (d >> 26) + t6;
+    t6 = d & 0x3FFFFFFULL;
+    d = (d >> 26) + t7;
+    t7 = d & 0x3FFFFFFULL;
+    d = (d >> 26) + t8;
+    t8 = d & 0x3FFFFFFULL;
+    d = (d >> 26) + t9;
+    t9 = d & 0x03FFFFFULL;
+    assert((d >> 22) == 0);
+/*    r->n[0] = t0; r->n[1] = t1; r->n[2] = t2; r->n[3] = t3; r->n[4] = t4;
+    r->n[5] = t5; r->n[6] = t6; r->n[7] = t7; r->n[8] = t8; r->n[9] = t9;
+    fog("         tm2: ", r); */
+
+    // Subtract p if result >= p
+    uint64_t low = ((uint64_t)t1 << 26) | t0;
+    uint64_t mask = -(int64_t)((t9 < 0x03FFFFFUL) | (t8 < 0x3FFFFFFUL) | (t7 < 0x3FFFFFFUL) | (t6 < 0x3FFFFFFUL) | (t5 < 0x3FFFFFFUL) | (t4 < 0x3FFFFFFUL) | (t3 < 0x3FFFFFFUL) | (t2 < 0x3FFFFFFUL) | (low < 0xFFFFEFFFFFC2FULL));
+    t9 &= mask;
+    t8 &= mask;
+    t7 &= mask;
+    t6 &= mask;
+    t5 &= mask;
+    t4 &= mask;
+    t3 &= mask;
+    t2 &= mask;
+    low -= (~mask & 0xFFFFEFFFFFC2FULL);
+
+    // push internal variables back
+    r->n[0] = low & 0x3FFFFFFUL; r->n[1] = (low >> 26) & 0x3FFFFFFUL; r->n[2] = t2; r->n[3] = t3; r->n[4] = t4;
+    r->n[5] = t5; r->n[6] = t6; r->n[7] = t7; r->n[8] = t8; r->n[9] = t9;
+/*    fog("         out: ", r);*/
+
+#ifdef VERIFY
+    r->magnitude = 1;
+    r->normalized = 1;
+#endif
+}
+
+void static inline secp256k1_fe_set_int(secp256k1_fe_t *r, int a) {
+    r->n[0] = a;
+    r->n[1] = r->n[2] = r->n[3] = r->n[4] = r->n[5] = r->n[6] = r->n[7] = r->n[8] = r->n[9] = 0;
+#ifdef VERIFY
+    r->magnitude = 1;
+    r->normalized = 1;
+#endif
+}
+
+// TODO: not constant time!
+int static inline secp256k1_fe_is_zero(const secp256k1_fe_t *a) {
+#ifdef VERIFY
+    assert(a->normalized);
+#endif
+    return (a->n[0] == 0 && a->n[1] == 0 && a->n[2] == 0 && a->n[3] == 0 && a->n[4] == 0 && a->n[5] == 0 && a->n[6] == 0 && a->n[7] == 0 && a->n[8] == 0 && a->n[9] == 0);
+}
+
+int static inline secp256k1_fe_is_odd(const secp256k1_fe_t *a) {
+#ifdef VERIFY
+    assert(a->normalized);
+#endif
+    return a->n[0] & 1;
+}
+
+// TODO: not constant time!
+int static inline secp256k1_fe_equal(const secp256k1_fe_t *a, const secp256k1_fe_t *b) {
+#ifdef VERIFY
+    assert(a->normalized);
+    assert(b->normalized);
+#endif
+    return (a->n[0] == b->n[0] && a->n[1] == b->n[1] && a->n[2] == b->n[2] && a->n[3] == b->n[3] && a->n[4] == b->n[4] &&
+            a->n[5] == b->n[5] && a->n[6] == b->n[6] && a->n[7] == b->n[7] && a->n[8] == b->n[8] && a->n[9] == b->n[9]);
+}
+
+void static secp256k1_fe_set_b32(secp256k1_fe_t *r, const unsigned char *a) {
+    r->n[0] = r->n[1] = r->n[2] = r->n[3] = r->n[4] = 0;
+    r->n[5] = r->n[6] = r->n[7] = r->n[8] = r->n[9] = 0;
+    for (int i=0; i<32; i++) {
+        for (int j=0; j<4; j++) {
+            int limb = (8*i+2*j)/26;
+            int shift = (8*i+2*j)%26;
+            r->n[limb] |= (uint32_t)((a[31-i] >> (2*j)) & 0x3) << shift;
+        }
+    }
+#ifdef VERIFY
+    r->magnitude = 1;
+    r->normalized = 1;
+#endif
+}
+
+/** Convert a field element to a 32-byte big endian value. Requires the input to be normalized */
+void static secp256k1_fe_get_b32(unsigned char *r, const secp256k1_fe_t *a) {
+#ifdef VERIFY
+    assert(a->normalized);
+#endif
+    for (int i=0; i<32; i++) {
+        int c = 0;
+        for (int j=0; j<4; j++) {
+            int limb = (8*i+2*j)/26;
+            int shift = (8*i+2*j)%26;
+            c |= ((a->n[limb] >> shift) & 0x3) << (2 * j);
+        }
+        r[31-i] = c;
+    }
+}
+
+void static inline secp256k1_fe_negate(secp256k1_fe_t *r, const secp256k1_fe_t *a, int m) {
+#ifdef VERIFY
+    assert(a->magnitude <= m);
+    r->magnitude = m + 1;
+    r->normalized = 0;
+#endif
+    r->n[0] = 0x3FFFC2FUL * (m + 1) - a->n[0];
+    r->n[1] = 0x3FFFFBFUL * (m + 1) - a->n[1];
+    r->n[2] = 0x3FFFFFFUL * (m + 1) - a->n[2];
+    r->n[3] = 0x3FFFFFFUL * (m + 1) - a->n[3];
+    r->n[4] = 0x3FFFFFFUL * (m + 1) - a->n[4];
+    r->n[5] = 0x3FFFFFFUL * (m + 1) - a->n[5];
+    r->n[6] = 0x3FFFFFFUL * (m + 1) - a->n[6];
+    r->n[7] = 0x3FFFFFFUL * (m + 1) - a->n[7];
+    r->n[8] = 0x3FFFFFFUL * (m + 1) - a->n[8];
+    r->n[9] = 0x03FFFFFUL * (m + 1) - a->n[9];
+}
+
+void static inline secp256k1_fe_mul_int(secp256k1_fe_t *r, int a) {
+#ifdef VERIFY
+    r->magnitude *= a;
+    r->normalized = 0;
+#endif
+    r->n[0] *= a;
+    r->n[1] *= a;
+    r->n[2] *= a;
+    r->n[3] *= a;
+    r->n[4] *= a;
+    r->n[5] *= a;
+    r->n[6] *= a;
+    r->n[7] *= a;
+    r->n[8] *= a;
+    r->n[9] *= a;
+}
+
+void static inline secp256k1_fe_add(secp256k1_fe_t *r, const secp256k1_fe_t *a) {
+#ifdef VERIFY
+    r->magnitude += a->magnitude;
+    r->normalized = 0;
+#endif
+    r->n[0] += a->n[0];
+    r->n[1] += a->n[1];
+    r->n[2] += a->n[2];
+    r->n[3] += a->n[3];
+    r->n[4] += a->n[4];
+    r->n[5] += a->n[5];
+    r->n[6] += a->n[6];
+    r->n[7] += a->n[7];
+    r->n[8] += a->n[8];
+    r->n[9] += a->n[9];
+}
+
+void static inline secp256k1_fe_mul_inner(const uint32_t *a, const uint32_t *b, uint32_t *r) {
+    uint64_t c = (uint64_t)a[0] * b[0];
+    uint32_t t0 = c & 0x3FFFFFFUL; c = c >> 26;
+    c = c + (uint64_t)a[0] * b[1] +
+            (uint64_t)a[1] * b[0];
+    uint32_t t1 = c & 0x3FFFFFFUL; c = c >> 26;
+    c = c + (uint64_t)a[0] * b[2] +
+            (uint64_t)a[1] * b[1] +
+            (uint64_t)a[2] * b[0];
+    uint32_t t2 = c & 0x3FFFFFFUL; c = c >> 26;
+    c = c + (uint64_t)a[0] * b[3] +
+            (uint64_t)a[1] * b[2] +
+            (uint64_t)a[2] * b[1] +
+            (uint64_t)a[3] * b[0];
+    uint32_t t3 = c & 0x3FFFFFFUL; c = c >> 26;
+    c = c + (uint64_t)a[0] * b[4] +
+            (uint64_t)a[1] * b[3] +
+            (uint64_t)a[2] * b[2] +
+            (uint64_t)a[3] * b[1] +
+            (uint64_t)a[4] * b[0];
+    uint32_t t4 = c & 0x3FFFFFFUL; c = c >> 26;
+    c = c + (uint64_t)a[0] * b[5] +
+            (uint64_t)a[1] * b[4] +
+            (uint64_t)a[2] * b[3] +
+            (uint64_t)a[3] * b[2] +
+            (uint64_t)a[4] * b[1] +
+            (uint64_t)a[5] * b[0];
+    uint32_t t5 = c & 0x3FFFFFFUL; c = c >> 26;
+    c = c + (uint64_t)a[0] * b[6] +
+            (uint64_t)a[1] * b[5] +
+            (uint64_t)a[2] * b[4] +
+            (uint64_t)a[3] * b[3] +
+            (uint64_t)a[4] * b[2] +
+            (uint64_t)a[5] * b[1] +
+            (uint64_t)a[6] * b[0];
+    uint32_t t6 = c & 0x3FFFFFFUL; c = c >> 26;
+    c = c + (uint64_t)a[0] * b[7] +
+            (uint64_t)a[1] * b[6] +
+            (uint64_t)a[2] * b[5] +
+            (uint64_t)a[3] * b[4] +
+            (uint64_t)a[4] * b[3] +
+            (uint64_t)a[5] * b[2] +
+            (uint64_t)a[6] * b[1] +
+            (uint64_t)a[7] * b[0];
+    uint32_t t7 = c & 0x3FFFFFFUL; c = c >> 26;
+    c = c + (uint64_t)a[0] * b[8] +
+            (uint64_t)a[1] * b[7] +
+            (uint64_t)a[2] * b[6] +
+            (uint64_t)a[3] * b[5] +
+            (uint64_t)a[4] * b[4] +
+            (uint64_t)a[5] * b[3] +
+            (uint64_t)a[6] * b[2] +
+            (uint64_t)a[7] * b[1] +
+            (uint64_t)a[8] * b[0];
+    uint32_t t8 = c & 0x3FFFFFFUL; c = c >> 26;
+    c = c + (uint64_t)a[0] * b[9] +
+            (uint64_t)a[1] * b[8] +
+            (uint64_t)a[2] * b[7] +
+            (uint64_t)a[3] * b[6] +
+            (uint64_t)a[4] * b[5] +
+            (uint64_t)a[5] * b[4] +
+            (uint64_t)a[6] * b[3] +
+            (uint64_t)a[7] * b[2] +
+            (uint64_t)a[8] * b[1] +
+            (uint64_t)a[9] * b[0];
+    uint32_t t9 = c & 0x3FFFFFFUL; c = c >> 26;
+    c = c + (uint64_t)a[1] * b[9] +
+            (uint64_t)a[2] * b[8] +
+            (uint64_t)a[3] * b[7] +
+            (uint64_t)a[4] * b[6] +
+            (uint64_t)a[5] * b[5] +
+            (uint64_t)a[6] * b[4] +
+            (uint64_t)a[7] * b[3] +
+            (uint64_t)a[8] * b[2] +
+            (uint64_t)a[9] * b[1];
+    uint32_t t10 = c & 0x3FFFFFFUL; c = c >> 26;
+    c = c + (uint64_t)a[2] * b[9] +
+            (uint64_t)a[3] * b[8] +
+            (uint64_t)a[4] * b[7] +
+            (uint64_t)a[5] * b[6] +
+            (uint64_t)a[6] * b[5] +
+            (uint64_t)a[7] * b[4] +
+            (uint64_t)a[8] * b[3] +
+            (uint64_t)a[9] * b[2];
+    uint32_t t11 = c & 0x3FFFFFFUL; c = c >> 26;
+    c = c + (uint64_t)a[3] * b[9] +
+            (uint64_t)a[4] * b[8] +
+            (uint64_t)a[5] * b[7] +
+            (uint64_t)a[6] * b[6] +
+            (uint64_t)a[7] * b[5] +
+            (uint64_t)a[8] * b[4] +
+            (uint64_t)a[9] * b[3];
+    uint32_t t12 = c & 0x3FFFFFFUL; c = c >> 26;
+    c = c + (uint64_t)a[4] * b[9] +
+            (uint64_t)a[5] * b[8] +
+            (uint64_t)a[6] * b[7] +
+            (uint64_t)a[7] * b[6] +
+            (uint64_t)a[8] * b[5] +
+            (uint64_t)a[9] * b[4];
+    uint32_t t13 = c & 0x3FFFFFFUL; c = c >> 26;
+    c = c + (uint64_t)a[5] * b[9] +
+            (uint64_t)a[6] * b[8] +
+            (uint64_t)a[7] * b[7] +
+            (uint64_t)a[8] * b[6] +
+            (uint64_t)a[9] * b[5];
+    uint32_t t14 = c & 0x3FFFFFFUL; c = c >> 26;
+    c = c + (uint64_t)a[6] * b[9] +
+            (uint64_t)a[7] * b[8] +
+            (uint64_t)a[8] * b[7] +
+            (uint64_t)a[9] * b[6];
+    uint32_t t15 = c & 0x3FFFFFFUL; c = c >> 26;
+    c = c + (uint64_t)a[7] * b[9] +
+            (uint64_t)a[8] * b[8] +
+            (uint64_t)a[9] * b[7];
+    uint32_t t16 = c & 0x3FFFFFFUL; c = c >> 26;
+    c = c + (uint64_t)a[8] * b[9] +
+            (uint64_t)a[9] * b[8];
+    uint32_t t17 = c & 0x3FFFFFFUL; c = c >> 26;
+    c = c + (uint64_t)a[9] * b[9];
+    uint32_t t18 = c & 0x3FFFFFFUL; c = c >> 26;
+    uint32_t t19 = c;
+
+    c = t0 + (uint64_t)t10 * 0x3D10UL;
+    t0 = c & 0x3FFFFFFUL; c = c >> 26;
+    c = c + t1 + (uint64_t)t10*0x400UL + (uint64_t)t11 * 0x3D10UL;
+    t1 = c & 0x3FFFFFFUL; c = c >> 26;
+    c = c + t2 + (uint64_t)t11*0x400UL + (uint64_t)t12 * 0x3D10UL;
+    t2 = c & 0x3FFFFFFUL; c = c >> 26;
+    c = c + t3 + (uint64_t)t12*0x400UL + (uint64_t)t13 * 0x3D10UL;
+    r[3] = c & 0x3FFFFFFUL; c = c >> 26;
+    c = c + t4 + (uint64_t)t13*0x400UL + (uint64_t)t14 * 0x3D10UL;
+    r[4] = c & 0x3FFFFFFUL; c = c >> 26;
+    c = c + t5 + (uint64_t)t14*0x400UL + (uint64_t)t15 * 0x3D10UL;
+    r[5] = c & 0x3FFFFFFUL; c = c >> 26;
+    c = c + t6 + (uint64_t)t15*0x400UL + (uint64_t)t16 * 0x3D10UL;
+    r[6] = c & 0x3FFFFFFUL; c = c >> 26;
+    c = c + t7 + (uint64_t)t16*0x400UL + (uint64_t)t17 * 0x3D10UL;
+    r[7] = c & 0x3FFFFFFUL; c = c >> 26;
+    c = c + t8 + (uint64_t)t17*0x400UL + (uint64_t)t18 * 0x3D10UL;
+    r[8] = c & 0x3FFFFFFUL; c = c >> 26;
+    c = c + t9 + (uint64_t)t18*0x400UL + (uint64_t)t19 * 0x1000003D10ULL;
+    r[9] = c & 0x03FFFFFUL; c = c >> 22;
+    uint64_t d = t0 + c * 0x3D1UL;
+    r[0] = d & 0x3FFFFFFUL; d = d >> 26;
+    d = d + t1 + c*0x40;
+    r[1] = d & 0x3FFFFFFUL; d = d >> 26;
+    r[2] = t2 + d;
+}
+
+void static inline secp256k1_fe_sqr_inner(const uint32_t *a, uint32_t *r) {
+    uint64_t c = (uint64_t)a[0] * a[0];
+    uint32_t t0 = c & 0x3FFFFFFUL; c = c >> 26;
+    c = c + (uint64_t)(a[0]*2) * a[1];
+    uint32_t t1 = c & 0x3FFFFFFUL; c = c >> 26;
+    c = c + (uint64_t)(a[0]*2) * a[2] +
+            (uint64_t)a[1] * a[1];
+    uint32_t t2 = c & 0x3FFFFFFUL; c = c >> 26;
+    c = c + (uint64_t)(a[0]*2) * a[3] +
+            (uint64_t)(a[1]*2) * a[2];
+    uint32_t t3 = c & 0x3FFFFFFUL; c = c >> 26;
+    c = c + (uint64_t)(a[0]*2) * a[4] +
+            (uint64_t)(a[1]*2) * a[3] +
+            (uint64_t)a[2] * a[2];
+    uint32_t t4 = c & 0x3FFFFFFUL; c = c >> 26;
+    c = c + (uint64_t)(a[0]*2) * a[5] +
+            (uint64_t)(a[1]*2) * a[4] +
+            (uint64_t)(a[2]*2) * a[3];
+    uint32_t t5 = c & 0x3FFFFFFUL; c = c >> 26;
+    c = c + (uint64_t)(a[0]*2) * a[6] +
+            (uint64_t)(a[1]*2) * a[5] +
+            (uint64_t)(a[2]*2) * a[4] +
+            (uint64_t)a[3] * a[3];
+    uint32_t t6 = c & 0x3FFFFFFUL; c = c >> 26;
+    c = c + (uint64_t)(a[0]*2) * a[7] +
+            (uint64_t)(a[1]*2) * a[6] +
+            (uint64_t)(a[2]*2) * a[5] +
+            (uint64_t)(a[3]*2) * a[4];
+    uint32_t t7 = c & 0x3FFFFFFUL; c = c >> 26;
+    c = c + (uint64_t)(a[0]*2) * a[8] +
+            (uint64_t)(a[1]*2) * a[7] +
+            (uint64_t)(a[2]*2) * a[6] +
+            (uint64_t)(a[3]*2) * a[5] +
+            (uint64_t)a[4] * a[4];
+    uint32_t t8 = c & 0x3FFFFFFUL; c = c >> 26;
+    c = c + (uint64_t)(a[0]*2) * a[9] +
+            (uint64_t)(a[1]*2) * a[8] +
+            (uint64_t)(a[2]*2) * a[7] +
+            (uint64_t)(a[3]*2) * a[6] +
+            (uint64_t)(a[4]*2) * a[5];
+    uint32_t t9 = c & 0x3FFFFFFUL; c = c >> 26;
+    c = c + (uint64_t)(a[1]*2) * a[9] +
+            (uint64_t)(a[2]*2) * a[8] +
+            (uint64_t)(a[3]*2) * a[7] +
+            (uint64_t)(a[4]*2) * a[6] +
+            (uint64_t)a[5] * a[5];
+    uint32_t t10 = c & 0x3FFFFFFUL; c = c >> 26;
+    c = c + (uint64_t)(a[2]*2) * a[9] +
+            (uint64_t)(a[3]*2) * a[8] +
+            (uint64_t)(a[4]*2) * a[7] +
+            (uint64_t)(a[5]*2) * a[6];
+    uint32_t t11 = c & 0x3FFFFFFUL; c = c >> 26;
+    c = c + (uint64_t)(a[3]*2) * a[9] +
+            (uint64_t)(a[4]*2) * a[8] +
+            (uint64_t)(a[5]*2) * a[7] +
+            (uint64_t)a[6] * a[6];
+    uint32_t t12 = c & 0x3FFFFFFUL; c = c >> 26;
+    c = c + (uint64_t)(a[4]*2) * a[9] +
+            (uint64_t)(a[5]*2) * a[8] +
+            (uint64_t)(a[6]*2) * a[7];
+    uint32_t t13 = c & 0x3FFFFFFUL; c = c >> 26;
+    c = c + (uint64_t)(a[5]*2) * a[9] +
+            (uint64_t)(a[6]*2) * a[8] +
+            (uint64_t)a[7] * a[7];
+    uint32_t t14 = c & 0x3FFFFFFUL; c = c >> 26;
+    c = c + (uint64_t)(a[6]*2) * a[9] +
+            (uint64_t)(a[7]*2) * a[8];
+    uint32_t t15 = c & 0x3FFFFFFUL; c = c >> 26;
+    c = c + (uint64_t)(a[7]*2) * a[9] +
+            (uint64_t)a[8] * a[8];
+    uint32_t t16 = c & 0x3FFFFFFUL; c = c >> 26;
+    c = c + (uint64_t)(a[8]*2) * a[9];
+    uint32_t t17 = c & 0x3FFFFFFUL; c = c >> 26;
+    c = c + (uint64_t)a[9] * a[9];
+    uint32_t t18 = c & 0x3FFFFFFUL; c = c >> 26;
+    uint32_t t19 = c;
+
+    c = t0 + (uint64_t)t10 * 0x3D10UL;
+    t0 = c & 0x3FFFFFFUL; c = c >> 26;
+    c = c + t1 + (uint64_t)t10*0x400UL + (uint64_t)t11 * 0x3D10UL;
+    t1 = c & 0x3FFFFFFUL; c = c >> 26;
+    c = c + t2 + (uint64_t)t11*0x400UL + (uint64_t)t12 * 0x3D10UL;
+    t2 = c & 0x3FFFFFFUL; c = c >> 26;
+    c = c + t3 + (uint64_t)t12*0x400UL + (uint64_t)t13 * 0x3D10UL;
+    r[3] = c & 0x3FFFFFFUL; c = c >> 26;
+    c = c + t4 + (uint64_t)t13*0x400UL + (uint64_t)t14 * 0x3D10UL;
+    r[4] = c & 0x3FFFFFFUL; c = c >> 26;
+    c = c + t5 + (uint64_t)t14*0x400UL + (uint64_t)t15 * 0x3D10UL;
+    r[5] = c & 0x3FFFFFFUL; c = c >> 26;
+    c = c + t6 + (uint64_t)t15*0x400UL + (uint64_t)t16 * 0x3D10UL;
+    r[6] = c & 0x3FFFFFFUL; c = c >> 26;
+    c = c + t7 + (uint64_t)t16*0x400UL + (uint64_t)t17 * 0x3D10UL;
+    r[7] = c & 0x3FFFFFFUL; c = c >> 26;
+    c = c + t8 + (uint64_t)t17*0x400UL + (uint64_t)t18 * 0x3D10UL;
+    r[8] = c & 0x3FFFFFFUL; c = c >> 26;
+    c = c + t9 + (uint64_t)t18*0x400UL + (uint64_t)t19 * 0x1000003D10ULL;
+    r[9] = c & 0x03FFFFFUL; c = c >> 22;
+    uint64_t d = t0 + c * 0x3D1UL;
+    r[0] = d & 0x3FFFFFFUL; d = d >> 26;
+    d = d + t1 + c*0x40;
+    r[1] = d & 0x3FFFFFFUL; d = d >> 26;
+    r[2] = t2 + d;
+}
+
+
+void static secp256k1_fe_mul(secp256k1_fe_t *r, const secp256k1_fe_t *a, const secp256k1_fe_t *b) {
+#ifdef VERIFY
+    assert(a->magnitude <= 8);
+    assert(b->magnitude <= 8);
+    r->magnitude = 1;
+    r->normalized = 0;
+#endif
+    secp256k1_fe_mul_inner(a->n, b->n, r->n);
+}
+
+void static secp256k1_fe_sqr(secp256k1_fe_t *r, const secp256k1_fe_t *a) {
+#ifdef VERIFY
+    assert(a->magnitude <= 8);
+    r->magnitude = 1;
+    r->normalized = 0;
+#endif
+    secp256k1_fe_sqr_inner(a->n, r->n);
+}
+
+#endif
diff --git a/crypto/secp256k1/secp256k1/src/impl/field_5x52.h b/crypto/secp256k1/secp256k1/src/impl/field_5x52.h
new file mode 100644
index 000000000..5347189f1
--- /dev/null
+++ b/crypto/secp256k1/secp256k1/src/impl/field_5x52.h
@@ -0,0 +1,196 @@
+// Copyright (c) 2013 Pieter Wuille
+// Distributed under the MIT/X11 software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef _SECP256K1_FIELD_REPR_IMPL_H_
+#define _SECP256K1_FIELD_REPR_IMPL_H_
+
+#include <assert.h>
+#include <string.h>
+#include "../num.h"
+#include "../field.h"
+
+#if defined(USE_FIELD_5X52_ASM)
+#include "field_5x52_asm.h"
+#elif defined(USE_FIELD_5X52_INT128)
+#include "field_5x52_int128.h"
+#else
+#error "Please select field_5x52 implementation"
+#endif
+
+/** Implements arithmetic modulo FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE FFFFFC2F,
+ *  represented as 5 uint64_t's in base 2^52. The values are allowed to contain >52 each. In particular,
+ *  each FieldElem has a 'magnitude' associated with it. Internally, a magnitude M means each element
+ *  is at most M*(2^53-1), except the most significant one, which is limited to M*(2^49-1). All operations
+ *  accept any input with magnitude at most M, and have different rules for propagating magnitude to their
+ *  output.
+ */
+
+void static secp256k1_fe_inner_start(void) {}
+void static secp256k1_fe_inner_stop(void) {}
+
+void static secp256k1_fe_normalize(secp256k1_fe_t *r) {
+    uint64_t c;
+    c = r->n[0];
+    uint64_t t0 = c & 0xFFFFFFFFFFFFFULL;
+    c = (c >> 52) + r->n[1];
+    uint64_t t1 = c & 0xFFFFFFFFFFFFFULL;
+    c = (c >> 52) + r->n[2];
+    uint64_t t2 = c & 0xFFFFFFFFFFFFFULL;
+    c = (c >> 52) + r->n[3];
+    uint64_t t3 = c & 0xFFFFFFFFFFFFFULL;
+    c = (c >> 52) + r->n[4];
+    uint64_t t4 = c & 0x0FFFFFFFFFFFFULL;
+    c >>= 48;
+
+    // The following code will not modify the t's if c is initially 0.
+    c = c * 0x1000003D1ULL + t0;
+    t0 = c & 0xFFFFFFFFFFFFFULL;
+    c = (c >> 52) + t1;
+    t1 = c & 0xFFFFFFFFFFFFFULL;
+    c = (c >> 52) + t2;
+    t2 = c & 0xFFFFFFFFFFFFFULL;
+    c = (c >> 52) + t3;
+    t3 = c & 0xFFFFFFFFFFFFFULL;
+    c = (c >> 52) + t4;
+    t4 = c & 0x0FFFFFFFFFFFFULL;
+    assert((c >> 48) == 0);
+
+    // Subtract p if result >= p
+    uint64_t mask = -(int64_t)((t4 < 0xFFFFFFFFFFFFULL) | (t3 < 0xFFFFFFFFFFFFFULL) | (t2 < 0xFFFFFFFFFFFFFULL) | (t1 < 0xFFFFFFFFFFFFFULL) | (t0 < 0xFFFFEFFFFFC2FULL));
+    t4 &= mask;
+    t3 &= mask;
+    t2 &= mask;
+    t1 &= mask;
+    t0 -= (~mask & 0xFFFFEFFFFFC2FULL);
+
+    // push internal variables back
+    r->n[0] = t0; r->n[1] = t1; r->n[2] = t2; r->n[3] = t3; r->n[4] = t4;
+
+#ifdef VERIFY
+    r->magnitude = 1;
+    r->normalized = 1;
+#endif
+}
+
+void static inline secp256k1_fe_set_int(secp256k1_fe_t *r, int a) {
+    r->n[0] = a;
+    r->n[1] = r->n[2] = r->n[3] = r->n[4] = 0;
+#ifdef VERIFY
+    r->magnitude = 1;
+    r->normalized = 1;
+#endif
+}
+
+// TODO: not constant time!
+int static inline secp256k1_fe_is_zero(const secp256k1_fe_t *a) {
+#ifdef VERIFY
+    assert(a->normalized);
+#endif
+    return (a->n[0] == 0 && a->n[1] == 0 && a->n[2] == 0 && a->n[3] == 0 && a->n[4] == 0);
+}
+
+int static inline secp256k1_fe_is_odd(const secp256k1_fe_t *a) {
+#ifdef VERIFY
+    assert(a->normalized);
+#endif
+    return a->n[0] & 1;
+}
+
+// TODO: not constant time!
+int static inline secp256k1_fe_equal(const secp256k1_fe_t *a, const secp256k1_fe_t *b) {
+#ifdef VERIFY
+    assert(a->normalized);
+    assert(b->normalized);
+#endif
+    return (a->n[0] == b->n[0] && a->n[1] == b->n[1] && a->n[2] == b->n[2] && a->n[3] == b->n[3] && a->n[4] == b->n[4]);
+}
+
+void static secp256k1_fe_set_b32(secp256k1_fe_t *r, const unsigned char *a) {
+    r->n[0] = r->n[1] = r->n[2] = r->n[3] = r->n[4] = 0;
+    for (int i=0; i<32; i++) {
+        for (int j=0; j<2; j++) {
+            int limb = (8*i+4*j)/52;
+            int shift = (8*i+4*j)%52;
+            r->n[limb] |= (uint64_t)((a[31-i] >> (4*j)) & 0xF) << shift;
+        }
+    }
+#ifdef VERIFY
+    r->magnitude = 1;
+    r->normalized = 1;
+#endif
+}
+
+/** Convert a field element to a 32-byte big endian value. Requires the input to be normalized */
+void static secp256k1_fe_get_b32(unsigned char *r, const secp256k1_fe_t *a) {
+#ifdef VERIFY
+    assert(a->normalized);
+#endif
+    for (int i=0; i<32; i++) {
+        int c = 0;
+        for (int j=0; j<2; j++) {
+            int limb = (8*i+4*j)/52;
+            int shift = (8*i+4*j)%52;
+            c |= ((a->n[limb] >> shift) & 0xF) << (4 * j);
+        }
+        r[31-i] = c;
+    }
+}
+
+void static inline secp256k1_fe_negate(secp256k1_fe_t *r, const secp256k1_fe_t *a, int m) {
+#ifdef VERIFY
+    assert(a->magnitude <= m);
+    r->magnitude = m + 1;
+    r->normalized = 0;
+#endif
+    r->n[0] = 0xFFFFEFFFFFC2FULL * (m + 1) - a->n[0];
+    r->n[1] = 0xFFFFFFFFFFFFFULL * (m + 1) - a->n[1];
+    r->n[2] = 0xFFFFFFFFFFFFFULL * (m + 1) - a->n[2];
+    r->n[3] = 0xFFFFFFFFFFFFFULL * (m + 1) - a->n[3];
+    r->n[4] = 0x0FFFFFFFFFFFFULL * (m + 1) - a->n[4];
+}
+
+void static inline secp256k1_fe_mul_int(secp256k1_fe_t *r, int a) {
+#ifdef VERIFY
+    r->magnitude *= a;
+    r->normalized = 0;
+#endif
+    r->n[0] *= a;
+    r->n[1] *= a;
+    r->n[2] *= a;
+    r->n[3] *= a;
+    r->n[4] *= a;
+}
+
+void static inline secp256k1_fe_add(secp256k1_fe_t *r, const secp256k1_fe_t *a) {
+#ifdef VERIFY
+    r->magnitude += a->magnitude;
+    r->normalized = 0;
+#endif
+    r->n[0] += a->n[0];
+    r->n[1] += a->n[1];
+    r->n[2] += a->n[2];
+    r->n[3] += a->n[3];
+    r->n[4] += a->n[4];
+}
+
+void static secp256k1_fe_mul(secp256k1_fe_t *r, const secp256k1_fe_t *a, const secp256k1_fe_t *b) {
+#ifdef VERIFY
+    assert(a->magnitude <= 8);
+    assert(b->magnitude <= 8);
+    r->magnitude = 1;
+    r->normalized = 0;
+#endif
+    secp256k1_fe_mul_inner(a->n, b->n, r->n);
+}
+
+void static secp256k1_fe_sqr(secp256k1_fe_t *r, const secp256k1_fe_t *a) {
+#ifdef VERIFY
+    assert(a->magnitude <= 8);
+    r->magnitude = 1;
+    r->normalized = 0;
+#endif
+    secp256k1_fe_sqr_inner(a->n, r->n);
+}
+
+#endif
diff --git a/crypto/secp256k1/secp256k1/src/impl/field_5x52_asm.h b/crypto/secp256k1/secp256k1/src/impl/field_5x52_asm.h
new file mode 100644
index 000000000..93c6ab6b5
--- /dev/null
+++ b/crypto/secp256k1/secp256k1/src/impl/field_5x52_asm.h
@@ -0,0 +1,11 @@
+// Copyright (c) 2013 Pieter Wuille
+// Distributed under the MIT/X11 software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef _SECP256K1_FIELD_INNER5X52_IMPL_H_
+#define _SECP256K1_FIELD_INNER5X52_IMPL_H_
+
+void __attribute__ ((sysv_abi)) secp256k1_fe_mul_inner(const uint64_t *a, const uint64_t *b, uint64_t *r);
+void __attribute__ ((sysv_abi)) secp256k1_fe_sqr_inner(const uint64_t *a, uint64_t *r);
+
+#endif
diff --git a/crypto/secp256k1/secp256k1/src/impl/field_5x52_int128.h b/crypto/secp256k1/secp256k1/src/impl/field_5x52_int128.h
new file mode 100644
index 000000000..23cb13462
--- /dev/null
+++ b/crypto/secp256k1/secp256k1/src/impl/field_5x52_int128.h
@@ -0,0 +1,105 @@
+// Copyright (c) 2013 Pieter Wuille
+// Distributed under the MIT/X11 software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef _SECP256K1_FIELD_INNER5X52_IMPL_H_
+#define _SECP256K1_FIELD_INNER5X52_IMPL_H_
+
+#include <stdint.h>
+
+void static inline secp256k1_fe_mul_inner(const uint64_t *a, const uint64_t *b, uint64_t *r) {
+    __int128 c = (__int128)a[0] * b[0];
+    uint64_t t0 = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 0FFFFFFFFFFFFFE0
+    c = c + (__int128)a[0] * b[1] +
+            (__int128)a[1] * b[0];
+    uint64_t t1 = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 20000000000000BF
+    c = c + (__int128)a[0] * b[2] +
+            (__int128)a[1] * b[1] +
+            (__int128)a[2] * b[0];
+    uint64_t t2 = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 30000000000001A0
+    c = c + (__int128)a[0] * b[3] +
+            (__int128)a[1] * b[2] +
+            (__int128)a[2] * b[1] +
+            (__int128)a[3] * b[0];
+    uint64_t t3 = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 4000000000000280
+    c = c + (__int128)a[0] * b[4] +
+            (__int128)a[1] * b[3] +
+            (__int128)a[2] * b[2] +
+            (__int128)a[3] * b[1] +
+            (__int128)a[4] * b[0];
+    uint64_t t4 = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 320000000000037E
+    c = c + (__int128)a[1] * b[4] +
+            (__int128)a[2] * b[3] +
+            (__int128)a[3] * b[2] +
+            (__int128)a[4] * b[1];
+    uint64_t t5 = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 22000000000002BE
+    c = c + (__int128)a[2] * b[4] +
+            (__int128)a[3] * b[3] +
+            (__int128)a[4] * b[2];
+    uint64_t t6 = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 12000000000001DE
+    c = c + (__int128)a[3] * b[4] +
+            (__int128)a[4] * b[3];
+    uint64_t t7 = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 02000000000000FE
+    c = c + (__int128)a[4] * b[4];
+    uint64_t t8 = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 001000000000001E
+    uint64_t t9 = c;
+
+    c = t0 + (__int128)t5 * 0x1000003D10ULL;
+    t0 = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 0000001000003D10
+    c = c + t1 + (__int128)t6 * 0x1000003D10ULL;
+    t1 = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 0000001000003D10
+    c = c + t2 + (__int128)t7 * 0x1000003D10ULL;
+    r[2] = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 0000001000003D10
+    c = c + t3 + (__int128)t8 * 0x1000003D10ULL;
+    r[3] = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 0000001000003D10
+    c = c + t4 + (__int128)t9 * 0x1000003D10ULL;
+    r[4] = c & 0x0FFFFFFFFFFFFULL; c = c >> 48; // c max 000001000003D110
+    c = t0 + (__int128)c * 0x1000003D1ULL;
+    r[0] = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 1000008
+    r[1] = t1 + c;
+
+}
+
+void static inline secp256k1_fe_sqr_inner(const uint64_t *a, uint64_t *r) {
+    __int128 c = (__int128)a[0] * a[0];
+    uint64_t t0 = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 0FFFFFFFFFFFFFE0
+    c = c + (__int128)(a[0]*2) * a[1];
+    uint64_t t1 = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 20000000000000BF
+    c = c + (__int128)(a[0]*2) * a[2] +
+            (__int128)a[1] * a[1];
+    uint64_t t2 = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 30000000000001A0
+    c = c + (__int128)(a[0]*2) * a[3] +
+            (__int128)(a[1]*2) * a[2];
+    uint64_t t3 = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 4000000000000280
+    c = c + (__int128)(a[0]*2) * a[4] +
+            (__int128)(a[1]*2) * a[3] +
+            (__int128)a[2] * a[2];
+    uint64_t t4 = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 320000000000037E
+    c = c + (__int128)(a[1]*2) * a[4] +
+            (__int128)(a[2]*2) * a[3];
+    uint64_t t5 = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 22000000000002BE
+    c = c + (__int128)(a[2]*2) * a[4] +
+            (__int128)a[3] * a[3];
+    uint64_t t6 = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 12000000000001DE
+    c = c + (__int128)(a[3]*2) * a[4];
+    uint64_t t7 = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 02000000000000FE
+    c = c + (__int128)a[4] * a[4];
+    uint64_t t8 = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 001000000000001E
+    uint64_t t9 = c;
+    c = t0 + (__int128)t5 * 0x1000003D10ULL;
+    t0 = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 0000001000003D10
+    c = c + t1 + (__int128)t6 * 0x1000003D10ULL;
+    t1 = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 0000001000003D10
+    c = c + t2 + (__int128)t7 * 0x1000003D10ULL;
+    r[2] = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 0000001000003D10
+    c = c + t3 + (__int128)t8 * 0x1000003D10ULL;
+    r[3] = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 0000001000003D10
+    c = c + t4 + (__int128)t9 * 0x1000003D10ULL;
+    r[4] = c & 0x0FFFFFFFFFFFFULL; c = c >> 48; // c max 000001000003D110
+    c = t0 + (__int128)c * 0x1000003D1ULL;
+    r[0] = c & 0xFFFFFFFFFFFFFULL; c = c >> 52; // c max 1000008
+    r[1] = t1 + c;
+
+}
+
+#endif
diff --git a/crypto/secp256k1/secp256k1/src/impl/field_5x64.h b/crypto/secp256k1/secp256k1/src/impl/field_5x64.h
new file mode 100644
index 000000000..1e645cddb
--- /dev/null
+++ b/crypto/secp256k1/secp256k1/src/impl/field_5x64.h
@@ -0,0 +1,371 @@
+// Copyright (c) 2013 Pieter Wuille
+// Distributed under the MIT/X11 software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef _SECP256K1_FIELD_REPR_IMPL_H_
+#define _SECP256K1_FIELD_REPR_IMPL_H_
+
+#include <assert.h>
+#include <string.h>
+#include "../num.h"
+#include "../field.h"
+
+#include <stdio.h>
+#include "field_5x64_asm.h"
+
+/** Implements arithmetic modulo FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE FFFFFC2F,
+ *  represented as 4 uint64_t's in base 2^64, and one overflow uint64_t.
+ */
+
+#define FULL_LIMB (0xFFFFFFFFFFFFFFFFULL)
+#define LAST_LIMB (0xFFFFFFFEFFFFFC2FULL)
+#define COMP_LIMB (0x00000001000003D1ULL)
+
+void static secp256k1_fe_inner_start(void) {}
+void static secp256k1_fe_inner_stop(void) {}
+
+void static secp256k1_fe_reduce(secp256k1_fe_t *r) {
+    unsigned __int128 c = (unsigned __int128)r->n[4] * COMP_LIMB + r->n[0];
+    uint64_t n0 = c;
+    c = (c >> 64) + r->n[1];
+    uint64_t n1 = c;
+    c = (c >> 64) + r->n[2];
+    r->n[2] = c;
+    c = (c >> 64) + r->n[3];
+    r->n[3] = c;
+    c = (c >> 64) * COMP_LIMB + n0;
+    r->n[0] = c;
+    r->n[1] = n1 + (c >> 64);
+    assert(r->n[1] >= n1);
+    r->n[4] = 0;
+#ifdef VERIFY
+    r->reduced = 1;
+#endif
+}
+
+void static secp256k1_fe_normalize(secp256k1_fe_t *r) {
+    secp256k1_fe_reduce(r);
+
+    // Subtract p if result >= p
+    uint64_t mask = -(int64_t)((r->n[0] < LAST_LIMB) | (r->n[1] != ~0ULL) | (r->n[2] != ~0ULL) | (r->n[3] != ~0ULL));
+    r->n[0] -= (~mask & LAST_LIMB);
+    r->n[1] &= mask;
+    r->n[2] &= mask;
+    r->n[3] &= mask;
+    assert(r->n[4] == 0);
+
+#ifdef VERIFY
+    r->normalized = 1;
+#endif
+}
+
+void static inline secp256k1_fe_set_int(secp256k1_fe_t *r, int a) {
+    r->n[0] = a;
+    r->n[1] = r->n[2] = r->n[3] = r->n[4] = 0;
+
+#ifdef VERIFY
+    r->reduced = 1;
+    r->normalized = 1;
+#endif
+}
+
+// TODO: not constant time!
+int static inline secp256k1_fe_is_zero(const secp256k1_fe_t *a) {
+#ifdef VERIFY
+    assert(a->normalized);
+#endif
+    return (a->n[0] == 0 && a->n[1] == 0 && a->n[2] == 0 && a->n[3] == 0);
+}
+
+int static inline secp256k1_fe_is_odd(const secp256k1_fe_t *a) {
+#ifdef VERIFY
+    assert(a->normalized);
+#endif
+    return a->n[0] & 1;
+}
+
+// TODO: not constant time!
+int static inline secp256k1_fe_equal(const secp256k1_fe_t *a, const secp256k1_fe_t *b) {
+#ifdef VERIFY
+    assert(a->normalized);
+    assert(b->normalized);
+#endif
+    return (a->n[0] == b->n[0] && a->n[1] == b->n[1] && a->n[2] == b->n[2] && a->n[3] == b->n[3]);
+}
+
+void static secp256k1_fe_set_b32(secp256k1_fe_t *r, const unsigned char *a) {
+    r->n[0] = r->n[1] = r->n[2] = r->n[3] = r->n[4] = 0;
+    for (int i=0; i<32; i++) {
+        r->n[i/8] |= (uint64_t)a[31-i] << (i&7)*8;
+    }
+#ifdef VERIFY
+    r->reduced = 1;
+    r->normalized = 0;
+#endif
+}
+
+/** Convert a field element to a 32-byte big endian value. Requires the input to be normalized */
+void static secp256k1_fe_get_b32(unsigned char *r, const secp256k1_fe_t *a) {
+#ifdef VERIFY
+    assert(a->normalized);
+#endif
+    for (int i=0; i<32; i++) {
+        r[31-i] = a->n[i/8] >> ((i&7)*8);
+    }
+}
+
+void static inline secp256k1_fe_negate(secp256k1_fe_t *r, const secp256k1_fe_t *ac, int m) {
+    secp256k1_fe_t a = *ac;
+    secp256k1_fe_reduce(&a);
+    unsigned __int128 c = (unsigned __int128)(~a.n[0]) + LAST_LIMB + 1;
+    r->n[0] = c;
+    c = (c >> 64) + (~a.n[1]) + FULL_LIMB;
+    r->n[1] = c;
+    c = (c >> 64) + (~a.n[2]) + FULL_LIMB;
+    r->n[2] = c;
+    c = (c >> 64) + (~a.n[3]) + FULL_LIMB;
+    r->n[3] = c;
+    r->n[4] = 0;
+#ifdef VERIFY
+    r->reduced = 1;
+    r->normalized = 0;
+#endif
+}
+
+void static inline secp256k1_fe_mul_int(secp256k1_fe_t *r, int a) {
+#ifdef VERIFY
+    r->reduced = 0;
+    r->normalized = 0;
+#endif
+    unsigned __int128 c = (unsigned __int128)r->n[0] * a;
+    r->n[0] = c;
+    c = (c >> 64) + (unsigned __int128)r->n[1] * a;
+    r->n[1] = c;
+    c = (c >> 64) + (unsigned __int128)r->n[2] * a;
+    r->n[2] = c;
+    c = (c >> 64) + (unsigned __int128)r->n[3] * a;
+    r->n[3] = c;
+    c = (c >> 64) + (unsigned __int128)r->n[4] * a;
+    r->n[4] = c;
+}
+
+void static inline secp256k1_fe_add(secp256k1_fe_t *r, const secp256k1_fe_t *a) {
+#ifdef VERIFY
+    r->reduced = 0;
+    r->normalized = 0;
+#endif
+    unsigned __int128 c = (unsigned __int128)r->n[0] + a->n[0];
+    r->n[0] = c;
+    c = (unsigned __int128)r->n[1] + a->n[1] + (c >> 64);
+    r->n[1] = c;
+    c = (unsigned __int128)r->n[2] + a->n[2] + (c >> 64);
+    r->n[2] = c;
+    c = (unsigned __int128)r->n[3] + a->n[3] + (c >> 64);
+    r->n[3] = c;
+    c = (unsigned __int128)r->n[4] + a->n[4] + (c >> 64);
+    r->n[4] = c;
+    assert((c >> 64) == 0);
+}
+
+#if 0
+#define muladd_c3(a,b,c0,c1,c2) { \
+    unsigned __int128 q1 = ((unsigned __int128)(a)) * (b) + (c0); \
+    (c0) = q1; \
+    unsigned __int128 q2 = (q1 >> 64) + (c1) + (((unsigned __int128)(c2)) << 64); \
+    (c1) = q2; \
+    (c2) = q2 >> 64; \
+}
+
+#define sqradd_c3(a,c0,c1,c2) muladd_c3(a,a,c0,c1,c2)
+
+/*#define muladd_c3(a,b,c0,c1,c2) { \
+    unsigned __int128 q = (unsigned __int128)(a) * (b) + (c0); \
+    (c0) = q; \
+    (c1) += (q >> 64); \
+    (c2) += ((c1) < (q >> 64))?1:0; \
+}*/
+
+#define muladd2_c3(a,b,c0,c1,c2) { \
+    unsigned __int128 q = (unsigned __int128)(a) * (b); \
+    uint64_t t1 = (q >> 64); \
+    uint64_t t0 = q; \
+    uint64_t t2 = t1+t1; (c2) += (t2<t1)?1:0; \
+    t1 = t0+t0; t2 += (t1<t0)?1:0; \
+    (c0) += t1; t2 += ((c0)<t1)?1:0; \
+    (c1) += t2; (c2) += ((c1)<t2)?1:0; \
+}
+
+/*#define muladd2_c3(a,b,c0,c1,c2) { \
+    muladd_c3(a,b,c0,c1,c2); \
+    muladd_c3(a,b,c0,c1,c2); \
+}*/
+#else
+
+#define muladd_c3(a,b,c0,c1,c2) {       \
+        register uint64_t t1, t2;       \
+        asm ("mulq %3"                  \
+                : "=a"(t1),"=d"(t2)     \
+                : "a"(a),"m"(b)         \
+                : "cc");                \
+        asm ("addq %2,%0; adcq %3,%1"   \
+                : "+r"(c0),"+d"(t2)     \
+                : "a"(t1),"g"(0)        \
+                : "cc");                \
+        asm ("addq %2,%0; adcq %3,%1"   \
+                : "+r"(c1),"+r"(c2)     \
+                : "d"(t2),"g"(0)        \
+                : "cc");                \
+        }
+
+#define sqradd_c3(a,c0,c1,c2) {         \
+        register uint64_t t1, t2;       \
+        asm ("mulq %2"                  \
+                : "=a"(t1),"=d"(t2)     \
+                : "a"(a)                \
+                : "cc");                \
+        asm ("addq %2,%0; adcq %3,%1"   \
+                : "+r"(c0),"+d"(t2)     \
+                : "a"(t1),"g"(0)        \
+                : "cc");                \
+        asm ("addq %2,%0; adcq %3,%1"   \
+                : "+r"(c1),"+r"(c2)     \
+                : "d"(t2),"g"(0)        \
+                : "cc");                \
+        }
+
+#define muladd2_c3(a,b,c0,c1,c2) {      \
+        register uint64_t t1, t2;       \
+        asm ("mulq %3"                  \
+                : "=a"(t1),"=d"(t2)     \
+                : "a"(a),"m"(b)         \
+                : "cc");                \
+        asm ("addq %0,%0; adcq %2,%1"   \
+                : "+d"(t2),"+r"(c2)     \
+                : "g"(0)                \
+                : "cc");                \
+        asm ("addq %0,%0; adcq %2,%1"   \
+                : "+a"(t1),"+d"(t2)     \
+                : "g"(0)                \
+                : "cc");                \
+        asm ("addq %2,%0; adcq %3,%1"   \
+                : "+r"(c0),"+d"(t2)     \
+                : "a"(t1),"g"(0)        \
+                : "cc");                \
+        asm ("addq %2,%0; adcq %3,%1"   \
+                : "+r"(c1),"+r"(c2)     \
+                : "d"(t2),"g"(0)        \
+                : "cc");                \
+        }
+#endif
+
+#define mul_c2(a,b,c0,c1) { \
+    unsigned __int128 q = (unsigned __int128)(a) * (b); \
+    (c0) = q; \
+    (c1) = (q >> 64); \
+}
+
+void static secp256k1_fe_mul(secp256k1_fe_t *r, const secp256k1_fe_t *ac, const secp256k1_fe_t *bc) {
+
+    secp256k1_fe_t a = *ac, b = *bc;
+    secp256k1_fe_reduce(&a);
+    secp256k1_fe_reduce(&b);
+
+#ifdef USE_FIELD_5X64_ASM
+    secp256k1_fe_mul_inner((&a)->n,(&b)->n,r->n);
+#else
+    uint64_t c1,c2,c3;
+    c3=0;
+    mul_c2(a.n[0], b.n[0], c1, c2);
+    uint64_t r0 = c1; c1 = 0;
+    muladd_c3(a.n[0], b.n[1], c2, c3, c1);
+    muladd_c3(a.n[1], b.n[0], c2, c3, c1);
+    uint64_t r1 = c2; c2 = 0;
+    muladd_c3(a.n[2], b.n[0], c3, c1, c2);
+    muladd_c3(a.n[1], b.n[1], c3, c1, c2);
+    muladd_c3(a.n[0], b.n[2], c3, c1, c2);
+    uint64_t r2 = c3; c3 = 0;
+    muladd_c3(a.n[0], b.n[3], c1, c2, c3);
+    muladd_c3(a.n[1], b.n[2], c1, c2, c3);
+    muladd_c3(a.n[2], b.n[1], c1, c2, c3);
+    muladd_c3(a.n[3], b.n[0], c1, c2, c3);
+    uint64_t r3 = c1; c1 = 0;
+    muladd_c3(a.n[3], b.n[1], c2, c3, c1);
+    muladd_c3(a.n[2], b.n[2], c2, c3, c1);
+    muladd_c3(a.n[1], b.n[3], c2, c3, c1);
+    uint64_t r4 = c2; c2 = 0;
+    muladd_c3(a.n[2], b.n[3], c3, c1, c2);
+    muladd_c3(a.n[3], b.n[2], c3, c1, c2);
+    uint64_t r5 = c3; c3 = 0;
+    muladd_c3(a.n[3], b.n[3], c1, c2, c3);
+    uint64_t r6 = c1;
+    uint64_t r7 = c2;
+    assert(c3 == 0);
+    unsigned __int128 c = (unsigned __int128)r4 * COMP_LIMB + r0;
+    r->n[0] = c;
+    c = (unsigned __int128)r5 * COMP_LIMB + r1 + (c >> 64);
+    r->n[1] = c;
+    c = (unsigned __int128)r6 * COMP_LIMB + r2 + (c >> 64);
+    r->n[2] = c;
+    c = (unsigned __int128)r7 * COMP_LIMB + r3 + (c >> 64);
+    r->n[3] = c;
+    r->n[4] = c >> 64;
+#endif
+
+#ifdef VERIFY
+    r->normalized = 0;
+    r->reduced = 0;
+#endif
+    secp256k1_fe_reduce(r);
+}
+
+/*void static secp256k1_fe_sqr(secp256k1_fe_t *r, const secp256k1_fe_t *a) {
+    secp256k1_fe_mul(r, a, a);
+}*/
+
+void static secp256k1_fe_sqr(secp256k1_fe_t *r, const secp256k1_fe_t *ac) {
+    secp256k1_fe_t a = *ac;
+    secp256k1_fe_reduce(&a);
+
+#ifdef USE_FIELD_5X64_ASM
+    secp256k1_fe_sqr_inner((&a)->n,r->n);
+#else
+    uint64_t c1,c2,c3;
+    c3=0;
+    mul_c2(a.n[0], a.n[0], c1, c2);
+    uint64_t r0 = c1; c1 = 0;
+    muladd2_c3(a.n[0], a.n[1], c2, c3, c1);
+    uint64_t r1 = c2; c2 = 0;
+    muladd2_c3(a.n[2], a.n[0], c3, c1, c2);
+    sqradd_c3(a.n[1], c3, c1, c2);
+    uint64_t r2 = c3; c3 = 0;
+    muladd2_c3(a.n[0], a.n[3], c1, c2, c3);
+    muladd2_c3(a.n[1], a.n[2], c1, c2, c3);
+    uint64_t r3 = c1; c1 = 0;
+    muladd2_c3(a.n[3], a.n[1], c2, c3, c1);
+    sqradd_c3(a.n[2], c2, c3, c1);
+    uint64_t r4 = c2; c2 = 0;
+    muladd2_c3(a.n[2], a.n[3], c3, c1, c2);
+    uint64_t r5 = c3; c3 = 0;
+    sqradd_c3(a.n[3], c1, c2, c3);
+    uint64_t r6 = c1;
+    uint64_t r7 = c2;
+    assert(c3 == 0);
+    unsigned __int128 c = (unsigned __int128)r4 * COMP_LIMB + r0;
+    r->n[0] = c;
+    c = (unsigned __int128)r5 * COMP_LIMB + r1 + (c >> 64);
+    r->n[1] = c;
+    c = (unsigned __int128)r6 * COMP_LIMB + r2 + (c >> 64);
+    r->n[2] = c;
+    c = (unsigned __int128)r7 * COMP_LIMB + r3 + (c >> 64);
+    r->n[3] = c;
+    r->n[4] = c >> 64;
+#endif
+
+#ifdef VERIFY
+    r->normalized = 0;
+    r->reduced = 0;
+#endif
+    secp256k1_fe_reduce(r);
+}
+
+#endif
diff --git a/crypto/secp256k1/secp256k1/src/impl/field_5x64_asm.h b/crypto/secp256k1/secp256k1/src/impl/field_5x64_asm.h
new file mode 100644
index 000000000..93c6ab6b5
--- /dev/null
+++ b/crypto/secp256k1/secp256k1/src/impl/field_5x64_asm.h
@@ -0,0 +1,11 @@
+// Copyright (c) 2013 Pieter Wuille
+// Distributed under the MIT/X11 software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef _SECP256K1_FIELD_INNER5X52_IMPL_H_
+#define _SECP256K1_FIELD_INNER5X52_IMPL_H_
+
+void __attribute__ ((sysv_abi)) secp256k1_fe_mul_inner(const uint64_t *a, const uint64_t *b, uint64_t *r);
+void __attribute__ ((sysv_abi)) secp256k1_fe_sqr_inner(const uint64_t *a, uint64_t *r);
+
+#endif
diff --git a/crypto/secp256k1/secp256k1/src/impl/field_gmp.h b/crypto/secp256k1/secp256k1/src/impl/field_gmp.h
new file mode 100644
index 000000000..6172ef48e
--- /dev/null
+++ b/crypto/secp256k1/secp256k1/src/impl/field_gmp.h
@@ -0,0 +1,155 @@
+// Copyright (c) 2013 Pieter Wuille
+// Distributed under the MIT/X11 software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef _SECP256K1_FIELD_REPR_IMPL_H_
+#define _SECP256K1_FIELD_REPR_IMPL_H_
+
+#include <stdio.h>
+#include <assert.h>
+#include <string.h>
+#include "../num.h"
+#include "../field.h"
+
+static mp_limb_t secp256k1_field_p[FIELD_LIMBS];
+static mp_limb_t secp256k1_field_pc[(33+GMP_NUMB_BITS-1)/GMP_NUMB_BITS];
+
+void static secp256k1_fe_inner_start(void) {
+    for (int i=0; i<(33+GMP_NUMB_BITS-1)/GMP_NUMB_BITS; i++)
+        secp256k1_field_pc[i] = 0;
+    secp256k1_field_pc[0] += 0x3D1UL;
+    secp256k1_field_pc[32/GMP_NUMB_BITS] += (1UL << (32 % GMP_NUMB_BITS));
+    for (int i=0; i<FIELD_LIMBS; i++) {
+        secp256k1_field_p[i] = 0;
+    }
+    mpn_sub(secp256k1_field_p, secp256k1_field_p, FIELD_LIMBS, secp256k1_field_pc, (33+GMP_NUMB_BITS-1)/GMP_NUMB_BITS);
+}
+
+void static secp256k1_fe_inner_stop(void) {
+}
+
+void static secp256k1_fe_normalize(secp256k1_fe_t *r) {
+    if (r->n[FIELD_LIMBS] != 0) {
+#if (GMP_NUMB_BITS >= 40)
+        mp_limb_t carry = mpn_add_1(r->n, r->n, FIELD_LIMBS, 0x1000003D1ULL * r->n[FIELD_LIMBS]);
+        mpn_add_1(r->n, r->n, FIELD_LIMBS, 0x1000003D1ULL * carry);
+#else
+        mp_limb_t carry = mpn_add_1(r->n, r->n, FIELD_LIMBS, 0x3D1UL * r->n[FIELD_LIMBS]) + 
+                          mpn_add_1(r->n+(32/GMP_NUMB_BITS), r->n+(32/GMP_NUMB_BITS), FIELD_LIMBS-(32/GMP_NUMB_BITS), r->n[FIELD_LIMBS] << (32 % GMP_NUMB_BITS));
+        mpn_add_1(r->n, r->n, FIELD_LIMBS, 0x3D1UL * carry);
+        mpn_add_1(r->n+(32/GMP_NUMB_BITS), r->n+(32/GMP_NUMB_BITS), FIELD_LIMBS-(32/GMP_NUMB_BITS), carry << (32%GMP_NUMB_BITS));
+#endif
+        r->n[FIELD_LIMBS] = 0;
+    }
+    if (mpn_cmp(r->n, secp256k1_field_p, FIELD_LIMBS) >= 0)
+        mpn_sub(r->n, r->n, FIELD_LIMBS, secp256k1_field_p, FIELD_LIMBS);
+}
+
+void static inline secp256k1_fe_set_int(secp256k1_fe_t *r, int a) {
+    r->n[0] = a;
+    for (int i=1; i<FIELD_LIMBS+1; i++)
+        r->n[i] = 0;
+}
+
+int static inline secp256k1_fe_is_zero(const secp256k1_fe_t *a) {
+    int ret = 1;
+    for (int i=0; i<FIELD_LIMBS+1; i++)
+        ret &= (a->n[i] == 0);
+    return ret;
+}
+
+int static inline secp256k1_fe_is_odd(const secp256k1_fe_t *a) {
+    return a->n[0] & 1;
+}
+
+int static inline secp256k1_fe_equal(const secp256k1_fe_t *a, const secp256k1_fe_t *b) {
+    int ret = 1;
+    for (int i=0; i<FIELD_LIMBS+1; i++)
+        ret &= (a->n[i] == b->n[i]);
+    return ret;
+}
+
+void static secp256k1_fe_set_b32(secp256k1_fe_t *r, const unsigned char *a) {
+    for (int i=0; i<FIELD_LIMBS+1; i++)
+        r->n[i] = 0;
+    for (int i=0; i<256; i++) {
+        int limb = i/GMP_NUMB_BITS;
+        int shift = i%GMP_NUMB_BITS;
+        r->n[limb] |= (mp_limb_t)((a[31-i/8] >> (i%8)) & 0x1) << shift;
+    }
+}
+
+/** Convert a field element to a 32-byte big endian value. Requires the input to be normalized */
+void static secp256k1_fe_get_b32(unsigned char *r, const secp256k1_fe_t *a) {
+    for (int i=0; i<32; i++) {
+        int c = 0;
+        for (int j=0; j<8; j++) {
+            int limb = (8*i+j)/GMP_NUMB_BITS;
+            int shift = (8*i+j)%GMP_NUMB_BITS;
+            c |= ((a->n[limb] >> shift) & 0x1) << j;
+        }
+        r[31-i] = c;
+    }
+}
+
+void static inline secp256k1_fe_negate(secp256k1_fe_t *r, const secp256k1_fe_t *a, int m) {
+    *r = *a;
+    secp256k1_fe_normalize(r);
+    for (int i=0; i<FIELD_LIMBS; i++)
+        r->n[i] = ~(r->n[i]);
+#if (GMP_NUMB_BITS >= 33)
+    mpn_sub_1(r->n, r->n, FIELD_LIMBS, 0x1000003D0ULL);
+#else
+    mpn_sub_1(r->n, r->n, FIELD_LIMBS, 0x3D0UL);
+    mpn_sub_1(r->n+(32/GMP_NUMB_BITS), r->n+(32/GMP_NUMB_BITS), FIELD_LIMBS-(32/GMP_NUMB_BITS), 0x1UL << (32%GMP_NUMB_BITS));
+#endif
+}
+
+void static inline secp256k1_fe_mul_int(secp256k1_fe_t *r, int a) {
+    mpn_mul_1(r->n, r->n, FIELD_LIMBS+1, a);
+}
+
+void static inline secp256k1_fe_add(secp256k1_fe_t *r, const secp256k1_fe_t *a) {
+    mpn_add(r->n, r->n, FIELD_LIMBS+1, a->n, FIELD_LIMBS+1);
+}
+
+void static secp256k1_fe_reduce(secp256k1_fe_t *r, mp_limb_t *tmp) {
+    // <A1 A2 A3 A4> <B1 B2 B3 B4>
+    //       B1 B2 B3 B4
+    // + C * A1 A2 A3 A4
+    // +  A1 A2 A3 A4
+
+#if (GMP_NUMB_BITS >= 33)
+    mp_limb_t o = mpn_addmul_1(tmp, tmp+FIELD_LIMBS, FIELD_LIMBS, 0x1000003D1ULL);
+#else
+    mp_limb_t o = mpn_addmul_1(tmp, tmp+FIELD_LIMBS, FIELD_LIMBS, 0x3D1UL) +
+                  mpn_addmul_1(tmp+(32/GMP_NUMB_BITS), tmp+FIELD_LIMBS, FIELD_LIMBS-(32/GMP_NUMB_BITS), 0x1UL << (32%GMP_NUMB_BITS));
+#endif
+    mp_limb_t q[1+(33+GMP_NUMB_BITS-1)/GMP_NUMB_BITS];
+    q[(33+GMP_NUMB_BITS-1)/GMP_NUMB_BITS] = mpn_mul_1(q, secp256k1_field_pc, (33+GMP_NUMB_BITS-1)/GMP_NUMB_BITS, o);
+#if (GMP_NUMB_BITS <= 32)
+    mp_limb_t o2 = tmp[2*FIELD_LIMBS-(32/GMP_NUMB_BITS)] << (32%GMP_NUMB_BITS);
+    q[(33+GMP_NUMB_BITS-1)/GMP_NUMB_BITS] += mpn_addmul_1(q, secp256k1_field_pc, (33+GMP_NUMB_BITS-1)/GMP_NUMB_BITS, o2);
+#endif
+    r->n[FIELD_LIMBS] = mpn_add(r->n, tmp, FIELD_LIMBS, q, 1+(33+GMP_NUMB_BITS-1)/GMP_NUMB_BITS);
+}
+
+void static secp256k1_fe_mul(secp256k1_fe_t *r, const secp256k1_fe_t *a, const secp256k1_fe_t *b) {
+    secp256k1_fe_t ac = *a;
+    secp256k1_fe_t bc = *b;
+    secp256k1_fe_normalize(&ac);
+    secp256k1_fe_normalize(&bc);
+    mp_limb_t tmp[2*FIELD_LIMBS];
+    mpn_mul_n(tmp, ac.n, bc.n, FIELD_LIMBS);
+    secp256k1_fe_reduce(r, tmp);
+}
+
+void static secp256k1_fe_sqr(secp256k1_fe_t *r, const secp256k1_fe_t *a) {
+    secp256k1_fe_t ac = *a;
+    secp256k1_fe_normalize(&ac);
+    mp_limb_t tmp[2*FIELD_LIMBS];
+    mpn_sqr(tmp, ac.n, FIELD_LIMBS);
+    secp256k1_fe_reduce(r, tmp);
+}
+
+#endif
diff --git a/crypto/secp256k1/secp256k1/src/impl/group.h b/crypto/secp256k1/secp256k1/src/impl/group.h
new file mode 100644
index 000000000..ce8d7b204
--- /dev/null
+++ b/crypto/secp256k1/secp256k1/src/impl/group.h
@@ -0,0 +1,397 @@
+// Copyright (c) 2013 Pieter Wuille
+// Distributed under the MIT/X11 software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef _SECP256K1_GROUP_IMPL_H_
+#define _SECP256K1_GROUP_IMPL_H_
+
+#include <string.h>
+
+#include "../num.h"
+#include "../field.h"
+#include "../group.h"
+
+void static secp256k1_ge_set_infinity(secp256k1_ge_t *r) {
+    r->infinity = 1;
+}
+
+void static secp256k1_ge_set_xy(secp256k1_ge_t *r, const secp256k1_fe_t *x, const secp256k1_fe_t *y) {
+    r->infinity = 0;
+    r->x = *x;
+    r->y = *y;
+}
+
+int static secp256k1_ge_is_infinity(const secp256k1_ge_t *a) {
+    return a->infinity;
+}
+
+void static secp256k1_ge_neg(secp256k1_ge_t *r, const secp256k1_ge_t *a) {
+    r->infinity = a->infinity;
+    r->x = a->x;
+    r->y = a->y;
+    secp256k1_fe_normalize(&r->y);
+    secp256k1_fe_negate(&r->y, &r->y, 1);
+}
+
+void static secp256k1_ge_get_hex(char *r, int *rlen, const secp256k1_ge_t *a) {
+    char cx[65]; int lx=65;
+    char cy[65]; int ly=65;
+    secp256k1_fe_get_hex(cx, &lx, &a->x);
+    secp256k1_fe_get_hex(cy, &ly, &a->y);
+    lx = strlen(cx);
+    ly = strlen(cy);
+    int len = lx + ly + 3 + 1;
+    if (*rlen < len) {
+        *rlen = len;
+        return;
+    }
+    *rlen = len;
+    r[0] = '(';
+    memcpy(r+1, cx, lx);
+    r[1+lx] = ',';
+    memcpy(r+2+lx, cy, ly);
+    r[2+lx+ly] = ')';
+    r[3+lx+ly] = 0;
+}
+
+void static secp256k1_ge_set_gej(secp256k1_ge_t *r, secp256k1_gej_t *a) {
+    secp256k1_fe_inv_var(&a->z, &a->z);
+    secp256k1_fe_t z2; secp256k1_fe_sqr(&z2, &a->z);
+    secp256k1_fe_t z3; secp256k1_fe_mul(&z3, &a->z, &z2);
+    secp256k1_fe_mul(&a->x, &a->x, &z2);
+    secp256k1_fe_mul(&a->y, &a->y, &z3);
+    secp256k1_fe_set_int(&a->z, 1);
+    r->infinity = a->infinity;
+    r->x = a->x;
+    r->y = a->y;
+}
+
+void static secp256k1_gej_set_infinity(secp256k1_gej_t *r) {
+    r->infinity = 1;
+}
+
+void static secp256k1_gej_set_xy(secp256k1_gej_t *r, const secp256k1_fe_t *x, const secp256k1_fe_t *y) {
+    r->infinity = 0;
+    r->x = *x;
+    r->y = *y;
+    secp256k1_fe_set_int(&r->z, 1);
+}
+
+void static secp256k1_ge_set_xo(secp256k1_ge_t *r, const secp256k1_fe_t *x, int odd) {
+    r->x = *x;
+    secp256k1_fe_t x2; secp256k1_fe_sqr(&x2, x);
+    secp256k1_fe_t x3; secp256k1_fe_mul(&x3, x, &x2);
+    r->infinity = 0;
+    secp256k1_fe_t c; secp256k1_fe_set_int(&c, 7);
+    secp256k1_fe_add(&c, &x3);
+    secp256k1_fe_sqrt(&r->y, &c);
+    secp256k1_fe_normalize(&r->y);
+    if (secp256k1_fe_is_odd(&r->y) != odd)
+        secp256k1_fe_negate(&r->y, &r->y, 1);
+}
+
+void static secp256k1_gej_set_ge(secp256k1_gej_t *r, const secp256k1_ge_t *a) {
+   r->infinity = a->infinity;
+   r->x = a->x;
+   r->y = a->y;
+   secp256k1_fe_set_int(&r->z, 1);
+}
+
+void static secp256k1_gej_get_x(secp256k1_fe_t *r, const secp256k1_gej_t *a) {
+    secp256k1_fe_t zi2; secp256k1_fe_inv_var(&zi2, &a->z); secp256k1_fe_sqr(&zi2, &zi2);
+    secp256k1_fe_mul(r, &a->x, &zi2);
+}
+
+void static secp256k1_gej_neg(secp256k1_gej_t *r, const secp256k1_gej_t *a) {
+    r->infinity = a->infinity;
+    r->x = a->x;
+    r->y = a->y;
+    r->z = a->z;
+    secp256k1_fe_normalize(&r->y);
+    secp256k1_fe_negate(&r->y, &r->y, 1);
+}
+
+int static secp256k1_gej_is_infinity(const secp256k1_gej_t *a) {
+    return a->infinity;
+}
+
+int static secp256k1_gej_is_valid(const secp256k1_gej_t *a) {
+    if (a->infinity)
+        return 0;
+    // y^2 = x^3 + 7
+    // (Y/Z^3)^2 = (X/Z^2)^3 + 7
+    // Y^2 / Z^6 = X^3 / Z^6 + 7
+    // Y^2 = X^3 + 7*Z^6
+    secp256k1_fe_t y2; secp256k1_fe_sqr(&y2, &a->y);
+    secp256k1_fe_t x3; secp256k1_fe_sqr(&x3, &a->x); secp256k1_fe_mul(&x3, &x3, &a->x);
+    secp256k1_fe_t z2; secp256k1_fe_sqr(&z2, &a->z);
+    secp256k1_fe_t z6; secp256k1_fe_sqr(&z6, &z2); secp256k1_fe_mul(&z6, &z6, &z2);
+    secp256k1_fe_mul_int(&z6, 7);
+    secp256k1_fe_add(&x3, &z6);
+    secp256k1_fe_normalize(&y2);
+    secp256k1_fe_normalize(&x3);
+    return secp256k1_fe_equal(&y2, &x3);
+}
+
+int static secp256k1_ge_is_valid(const secp256k1_ge_t *a) {
+    if (a->infinity)
+        return 0;
+    // y^2 = x^3 + 7
+    secp256k1_fe_t y2; secp256k1_fe_sqr(&y2, &a->y);
+    secp256k1_fe_t x3; secp256k1_fe_sqr(&x3, &a->x); secp256k1_fe_mul(&x3, &x3, &a->x);
+    secp256k1_fe_t c; secp256k1_fe_set_int(&c, 7);
+    secp256k1_fe_add(&x3, &c);
+    secp256k1_fe_normalize(&y2);
+    secp256k1_fe_normalize(&x3);
+    return secp256k1_fe_equal(&y2, &x3);
+}
+
+void static secp256k1_gej_double(secp256k1_gej_t *r, const secp256k1_gej_t *a) {
+    secp256k1_fe_t t5 = a->y;
+    secp256k1_fe_normalize(&t5);
+    if (a->infinity || secp256k1_fe_is_zero(&t5)) {
+        r->infinity = 1;
+        return;
+    }
+
+    secp256k1_fe_t t1,t2,t3,t4;
+    secp256k1_fe_mul(&r->z, &t5, &a->z);
+    secp256k1_fe_mul_int(&r->z, 2);       // Z' = 2*Y*Z (2)
+    secp256k1_fe_sqr(&t1, &a->x);
+    secp256k1_fe_mul_int(&t1, 3);         // T1 = 3*X^2 (3)
+    secp256k1_fe_sqr(&t2, &t1);           // T2 = 9*X^4 (1)
+    secp256k1_fe_sqr(&t3, &t5);
+    secp256k1_fe_mul_int(&t3, 2);         // T3 = 2*Y^2 (2)
+    secp256k1_fe_sqr(&t4, &t3);
+    secp256k1_fe_mul_int(&t4, 2);         // T4 = 8*Y^4 (2)
+    secp256k1_fe_mul(&t3, &a->x, &t3);    // T3 = 2*X*Y^2 (1)
+    r->x = t3;
+    secp256k1_fe_mul_int(&r->x, 4);       // X' = 8*X*Y^2 (4)
+    secp256k1_fe_negate(&r->x, &r->x, 4); // X' = -8*X*Y^2 (5)
+    secp256k1_fe_add(&r->x, &t2);         // X' = 9*X^4 - 8*X*Y^2 (6)
+    secp256k1_fe_negate(&t2, &t2, 1);     // T2 = -9*X^4 (2)
+    secp256k1_fe_mul_int(&t3, 6);         // T3 = 12*X*Y^2 (6)
+    secp256k1_fe_add(&t3, &t2);           // T3 = 12*X*Y^2 - 9*X^4 (8)
+    secp256k1_fe_mul(&r->y, &t1, &t3);    // Y' = 36*X^3*Y^2 - 27*X^6 (1)
+    secp256k1_fe_negate(&t2, &t4, 2);     // T2 = -8*Y^4 (3)
+    secp256k1_fe_add(&r->y, &t2);         // Y' = 36*X^3*Y^2 - 27*X^6 - 8*Y^4 (4)
+    r->infinity = 0;
+}
+
+void static secp256k1_gej_add(secp256k1_gej_t *r, const secp256k1_gej_t *a, const secp256k1_gej_t *b) {
+    if (a->infinity) {
+        *r = *b;
+        return;
+    }
+    if (b->infinity) {
+        *r = *a;
+        return;
+    }
+    r->infinity = 0;
+    secp256k1_fe_t z22; secp256k1_fe_sqr(&z22, &b->z);
+    secp256k1_fe_t z12; secp256k1_fe_sqr(&z12, &a->z);
+    secp256k1_fe_t u1; secp256k1_fe_mul(&u1, &a->x, &z22);
+    secp256k1_fe_t u2; secp256k1_fe_mul(&u2, &b->x, &z12);
+    secp256k1_fe_t s1; secp256k1_fe_mul(&s1, &a->y, &z22); secp256k1_fe_mul(&s1, &s1, &b->z);
+    secp256k1_fe_t s2; secp256k1_fe_mul(&s2, &b->y, &z12); secp256k1_fe_mul(&s2, &s2, &a->z);
+    secp256k1_fe_normalize(&u1);
+    secp256k1_fe_normalize(&u2);
+    if (secp256k1_fe_equal(&u1, &u2)) {
+        secp256k1_fe_normalize(&s1);
+        secp256k1_fe_normalize(&s2);
+        if (secp256k1_fe_equal(&s1, &s2)) {
+            secp256k1_gej_double(r, a);
+        } else {
+            r->infinity = 1;
+        }
+        return;
+    }
+    secp256k1_fe_t h; secp256k1_fe_negate(&h, &u1, 1); secp256k1_fe_add(&h, &u2);
+    secp256k1_fe_t i; secp256k1_fe_negate(&i, &s1, 1); secp256k1_fe_add(&i, &s2);
+    secp256k1_fe_t i2; secp256k1_fe_sqr(&i2, &i);
+    secp256k1_fe_t h2; secp256k1_fe_sqr(&h2, &h);
+    secp256k1_fe_t h3; secp256k1_fe_mul(&h3, &h, &h2);
+    secp256k1_fe_mul(&r->z, &a->z, &b->z); secp256k1_fe_mul(&r->z, &r->z, &h);
+    secp256k1_fe_t t; secp256k1_fe_mul(&t, &u1, &h2);
+    r->x = t; secp256k1_fe_mul_int(&r->x, 2); secp256k1_fe_add(&r->x, &h3); secp256k1_fe_negate(&r->x, &r->x, 3); secp256k1_fe_add(&r->x, &i2);
+    secp256k1_fe_negate(&r->y, &r->x, 5); secp256k1_fe_add(&r->y, &t); secp256k1_fe_mul(&r->y, &r->y, &i);
+    secp256k1_fe_mul(&h3, &h3, &s1); secp256k1_fe_negate(&h3, &h3, 1);
+    secp256k1_fe_add(&r->y, &h3);
+}
+
+void static secp256k1_gej_add_ge(secp256k1_gej_t *r, const secp256k1_gej_t *a, const secp256k1_ge_t *b) {
+    if (a->infinity) {
+        r->infinity = b->infinity;
+        r->x = b->x;
+        r->y = b->y;
+        secp256k1_fe_set_int(&r->z, 1);
+        return;
+    }
+    if (b->infinity) {
+        *r = *a;
+        return;
+    }
+    r->infinity = 0;
+    secp256k1_fe_t z12; secp256k1_fe_sqr(&z12, &a->z);
+    secp256k1_fe_t u1 = a->x; secp256k1_fe_normalize(&u1);
+    secp256k1_fe_t u2; secp256k1_fe_mul(&u2, &b->x, &z12);
+    secp256k1_fe_t s1 = a->y; secp256k1_fe_normalize(&s1);
+    secp256k1_fe_t s2; secp256k1_fe_mul(&s2, &b->y, &z12); secp256k1_fe_mul(&s2, &s2, &a->z);
+    secp256k1_fe_normalize(&u1);
+    secp256k1_fe_normalize(&u2);
+    if (secp256k1_fe_equal(&u1, &u2)) {
+        secp256k1_fe_normalize(&s1);
+        secp256k1_fe_normalize(&s2);
+        if (secp256k1_fe_equal(&s1, &s2)) {
+            secp256k1_gej_double(r, a);
+        } else {
+            r->infinity = 1;
+        }
+        return;
+    }
+    secp256k1_fe_t h; secp256k1_fe_negate(&h, &u1, 1); secp256k1_fe_add(&h, &u2);
+    secp256k1_fe_t i; secp256k1_fe_negate(&i, &s1, 1); secp256k1_fe_add(&i, &s2);
+    secp256k1_fe_t i2; secp256k1_fe_sqr(&i2, &i);
+    secp256k1_fe_t h2; secp256k1_fe_sqr(&h2, &h);
+    secp256k1_fe_t h3; secp256k1_fe_mul(&h3, &h, &h2);
+    r->z = a->z; secp256k1_fe_mul(&r->z, &r->z, &h);
+    secp256k1_fe_t t; secp256k1_fe_mul(&t, &u1, &h2);
+    r->x = t; secp256k1_fe_mul_int(&r->x, 2); secp256k1_fe_add(&r->x, &h3); secp256k1_fe_negate(&r->x, &r->x, 3); secp256k1_fe_add(&r->x, &i2);
+    secp256k1_fe_negate(&r->y, &r->x, 5); secp256k1_fe_add(&r->y, &t); secp256k1_fe_mul(&r->y, &r->y, &i);
+    secp256k1_fe_mul(&h3, &h3, &s1); secp256k1_fe_negate(&h3, &h3, 1);
+    secp256k1_fe_add(&r->y, &h3);
+}
+
+void static secp256k1_gej_get_hex(char *r, int *rlen, const secp256k1_gej_t *a) {
+    secp256k1_gej_t c = *a;
+    secp256k1_ge_t t; secp256k1_ge_set_gej(&t, &c);
+    secp256k1_ge_get_hex(r, rlen, &t);
+}
+
+void static secp256k1_gej_mul_lambda(secp256k1_gej_t *r, const secp256k1_gej_t *a) {
+    const secp256k1_fe_t *beta = &secp256k1_ge_consts->beta;
+    *r = *a;
+    secp256k1_fe_mul(&r->x, &r->x, beta);
+}
+
+void static secp256k1_gej_split_exp(secp256k1_num_t *r1, secp256k1_num_t *r2, const secp256k1_num_t *a) {
+    const secp256k1_ge_consts_t *c = secp256k1_ge_consts;
+    secp256k1_num_t bnc1, bnc2, bnt1, bnt2, bnn2;
+
+    secp256k1_num_init(&bnc1);
+    secp256k1_num_init(&bnc2);
+    secp256k1_num_init(&bnt1);
+    secp256k1_num_init(&bnt2);
+    secp256k1_num_init(&bnn2);
+
+    secp256k1_num_copy(&bnn2, &c->order);
+    secp256k1_num_shift(&bnn2, 1);
+
+    secp256k1_num_mul(&bnc1, a, &c->a1b2);
+    secp256k1_num_add(&bnc1, &bnc1, &bnn2);
+    secp256k1_num_div(&bnc1, &bnc1, &c->order);
+
+    secp256k1_num_mul(&bnc2, a, &c->b1);
+    secp256k1_num_add(&bnc2, &bnc2, &bnn2);
+    secp256k1_num_div(&bnc2, &bnc2, &c->order);
+
+    secp256k1_num_mul(&bnt1, &bnc1, &c->a1b2);
+    secp256k1_num_mul(&bnt2, &bnc2, &c->a2);
+    secp256k1_num_add(&bnt1, &bnt1, &bnt2);
+    secp256k1_num_sub(r1, a, &bnt1);
+    secp256k1_num_mul(&bnt1, &bnc1, &c->b1);
+    secp256k1_num_mul(&bnt2, &bnc2, &c->a1b2);
+    secp256k1_num_sub(r2, &bnt1, &bnt2);
+
+    secp256k1_num_free(&bnc1);
+    secp256k1_num_free(&bnc2);
+    secp256k1_num_free(&bnt1);
+    secp256k1_num_free(&bnt2);
+    secp256k1_num_free(&bnn2);
+}
+
+
+void static secp256k1_ge_start(void) {
+    static const unsigned char secp256k1_ge_consts_order[] = {
+        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
+    };
+    static const unsigned char secp256k1_ge_consts_g_x[] = {
+        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
+    };
+    static const unsigned char secp256k1_ge_consts_g_y[] = {
+        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
+    };
+    // properties of secp256k1's efficiently computable endomorphism
+    static const unsigned char secp256k1_ge_consts_lambda[] = {
+        0x53,0x63,0xad,0x4c,0xc0,0x5c,0x30,0xe0,
+        0xa5,0x26,0x1c,0x02,0x88,0x12,0x64,0x5a,
+        0x12,0x2e,0x22,0xea,0x20,0x81,0x66,0x78,
+        0xdf,0x02,0x96,0x7c,0x1b,0x23,0xbd,0x72
+    };
+    static const unsigned char secp256k1_ge_consts_beta[] = {
+        0x7a,0xe9,0x6a,0x2b,0x65,0x7c,0x07,0x10,
+        0x6e,0x64,0x47,0x9e,0xac,0x34,0x34,0xe9,
+        0x9c,0xf0,0x49,0x75,0x12,0xf5,0x89,0x95,
+        0xc1,0x39,0x6c,0x28,0x71,0x95,0x01,0xee
+    };
+    static const unsigned char secp256k1_ge_consts_a1b2[] = {
+        0x30,0x86,0xd2,0x21,0xa7,0xd4,0x6b,0xcd,
+        0xe8,0x6c,0x90,0xe4,0x92,0x84,0xeb,0x15
+    };
+    static const unsigned char secp256k1_ge_consts_b1[] = {
+        0xe4,0x43,0x7e,0xd6,0x01,0x0e,0x88,0x28,
+        0x6f,0x54,0x7f,0xa9,0x0a,0xbf,0xe4,0xc3
+    };
+    static const unsigned char secp256k1_ge_consts_a2[] = {
+        0x01,
+        0x14,0xca,0x50,0xf7,0xa8,0xe2,0xf3,0xf6,
+        0x57,0xc1,0x10,0x8d,0x9d,0x44,0xcf,0xd8
+    };
+    if (secp256k1_ge_consts == NULL) {
+        secp256k1_ge_consts_t *ret = (secp256k1_ge_consts_t*)malloc(sizeof(secp256k1_ge_consts_t));
+        secp256k1_num_init(&ret->order);
+        secp256k1_num_init(&ret->half_order);
+        secp256k1_num_init(&ret->lambda);
+        secp256k1_num_init(&ret->a1b2);
+        secp256k1_num_init(&ret->a2);
+        secp256k1_num_init(&ret->b1);
+        secp256k1_num_set_bin(&ret->order,  secp256k1_ge_consts_order,  sizeof(secp256k1_ge_consts_order));
+        secp256k1_num_set_bin(&ret->lambda, secp256k1_ge_consts_lambda, sizeof(secp256k1_ge_consts_lambda));
+        secp256k1_num_set_bin(&ret->a1b2,   secp256k1_ge_consts_a1b2,   sizeof(secp256k1_ge_consts_a1b2));
+        secp256k1_num_set_bin(&ret->a2,     secp256k1_ge_consts_a2,     sizeof(secp256k1_ge_consts_a2));
+        secp256k1_num_set_bin(&ret->b1,     secp256k1_ge_consts_b1,     sizeof(secp256k1_ge_consts_b1));
+        secp256k1_num_copy(&ret->half_order, &ret->order);
+        secp256k1_num_shift(&ret->half_order, 1);
+        secp256k1_fe_set_b32(&ret->beta, secp256k1_ge_consts_beta);
+        secp256k1_fe_t g_x, g_y;
+        secp256k1_fe_set_b32(&g_x, secp256k1_ge_consts_g_x);
+        secp256k1_fe_set_b32(&g_y, secp256k1_ge_consts_g_y);
+        secp256k1_ge_set_xy(&ret->g, &g_x, &g_y);
+        secp256k1_ge_consts = ret;
+    }
+}
+
+void static secp256k1_ge_stop(void) {
+    if (secp256k1_ge_consts != NULL) {
+        secp256k1_ge_consts_t *c = (secp256k1_ge_consts_t*)secp256k1_ge_consts;
+        secp256k1_num_free(&c->order);
+        secp256k1_num_free(&c->half_order);
+        secp256k1_num_free(&c->lambda);
+        secp256k1_num_free(&c->a1b2);
+        secp256k1_num_free(&c->a2);
+        secp256k1_num_free(&c->b1);
+        free((void*)c);
+        secp256k1_ge_consts = NULL;
+    }
+}
+
+#endif
diff --git a/crypto/secp256k1/secp256k1/src/impl/num.h b/crypto/secp256k1/secp256k1/src/impl/num.h
new file mode 100644
index 000000000..fc6d05c3d
--- /dev/null
+++ b/crypto/secp256k1/secp256k1/src/impl/num.h
@@ -0,0 +1,18 @@
+// Copyright (c) 2013 Pieter Wuille
+// Distributed under the MIT/X11 software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef _SECP256K1_NUM_IMPL_H_
+#define _SECP256K1_NUM_IMPL_H_
+
+#include "../num.h"
+
+#if defined(USE_NUM_GMP)
+#include "num_gmp.h"
+#elif defined(USE_NUM_OPENSSL)
+#include "num_openssl.h"
+#else
+#error "Please select num implementation"
+#endif
+
+#endif
diff --git a/crypto/secp256k1/secp256k1/src/impl/num_gmp.h b/crypto/secp256k1/secp256k1/src/impl/num_gmp.h
new file mode 100644
index 000000000..067c15180
--- /dev/null
+++ b/crypto/secp256k1/secp256k1/src/impl/num_gmp.h
@@ -0,0 +1,346 @@
+// Copyright (c) 2013 Pieter Wuille
+// Distributed under the MIT/X11 software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef _SECP256K1_NUM_REPR_IMPL_H_
+#define _SECP256K1_NUM_REPR_IMPL_H_
+
+#include <assert.h>
+#include <string.h>
+#include <stdlib.h>
+#include <gmp.h>
+
+#include "num.h"
+
+#ifdef VERIFY
+void static secp256k1_num_sanity(const secp256k1_num_t *a) {
+    assert(a->limbs == 1 || (a->limbs > 1 && a->data[a->limbs-1] != 0));
+}
+#else
+#define secp256k1_num_sanity(a) do { } while(0)
+#endif
+
+void static secp256k1_num_init(secp256k1_num_t *r) {
+    r->neg = 0;
+    r->limbs = 1;
+    r->data[0] = 0;
+}
+
+void static secp256k1_num_free(secp256k1_num_t *r) {
+}
+
+void static secp256k1_num_copy(secp256k1_num_t *r, const secp256k1_num_t *a) {
+    *r = *a;
+}
+
+int static secp256k1_num_bits(const secp256k1_num_t *a) {
+    int ret=(a->limbs-1)*GMP_NUMB_BITS;
+    mp_limb_t x=a->data[a->limbs-1];
+    while (x) {
+        x >>= 1;
+        ret++;
+    }
+    return ret;
+}
+
+
+void static secp256k1_num_get_bin(unsigned char *r, unsigned int rlen, const secp256k1_num_t *a) {
+    unsigned char tmp[65];
+    int len = 0;
+    if (a->limbs>1 || a->data[0] != 0) {
+        len = mpn_get_str(tmp, 256, (mp_limb_t*)a->data, a->limbs);
+    }
+    int shift = 0;
+    while (shift < len && tmp[shift] == 0) shift++;
+    assert(len-shift <= rlen);
+    memset(r, 0, rlen - len + shift);
+    if (len > shift)
+        memcpy(r + rlen - len + shift, tmp + shift, len - shift);
+}
+
+void static secp256k1_num_set_bin(secp256k1_num_t *r, const unsigned char *a, unsigned int alen) {
+    assert(alen > 0);
+    assert(alen <= 64);
+    int len = mpn_set_str(r->data, a, alen, 256);
+    assert(len <= NUM_LIMBS*2);
+    r->limbs = len;
+    r->neg = 0;
+    while (r->limbs > 1 && r->data[r->limbs-1]==0) r->limbs--;
+}
+
+void static secp256k1_num_set_int(secp256k1_num_t *r, int a) {
+    r->limbs = 1;
+    r->neg = (a < 0);
+    r->data[0] = (a < 0) ? -a : a;
+}
+
+void static secp256k1_num_add_abs(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b) {
+    mp_limb_t c = mpn_add(r->data, a->data, a->limbs, b->data, b->limbs);
+    r->limbs = a->limbs;
+    if (c != 0) {
+        assert(r->limbs < 2*NUM_LIMBS);
+        r->data[r->limbs++] = c;
+    }
+}
+
+void static secp256k1_num_sub_abs(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b) {
+    mp_limb_t c = mpn_sub(r->data, a->data, a->limbs, b->data, b->limbs);
+    assert(c == 0);
+    r->limbs = a->limbs;
+    while (r->limbs > 1 && r->data[r->limbs-1]==0) r->limbs--;
+}
+
+void static secp256k1_num_mod(secp256k1_num_t *r, const secp256k1_num_t *m) {
+    secp256k1_num_sanity(r);
+    secp256k1_num_sanity(m);
+
+    if (r->limbs >= m->limbs) {
+        mp_limb_t t[2*NUM_LIMBS];
+        mpn_tdiv_qr(t, r->data, 0, r->data, r->limbs, m->data, m->limbs);
+        r->limbs = m->limbs;
+        while (r->limbs > 1 && r->data[r->limbs-1]==0) r->limbs--;
+    }
+
+    if (r->neg && (r->limbs > 1 || r->data[0] != 0)) {
+        secp256k1_num_sub_abs(r, m, r);
+        r->neg = 0;
+    }
+}
+
+void static secp256k1_num_mod_inverse(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *m) {
+    secp256k1_num_sanity(a);
+    secp256k1_num_sanity(m);
+
+    // mpn_gcdext computes: (G,S) = gcdext(U,V), where
+    // * G = gcd(U,V)
+    // * G = U*S + V*T
+    // * U has equal or more limbs than V, and V has no padding
+    // If we set U to be (a padded version of) a, and V = m:
+    //   G = a*S + m*T
+    //   G = a*S mod m
+    // Assuming G=1:
+    //   S = 1/a mod m
+    assert(m->limbs <= NUM_LIMBS);
+    assert(m->data[m->limbs-1] != 0);
+    mp_limb_t g[NUM_LIMBS+1];
+    mp_limb_t u[NUM_LIMBS+1];
+    mp_limb_t v[NUM_LIMBS+1];
+    for (int i=0; i < m->limbs; i++) {
+        u[i] = (i < a->limbs) ? a->data[i] : 0;
+        v[i] = m->data[i];
+    }
+    mp_size_t sn = NUM_LIMBS+1;
+    mp_size_t gn = mpn_gcdext(g, r->data, &sn, u, m->limbs, v, m->limbs);
+    assert(gn == 1);
+    assert(g[0] == 1);
+    r->neg = a->neg ^ m->neg;
+    if (sn < 0) {
+        mpn_sub(r->data, m->data, m->limbs, r->data, -sn);
+        r->limbs = m->limbs;
+        while (r->limbs > 1 && r->data[r->limbs-1]==0) r->limbs--;
+    } else {
+        r->limbs = sn;
+    }
+}
+
+int static secp256k1_num_is_zero(const secp256k1_num_t *a) {
+    return (a->limbs == 1 && a->data[0] == 0);
+}
+
+int static secp256k1_num_is_odd(const secp256k1_num_t *a) {
+    return a->data[0] & 1;
+}
+
+int static secp256k1_num_is_neg(const secp256k1_num_t *a) {
+    return (a->limbs > 1 || a->data[0] != 0) && a->neg;
+}
+
+int static secp256k1_num_cmp(const secp256k1_num_t *a, const secp256k1_num_t *b) {
+    if (a->limbs > b->limbs) return 1;
+    if (a->limbs < b->limbs) return -1;
+    return mpn_cmp(a->data, b->data, a->limbs);
+}
+
+void static secp256k1_num_subadd(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b, int bneg) {
+    if (!(b->neg ^ bneg ^ a->neg)) { // a and b have the same sign
+        r->neg = a->neg;
+        if (a->limbs >= b->limbs) {
+            secp256k1_num_add_abs(r, a, b);
+        } else {
+            secp256k1_num_add_abs(r, b, a);
+        }
+    } else {
+        if (secp256k1_num_cmp(a, b) > 0) {
+            r->neg = a->neg;
+            secp256k1_num_sub_abs(r, a, b);
+        } else {
+            r->neg = b->neg ^ bneg;
+            secp256k1_num_sub_abs(r, b, a);
+        }
+    }
+}
+
+void static secp256k1_num_add(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b) {
+    secp256k1_num_sanity(a);
+    secp256k1_num_sanity(b);
+    secp256k1_num_subadd(r, a, b, 0);
+}
+
+void static secp256k1_num_sub(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b) {
+    secp256k1_num_sanity(a);
+    secp256k1_num_sanity(b);
+    secp256k1_num_subadd(r, a, b, 1);
+}
+
+void static secp256k1_num_mul(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b) {
+    secp256k1_num_sanity(a);
+    secp256k1_num_sanity(b);
+
+    mp_limb_t tmp[2*NUM_LIMBS+1];
+    assert(a->limbs + b->limbs <= 2*NUM_LIMBS+1);
+    if ((a->limbs==1 && a->data[0]==0) || (b->limbs==1 && b->data[0]==0)) {
+        r->limbs = 1;
+        r->neg = 0;
+        r->data[0] = 0;
+        return;
+    }
+    if (a->limbs >= b->limbs)
+        mpn_mul(tmp, a->data, a->limbs, b->data, b->limbs);
+    else
+        mpn_mul(tmp, b->data, b->limbs, a->data, a->limbs);
+    r->limbs = a->limbs + b->limbs;
+    if (r->limbs > 1 && tmp[r->limbs - 1]==0) r->limbs--;
+    assert(r->limbs <= 2*NUM_LIMBS);
+    mpn_copyi(r->data, tmp, r->limbs);
+    r->neg = a->neg ^ b->neg;
+}
+
+void static secp256k1_num_div(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b) {
+    secp256k1_num_sanity(a);
+    secp256k1_num_sanity(b);
+    if (b->limbs > a->limbs) {
+        r->limbs = 1;
+        r->data[0] = 0;
+        r->neg = 0;
+        return;
+    }
+
+    mp_limb_t quo[2*NUM_LIMBS+1];
+    mp_limb_t rem[2*NUM_LIMBS+1];
+    mpn_tdiv_qr(quo, rem, 0, a->data, a->limbs, b->data, b->limbs);
+    mpn_copyi(r->data, quo, a->limbs - b->limbs + 1);
+    r->limbs = a->limbs - b->limbs + 1;
+    while (r->limbs > 1 && r->data[r->limbs - 1]==0) r->limbs--;
+    r->neg = a->neg ^ b->neg;
+}
+
+void static secp256k1_num_mod_mul(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b, const secp256k1_num_t *m) {
+    secp256k1_num_mul(r, a, b);
+    secp256k1_num_mod(r, m);
+}
+
+
+int static secp256k1_num_shift(secp256k1_num_t *r, int bits) {
+    assert(bits <= GMP_NUMB_BITS);
+    mp_limb_t ret = mpn_rshift(r->data, r->data, r->limbs, bits);
+    if (r->limbs>1 && r->data[r->limbs-1]==0) r->limbs--;
+    ret >>= (GMP_NUMB_BITS - bits);
+    return ret;
+}
+
+int static secp256k1_num_get_bit(const secp256k1_num_t *a, int pos) {
+    return (a->limbs*GMP_NUMB_BITS > pos) && ((a->data[pos/GMP_NUMB_BITS] >> (pos % GMP_NUMB_BITS)) & 1);
+}
+
+void static secp256k1_num_inc(secp256k1_num_t *r) {
+    mp_limb_t ret = mpn_add_1(r->data, r->data, r->limbs, (mp_limb_t)1);
+    if (ret) {
+        assert(r->limbs < 2*NUM_LIMBS);
+        r->data[r->limbs++] = ret;
+    }
+}
+
+void static secp256k1_num_set_hex(secp256k1_num_t *r, const char *a, int alen) {
+    static const unsigned char cvt[256] = {
+        0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,
+        0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,
+        0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,
+        0, 1, 2, 3, 4, 5, 6,7,8,9,0,0,0,0,0,0,
+        0,10,11,12,13,14,15,0,0,0,0,0,0,0,0,0,
+        0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,
+        0,10,11,12,13,14,15,0,0,0,0,0,0,0,0,0,
+        0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,
+        0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,
+        0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,
+        0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,
+        0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,
+        0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,
+        0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,
+        0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,
+        0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0
+    };
+    unsigned char num[257] = {};
+    for (int i=0; i<alen; i++) {
+        num[i] = cvt[a[i]];
+    }
+    r->limbs = mpn_set_str(r->data, num, alen, 16);
+    while (r->limbs > 1 && r->data[r->limbs-1] == 0) r->limbs--;
+}
+
+void static secp256k1_num_get_hex(char *r, int rlen, const secp256k1_num_t *a) {
+    static const unsigned char cvt[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
+    unsigned char *tmp = malloc(257);
+    mp_size_t len = mpn_get_str(tmp, 16, (mp_limb_t*)a->data, a->limbs);
+    assert(len <= rlen);
+    for (int i=0; i<len; i++) {
+        assert(rlen-len+i >= 0);
+        assert(rlen-len+i < rlen);
+        assert(tmp[i] >= 0);
+        assert(tmp[i] < 16);
+        r[rlen-len+i] = cvt[tmp[i]];
+    }
+    for (int i=0; i<rlen-len; i++) {
+        assert(i >= 0);
+        assert(i < rlen);
+        r[i] = cvt[0];
+    }
+    free(tmp);
+}
+
+void static secp256k1_num_split(secp256k1_num_t *rl, secp256k1_num_t *rh, const secp256k1_num_t *a, int bits) {
+    assert(bits > 0);
+    rh->neg = a->neg;
+    if (bits >= a->limbs * GMP_NUMB_BITS) {
+        *rl = *a;
+        rh->limbs = 1;
+        rh->data[0] = 0;
+        return;
+    }
+    rl->limbs = 0;
+    rl->neg = a->neg;
+    int left = bits;
+    while (left >= GMP_NUMB_BITS) {
+        rl->data[rl->limbs] = a->data[rl->limbs];
+        rl->limbs++;
+        left -= GMP_NUMB_BITS;
+    }
+    if (left == 0) {
+        mpn_copyi(rh->data, a->data + rl->limbs, a->limbs - rl->limbs);
+        rh->limbs = a->limbs - rl->limbs;
+    } else {
+        mpn_rshift(rh->data, a->data + rl->limbs, a->limbs - rl->limbs, left);
+        rh->limbs = a->limbs - rl->limbs;
+        while (rh->limbs>1 && rh->data[rh->limbs-1]==0) rh->limbs--;
+    }
+    if (left > 0) {
+        rl->data[rl->limbs] = a->data[rl->limbs] & ((((mp_limb_t)1) << left) - 1);
+        rl->limbs++;
+    }
+    while (rl->limbs>1 && rl->data[rl->limbs-1]==0) rl->limbs--;
+}
+
+void static secp256k1_num_negate(secp256k1_num_t *r) {
+    r->neg ^= 1;
+}
+
+#endif
diff --git a/crypto/secp256k1/secp256k1/src/impl/num_openssl.h b/crypto/secp256k1/secp256k1/src/impl/num_openssl.h
new file mode 100644
index 000000000..0a54689ac
--- /dev/null
+++ b/crypto/secp256k1/secp256k1/src/impl/num_openssl.h
@@ -0,0 +1,145 @@
+// Copyright (c) 2013 Pieter Wuille
+// Distributed under the MIT/X11 software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef _SECP256K1_NUM_REPR_IMPL_H_
+#define _SECP256K1_NUM_REPR_IMPL_H_
+
+#include <assert.h>
+#include <string.h>
+#include <stdlib.h>
+#include <openssl/bn.h>
+#include <openssl/crypto.h>
+
+#include "../num.h"
+
+void static secp256k1_num_init(secp256k1_num_t *r) {
+    BN_init(&r->bn);
+}
+
+void static secp256k1_num_free(secp256k1_num_t *r) {
+    BN_free(&r->bn);
+}
+
+void static secp256k1_num_copy(secp256k1_num_t *r, const secp256k1_num_t *a) {
+    BN_copy(&r->bn, &a->bn);
+}
+
+void static secp256k1_num_get_bin(unsigned char *r, unsigned int rlen, const secp256k1_num_t *a) {
+    unsigned int size = BN_num_bytes(&a->bn);
+    assert(size <= rlen);
+    memset(r,0,rlen);
+    BN_bn2bin(&a->bn, r + rlen - size);
+}
+
+void static secp256k1_num_set_bin(secp256k1_num_t *r, const unsigned char *a, unsigned int alen) {
+    BN_bin2bn(a, alen, &r->bn);
+}
+
+void static secp256k1_num_set_int(secp256k1_num_t *r, int a) {
+    BN_set_word(&r->bn, a < 0 ? -a : a);
+    BN_set_negative(&r->bn, a < 0);
+}
+
+void static secp256k1_num_mod_inverse(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *m) {
+    BN_CTX *ctx = BN_CTX_new();
+    BN_mod_inverse(&r->bn, &a->bn, &m->bn, ctx);
+    BN_CTX_free(ctx);
+}
+
+void static secp256k1_num_mod_mul(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b, const secp256k1_num_t *m) {
+    BN_CTX *ctx = BN_CTX_new();
+    BN_mod_mul(&r->bn, &a->bn, &b->bn, &m->bn, ctx);
+    BN_CTX_free(ctx);
+}
+
+int static secp256k1_num_cmp(const secp256k1_num_t *a, const secp256k1_num_t *b) {
+    return BN_cmp(&a->bn, &b->bn);
+}
+
+void static secp256k1_num_add(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b) {
+    BN_add(&r->bn, &a->bn, &b->bn);
+}
+
+void static secp256k1_num_sub(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b) {
+    BN_sub(&r->bn, &a->bn, &b->bn);
+}
+
+void static secp256k1_num_mul(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b) {
+    BN_CTX *ctx = BN_CTX_new();
+    BN_mul(&r->bn, &a->bn, &b->bn, ctx);
+    BN_CTX_free(ctx);
+}
+
+void static secp256k1_num_div(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b) {
+    BN_CTX *ctx = BN_CTX_new();
+    BN_div(&r->bn, NULL, &a->bn, &b->bn, ctx);
+    BN_CTX_free(ctx);
+}
+
+void static secp256k1_num_mod(secp256k1_num_t *r, const secp256k1_num_t *m) {
+    BN_CTX *ctx = BN_CTX_new();
+    BN_nnmod(&r->bn, &r->bn, &m->bn, ctx);
+    BN_CTX_free(ctx);
+}
+
+int static secp256k1_num_bits(const secp256k1_num_t *a) {
+    return BN_num_bits(&a->bn);
+}
+
+int static secp256k1_num_shift(secp256k1_num_t *r, int bits) {
+    int ret = BN_is_zero(&r->bn) ? 0 : r->bn.d[0] & ((1 << bits) - 1);
+    BN_rshift(&r->bn, &r->bn, bits);
+    return ret;
+}
+
+int static secp256k1_num_is_zero(const secp256k1_num_t *a) {
+    return BN_is_zero(&a->bn);
+}
+
+int static secp256k1_num_is_odd(const secp256k1_num_t *a) {
+    return BN_is_odd(&a->bn);
+}
+
+int static secp256k1_num_is_neg(const secp256k1_num_t *a) {
+    return BN_is_negative(&a->bn);
+}
+
+int static secp256k1_num_get_bit(const secp256k1_num_t *a, int pos) {
+    return BN_is_bit_set(&a->bn, pos);
+}
+
+void static secp256k1_num_inc(secp256k1_num_t *r) {
+    BN_add_word(&r->bn, 1);
+}
+
+void static secp256k1_num_set_hex(secp256k1_num_t *r, const char *a, int alen) {
+    char *str = (char*)malloc(alen+1);
+    memcpy(str, a, alen);
+    str[alen] = 0;
+    BIGNUM *pbn = &r->bn;
+    BN_hex2bn(&pbn, str);
+    free(str);
+}
+
+void static secp256k1_num_get_hex(char *r, int rlen, const secp256k1_num_t *a) {
+    char *str = BN_bn2hex(&a->bn);
+    int len = strlen(str);
+    assert(rlen >= len);
+    for (int i=0; i<rlen-len; i++)
+        r[i] = '0';
+    memcpy(r+rlen-len, str, len);
+    OPENSSL_free(str);
+}
+
+void static secp256k1_num_split(secp256k1_num_t *rl, secp256k1_num_t *rh, const secp256k1_num_t *a, int bits) {
+    BN_copy(&rl->bn, &a->bn);
+    BN_rshift(&rh->bn, &a->bn, bits);
+    BN_mask_bits(&rl->bn, bits);
+}
+
+void static secp256k1_num_negate(secp256k1_num_t *r) {
+    BN_set_negative(&r->bn, !BN_is_negative(&r->bn));
+}
+
+#endif
diff --git a/crypto/secp256k1/secp256k1/src/impl/util.h b/crypto/secp256k1/secp256k1/src/impl/util.h
new file mode 100644
index 000000000..a59a00cac
--- /dev/null
+++ b/crypto/secp256k1/secp256k1/src/impl/util.h
@@ -0,0 +1,45 @@
+// Copyright (c) 2013 Pieter Wuille
+// Distributed under the MIT/X11 software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef _SECP256K1_UTIL_IMPL_H_
+#define _SECP256K1_UTIL_IMPL_H_
+
+#include <stdint.h>
+#include <string.h>
+
+#include "../util.h"
+
+static inline uint32_t secp256k1_rand32(void) {
+    static uint32_t Rz = 11, Rw = 11;
+    Rz = 36969 * (Rz & 0xFFFF) + (Rz >> 16);
+    Rw = 18000 * (Rw & 0xFFFF) + (Rw >> 16);
+    return (Rw << 16) + (Rw >> 16) + Rz;
+}
+
+static void secp256k1_rand256(unsigned char *b32) {
+    for (int i=0; i<8; i++) {
+        uint32_t r = secp256k1_rand32();
+        b32[i*4 + 0] = (r >>  0) & 0xFF;
+        b32[i*4 + 1] = (r >>  8) & 0xFF;
+        b32[i*4 + 2] = (r >> 16) & 0xFF;
+        b32[i*4 + 3] = (r >> 24) & 0xFF;
+    }
+}
+
+static void secp256k1_rand256_test(unsigned char *b32) {
+    int bits=0;
+    memset(b32, 0, 32);
+    while (bits < 256) {
+        uint32_t ent = secp256k1_rand32();
+        int now = 1 + ((ent % 64)*((ent >> 6) % 32)+16)/31;
+        uint32_t val = 1 & (ent >> 11);
+        while (now > 0 && bits < 256) {
+            b32[bits / 8] |= val << (bits % 8);
+            now--;
+            bits++;
+        }
+    }
+}
+
+#endif
diff --git a/crypto/secp256k1/secp256k1/src/java/org/bitcoin/NativeSecp256k1.java b/crypto/secp256k1/secp256k1/src/java/org/bitcoin/NativeSecp256k1.java
new file mode 100644
index 000000000..90a498eaa
--- /dev/null
+++ b/crypto/secp256k1/secp256k1/src/java/org/bitcoin/NativeSecp256k1.java
@@ -0,0 +1,60 @@
+package org.bitcoin;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
+import com.google.common.base.Preconditions;
+
+
+/**
+ * This class holds native methods to handle ECDSA verification.
+ * You can find an example library that can be used for this at
+ * https://github.com/sipa/secp256k1
+ */
+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 ThreadLocal<ByteBuffer> nativeECDSABuffer = new ThreadLocal<ByteBuffer>();
+    /**
+     * Verifies the given secp256k1 signature in native code.
+     * Calling when enabled == false is undefined (probably library not loaded)
+     * 
+     * @param data The data which was signed, must be exactly 32 bytes
+     * @param signature The signature
+     * @param pub The public key which did the signing
+     */
+    public static boolean verify(byte[] data, byte[] signature, byte[] pub) {
+        Preconditions.checkArgument(data.length == 32 && signature.length <= 520 && pub.length <= 520);
+
+        ByteBuffer byteBuff = nativeECDSABuffer.get();
+        if (byteBuff == null) {
+            byteBuff = ByteBuffer.allocateDirect(32 + 8 + 520 + 520);
+            byteBuff.order(ByteOrder.nativeOrder());
+            nativeECDSABuffer.set(byteBuff);
+        }
+        byteBuff.rewind();
+        byteBuff.put(data);
+        byteBuff.putInt(signature.length);
+        byteBuff.putInt(pub.length);
+        byteBuff.put(signature);
+        byteBuff.put(pub);
+        return secp256k1_ecdsa_verify(byteBuff) == 1;
+    }
+
+    /**
+     * @param byteBuff signature format is byte[32] data,
+     *        native-endian int signatureLength, native-endian int pubkeyLength,
+     *        byte[signatureLength] signature, byte[pubkeyLength] pub
+     * @returns 1 for valid signature, anything else for invalid
+     */
+    private static native int secp256k1_ecdsa_verify(ByteBuffer byteBuff);
+}
diff --git a/crypto/secp256k1/secp256k1/src/java/org_bitcoin_NativeSecp256k1.c b/crypto/secp256k1/secp256k1/src/java/org_bitcoin_NativeSecp256k1.c
new file mode 100644
index 000000000..ed65cccf6
--- /dev/null
+++ b/crypto/secp256k1/secp256k1/src/java/org_bitcoin_NativeSecp256k1.c
@@ -0,0 +1,23 @@
+#include "org_bitcoin_NativeSecp256k1.h"
+#include "include/secp256k1.h"
+
+JNIEXPORT jint JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ecdsa_1verify
+  (JNIEnv* env, jclass classObject, jobject byteBufferObject)
+{
+	unsigned char* data = (unsigned char*) (*env)->GetDirectBufferAddress(env, byteBufferObject);
+	int sigLen = *((int*)(data + 32));
+	int pubLen = *((int*)(data + 32 + 4));
+
+	return secp256k1_ecdsa_verify(data, 32, data+32+8, sigLen, data+32+8+sigLen, pubLen);
+}
+
+static void __javasecp256k1_attach(void) __attribute__((constructor));
+static void __javasecp256k1_detach(void) __attribute__((destructor));
+
+static void __javasecp256k1_attach(void) {
+	secp256k1_start();
+}
+
+static void __javasecp256k1_detach(void) {
+	secp256k1_stop();
+}
diff --git a/crypto/secp256k1/secp256k1/src/java/org_bitcoin_NativeSecp256k1.h b/crypto/secp256k1/secp256k1/src/java/org_bitcoin_NativeSecp256k1.h
new file mode 100644
index 000000000..d7fb004fa
--- /dev/null
+++ b/crypto/secp256k1/secp256k1/src/java/org_bitcoin_NativeSecp256k1.h
@@ -0,0 +1,21 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class org_bitcoin_NativeSecp256k1 */
+
+#ifndef _Included_org_bitcoin_NativeSecp256k1
+#define _Included_org_bitcoin_NativeSecp256k1
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class:     org_bitcoin_NativeSecp256k1
+ * Method:    secp256k1_ecdsa_verify
+ * Signature: (Ljava/nio/ByteBuffer;)I
+ */
+JNIEXPORT jint JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ecdsa_1verify
+  (JNIEnv *, jclass, jobject);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/crypto/secp256k1/secp256k1/src/num.h b/crypto/secp256k1/secp256k1/src/num.h
new file mode 100644
index 000000000..b2e7462bc
--- /dev/null
+++ b/crypto/secp256k1/secp256k1/src/num.h
@@ -0,0 +1,93 @@
+// Copyright (c) 2013 Pieter Wuille
+// Distributed under the MIT/X11 software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef _SECP256K1_NUM_
+#define _SECP256K1_NUM_
+
+#if defined(USE_NUM_GMP)
+#include "num_gmp.h"
+#elif defined(USE_NUM_OPENSSL)
+#include "num_openssl.h"
+#else
+#error "Please select num implementation"
+#endif
+
+/** Initialize a number. */
+void static secp256k1_num_init(secp256k1_num_t *r);
+
+/** Free a number. */
+void static secp256k1_num_free(secp256k1_num_t *r);
+
+/** Copy a number. */
+void static secp256k1_num_copy(secp256k1_num_t *r, const secp256k1_num_t *a);
+
+/** Convert a number's absolute value to a binary big-endian string.
+ *  There must be enough place. */
+void static secp256k1_num_get_bin(unsigned char *r, unsigned int rlen, const secp256k1_num_t *a);
+
+/** Set a number to the value of a binary big-endian string. */
+void static secp256k1_num_set_bin(secp256k1_num_t *r, const unsigned char *a, unsigned int alen);
+
+/** Set a number equal to a (signed) integer. */
+void static secp256k1_num_set_int(secp256k1_num_t *r, int a);
+
+/** Compute a modular inverse. The input must be less than the modulus. */
+void static secp256k1_num_mod_inverse(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *m);
+
+/** Multiply two numbers modulo another. */
+void static secp256k1_num_mod_mul(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b, const secp256k1_num_t *m);
+
+/** Compare the absolute value of two numbers. */
+int  static secp256k1_num_cmp(const secp256k1_num_t *a, const secp256k1_num_t *b);
+
+/** Add two (signed) numbers. */
+void static secp256k1_num_add(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b);
+
+/** Subtract two (signed) numbers. */
+void static secp256k1_num_sub(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b);
+
+/** Multiply two (signed) numbers. */
+void static secp256k1_num_mul(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b);
+
+/** Divide two (signed) numbers. */
+void static secp256k1_num_div(secp256k1_num_t *r, const secp256k1_num_t *a, const secp256k1_num_t *b);
+
+/** Replace a number by its remainder modulo m. M's sign is ignored. The result is a number between 0 and m-1,
+    even if r was negative. */
+void static secp256k1_num_mod(secp256k1_num_t *r, const secp256k1_num_t *m);
+
+/** Calculate the number of bits in (the absolute value of) a number. */
+int  static secp256k1_num_bits(const secp256k1_num_t *a);
+
+/** Right-shift the passed number by bits bits, and return those bits. */
+int  static secp256k1_num_shift(secp256k1_num_t *r, int bits);
+
+/** Check whether a number is zero. */
+int  static secp256k1_num_is_zero(const secp256k1_num_t *a);
+
+/** Check whether a number is odd. */
+int  static secp256k1_num_is_odd(const secp256k1_num_t *a);
+
+/** Check whether a number is strictly negative. */
+int  static secp256k1_num_is_neg(const secp256k1_num_t *a);
+
+/** Check whether a particular bit is set in a number. */
+int  static secp256k1_num_get_bit(const secp256k1_num_t *a, int pos);
+
+/** Increase a number by 1. */
+void static secp256k1_num_inc(secp256k1_num_t *r);
+
+/** Set a number equal to the value of a hex string (unsigned). */
+void static secp256k1_num_set_hex(secp256k1_num_t *r, const char *a, int alen);
+
+/** Convert (the absolute value of) a number to a hexadecimal string. */
+void static secp256k1_num_get_hex(char *r, int rlen, const secp256k1_num_t *a);
+
+/** Split a number into a low and high part. */
+void static secp256k1_num_split(secp256k1_num_t *rl, secp256k1_num_t *rh, const secp256k1_num_t *a, int bits);
+
+/** Change a number's sign. */
+void static secp256k1_num_negate(secp256k1_num_t *r);
+
+#endif
diff --git a/crypto/secp256k1/secp256k1/src/num_gmp.h b/crypto/secp256k1/secp256k1/src/num_gmp.h
new file mode 100644
index 000000000..960df8605
--- /dev/null
+++ b/crypto/secp256k1/secp256k1/src/num_gmp.h
@@ -0,0 +1,18 @@
+// Copyright (c) 2013 Pieter Wuille
+// Distributed under the MIT/X11 software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef _SECP256K1_NUM_REPR_
+#define _SECP256K1_NUM_REPR_
+
+#include <gmp.h>
+
+#define NUM_LIMBS ((256+GMP_NUMB_BITS-1)/GMP_NUMB_BITS)
+
+typedef struct {
+    mp_limb_t data[2*NUM_LIMBS];
+    int neg;
+    int limbs;
+} secp256k1_num_t;
+
+#endif
diff --git a/crypto/secp256k1/secp256k1/src/num_openssl.h b/crypto/secp256k1/secp256k1/src/num_openssl.h
new file mode 100644
index 000000000..7d03757f6
--- /dev/null
+++ b/crypto/secp256k1/secp256k1/src/num_openssl.h
@@ -0,0 +1,14 @@
+// Copyright (c) 2013 Pieter Wuille
+// Distributed under the MIT/X11 software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef _SECP256K1_NUM_REPR_
+#define _SECP256K1_NUM_REPR_
+
+#include <openssl/bn.h>
+
+typedef struct {
+    BIGNUM bn;
+} secp256k1_num_t;
+
+#endif
diff --git a/crypto/secp256k1/secp256k1/src/secp256k1.c b/crypto/secp256k1/secp256k1/src/secp256k1.c
new file mode 100644
index 000000000..ed8bf2e95
--- /dev/null
+++ b/crypto/secp256k1/secp256k1/src/secp256k1.c
@@ -0,0 +1,269 @@
+// Copyright (c) 2013 Pieter Wuille
+// Distributed under the MIT/X11 software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include "impl/num.h"
+#include "impl/field.h"
+#include "impl/group.h"
+#include "impl/ecmult.h"
+#include "impl/ecdsa.h"
+
+void secp256k1_start(void) {
+    secp256k1_fe_start();
+    secp256k1_ge_start();
+    secp256k1_ecmult_start();
+}
+
+void secp256k1_stop(void) {
+    secp256k1_ecmult_stop();
+    secp256k1_ge_stop();
+    secp256k1_fe_stop();
+}
+
+int secp256k1_ecdsa_verify(const unsigned char *msg, int msglen, const unsigned char *sig, int siglen, const unsigned char *pubkey, int pubkeylen) {
+    int ret = -3;
+    secp256k1_num_t m; 
+    secp256k1_num_init(&m);
+    secp256k1_ecdsa_sig_t s;
+    secp256k1_ecdsa_sig_init(&s);
+    secp256k1_ge_t q;
+    secp256k1_num_set_bin(&m, msg, msglen);
+
+    if (!secp256k1_ecdsa_pubkey_parse(&q, pubkey, pubkeylen)) {
+        ret = -1;
+        goto end;
+    }
+    if (!secp256k1_ecdsa_sig_parse(&s, sig, siglen)) {
+        ret = -2;
+        goto end;
+    }
+    if (!secp256k1_ecdsa_sig_verify(&s, &q, &m)) {
+        ret = 0;
+        goto end;
+    }
+    ret = 1;
+end:
+    secp256k1_ecdsa_sig_free(&s);
+    secp256k1_num_free(&m);
+    return ret;
+}
+
+int secp256k1_ecdsa_sign(const unsigned char *message, int messagelen, unsigned char *signature, int *signaturelen, const unsigned char *seckey, const unsigned char *nonce) {
+    secp256k1_num_t sec, non, msg;
+    secp256k1_num_init(&sec);
+    secp256k1_num_init(&non);
+    secp256k1_num_init(&msg);
+    secp256k1_num_set_bin(&sec, seckey, 32);
+    secp256k1_num_set_bin(&non, nonce, 32);
+    secp256k1_num_set_bin(&msg, message, messagelen);
+    secp256k1_ecdsa_sig_t sig;
+    secp256k1_ecdsa_sig_init(&sig);
+    int ret = secp256k1_ecdsa_sig_sign(&sig, &sec, &msg, &non, NULL);
+    if (ret) {
+        secp256k1_ecdsa_sig_serialize(signature, signaturelen, &sig);
+    }
+    secp256k1_ecdsa_sig_free(&sig);
+    secp256k1_num_free(&msg);
+    secp256k1_num_free(&non);
+    secp256k1_num_free(&sec);
+    return ret;
+}
+
+int secp256k1_ecdsa_sign_compact(const unsigned char *message, int messagelen, unsigned char *sig64, const unsigned char *seckey, const unsigned char *nonce, int *recid) {
+    secp256k1_num_t sec, non, msg;
+    secp256k1_num_init(&sec);
+    secp256k1_num_init(&non);
+    secp256k1_num_init(&msg);
+    secp256k1_num_set_bin(&sec, seckey, 32);
+    secp256k1_num_set_bin(&non, nonce, 32);
+    secp256k1_num_set_bin(&msg, message, messagelen);
+    secp256k1_ecdsa_sig_t sig;
+    secp256k1_ecdsa_sig_init(&sig);
+    int ret = secp256k1_ecdsa_sig_sign(&sig, &sec, &msg, &non, recid);
+    if (ret) {
+        secp256k1_num_get_bin(sig64, 32, &sig.r);
+        secp256k1_num_get_bin(sig64 + 32, 32, &sig.s);
+    }
+    secp256k1_ecdsa_sig_free(&sig);
+    secp256k1_num_free(&msg);
+    secp256k1_num_free(&non);
+    secp256k1_num_free(&sec);
+    return ret;
+}
+
+int secp256k1_ecdsa_recover_compact(const unsigned char *msg, int msglen, const unsigned char *sig64, unsigned char *pubkey, int *pubkeylen, int compressed, int recid) {
+    int ret = 0;
+    secp256k1_num_t m; 
+    secp256k1_num_init(&m);
+    secp256k1_ecdsa_sig_t sig;
+    secp256k1_ecdsa_sig_init(&sig);
+    secp256k1_num_set_bin(&sig.r, sig64, 32);
+    secp256k1_num_set_bin(&sig.s, sig64 + 32, 32);
+    secp256k1_num_set_bin(&m, msg, msglen);
+
+    secp256k1_ge_t q;
+    if (secp256k1_ecdsa_sig_recover(&sig, &q, &m, recid)) {
+        secp256k1_ecdsa_pubkey_serialize(&q, pubkey, pubkeylen, compressed);
+        ret = 1;
+    }
+    secp256k1_ecdsa_sig_free(&sig);
+    secp256k1_num_free(&m);
+    return ret;
+}
+
+int secp256k1_ecdsa_seckey_verify(const unsigned char *seckey) {
+    secp256k1_num_t sec;
+    secp256k1_num_init(&sec);
+    secp256k1_num_set_bin(&sec, seckey, 32);
+    int ret = !secp256k1_num_is_zero(&sec) &&
+              (secp256k1_num_cmp(&sec, &secp256k1_ge_consts->order) < 0);
+    secp256k1_num_free(&sec);
+    return ret;
+}
+
+int secp256k1_ecdsa_pubkey_verify(const unsigned char *pubkey, int pubkeylen) {
+    secp256k1_ge_t q;
+    return secp256k1_ecdsa_pubkey_parse(&q, pubkey, pubkeylen);
+}
+
+int secp256k1_ecdsa_pubkey_create(unsigned char *pubkey, int *pubkeylen, const unsigned char *seckey, int compressed) {
+    secp256k1_num_t sec;
+    secp256k1_num_init(&sec);
+    secp256k1_num_set_bin(&sec, seckey, 32);
+    secp256k1_gej_t pj;
+    secp256k1_ecmult_gen(&pj, &sec);
+    secp256k1_ge_t p;
+    secp256k1_ge_set_gej(&p, &pj);
+    secp256k1_ecdsa_pubkey_serialize(&p, pubkey, pubkeylen, compressed);
+    return 1;
+}
+
+int secp256k1_ecdsa_pubkey_decompress(unsigned char *pubkey, int *pubkeylen) {
+    secp256k1_ge_t p;
+    if (!secp256k1_ecdsa_pubkey_parse(&p, pubkey, *pubkeylen))
+        return 0;
+    secp256k1_ecdsa_pubkey_serialize(&p, pubkey, pubkeylen, 0);
+    return 1;
+}
+
+int secp256k1_ecdsa_privkey_tweak_add(unsigned char *seckey, const unsigned char *tweak) {
+    int ret = 1;
+    secp256k1_num_t term;
+    secp256k1_num_init(&term);
+    secp256k1_num_set_bin(&term, tweak, 32);
+    if (secp256k1_num_cmp(&term, &secp256k1_ge_consts->order) >= 0)
+        ret = 0;
+    secp256k1_num_t sec;
+    secp256k1_num_init(&sec);
+    if (ret) {
+        secp256k1_num_set_bin(&sec, seckey, 32);
+        secp256k1_num_add(&sec, &sec, &term);
+        secp256k1_num_mod(&sec, &secp256k1_ge_consts->order);
+        if (secp256k1_num_is_zero(&sec))
+            ret = 0;
+    }
+    if (ret)
+        secp256k1_num_get_bin(seckey, 32, &sec);
+    secp256k1_num_free(&sec);
+    secp256k1_num_free(&term);
+    return ret;
+}
+
+int secp256k1_ecdsa_pubkey_tweak_add(unsigned char *pubkey, int pubkeylen, const unsigned char *tweak) {
+    int ret = 1;
+    secp256k1_num_t term;
+    secp256k1_num_init(&term);
+    secp256k1_num_set_bin(&term, tweak, 32);
+    if (secp256k1_num_cmp(&term, &secp256k1_ge_consts->order) >= 0)
+        ret = 0;
+    secp256k1_ge_t p;
+    if (ret) {
+        if (!secp256k1_ecdsa_pubkey_parse(&p, pubkey, pubkeylen))
+            ret = 0;
+    }
+    if (ret) {
+        secp256k1_gej_t pt;
+        secp256k1_ecmult_gen(&pt, &term);
+        secp256k1_gej_add_ge(&pt, &pt, &p);
+        if (secp256k1_gej_is_infinity(&pt))
+            ret = 0;
+        secp256k1_ge_set_gej(&p, &pt);
+        int oldlen = pubkeylen;
+        secp256k1_ecdsa_pubkey_serialize(&p, pubkey, &pubkeylen, oldlen <= 33);
+        assert(pubkeylen == oldlen);
+    }
+    secp256k1_num_free(&term);
+    return ret;
+}
+
+int secp256k1_ecdsa_privkey_tweak_mul(unsigned char *seckey, const unsigned char *tweak) {
+    int ret = 1;
+    secp256k1_num_t factor;
+    secp256k1_num_init(&factor);
+    secp256k1_num_set_bin(&factor, tweak, 32);
+    if (secp256k1_num_is_zero(&factor))
+        ret = 0;
+    if (secp256k1_num_cmp(&factor, &secp256k1_ge_consts->order) >= 0)
+        ret = 0;
+    secp256k1_num_t sec;
+    secp256k1_num_init(&sec);
+    if (ret) {
+        secp256k1_num_set_bin(&sec, seckey, 32);
+        secp256k1_num_mod_mul(&sec, &sec, &factor, &secp256k1_ge_consts->order);
+    }
+    if (ret)
+        secp256k1_num_get_bin(seckey, 32, &sec);
+    secp256k1_num_free(&sec);
+    secp256k1_num_free(&factor);
+    return ret;
+}
+
+int secp256k1_ecdsa_pubkey_tweak_mul(unsigned char *pubkey, int pubkeylen, const unsigned char *tweak) {
+    int ret = 1;
+    secp256k1_num_t factor;
+    secp256k1_num_init(&factor);
+    secp256k1_num_set_bin(&factor, tweak, 32);
+    if (secp256k1_num_is_zero(&factor))
+        ret = 0;
+    if (secp256k1_num_cmp(&factor, &secp256k1_ge_consts->order) >= 0)
+        ret = 0;
+    secp256k1_ge_t p;
+    if (ret) {
+        if (!secp256k1_ecdsa_pubkey_parse(&p, pubkey, pubkeylen))
+            ret = 0;
+    }
+    if (ret) {
+        secp256k1_num_t zero;
+        secp256k1_num_init(&zero);
+        secp256k1_num_set_int(&zero, 0);
+        secp256k1_gej_t pt;
+        secp256k1_gej_set_ge(&pt, &p);
+        secp256k1_ecmult(&pt, &pt, &factor, &zero);
+        secp256k1_num_free(&zero);
+        secp256k1_ge_set_gej(&p, &pt);
+        int oldlen = pubkeylen;
+        secp256k1_ecdsa_pubkey_serialize(&p, pubkey, &pubkeylen, oldlen <= 33);
+        assert(pubkeylen == oldlen);
+    }
+    secp256k1_num_free(&factor);
+    return ret;
+}
+
+int secp256k1_ecdsa_privkey_export(const unsigned char *seckey, unsigned char *privkey, int *privkeylen, int compressed) {
+    secp256k1_num_t key;
+    secp256k1_num_init(&key);
+    secp256k1_num_set_bin(&key, seckey, 32);
+    int ret = secp256k1_ecdsa_privkey_serialize(privkey, privkeylen, &key, compressed);
+    secp256k1_num_free(&key);
+    return ret;
+}
+
+int secp256k1_ecdsa_privkey_import(unsigned char *seckey, const unsigned char *privkey, int privkeylen) {
+    secp256k1_num_t key;
+    secp256k1_num_init(&key);
+    int ret = secp256k1_ecdsa_privkey_parse(&key, privkey, privkeylen);
+    if (ret)
+        secp256k1_num_get_bin(seckey, 32, &key);
+    secp256k1_num_free(&key);
+    return ret;
+}
diff --git a/crypto/secp256k1/secp256k1/src/tests.c b/crypto/secp256k1/secp256k1/src/tests.c
new file mode 100644
index 000000000..af7bbaad0
--- /dev/null
+++ b/crypto/secp256k1/secp256k1/src/tests.c
@@ -0,0 +1,465 @@
+// Copyright (c) 2013 Pieter Wuille
+// Distributed under the MIT/X11 software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <assert.h>
+
+#include "impl/num.h"
+#include "impl/field.h"
+#include "impl/group.h"
+#include "impl/ecmult.h"
+#include "impl/ecdsa.h"
+#include "impl/util.h"
+
+#ifdef ENABLE_OPENSSL_TESTS
+#include "openssl/bn.h"
+#include "openssl/ec.h"
+#include "openssl/ecdsa.h"
+#include "openssl/obj_mac.h"
+#endif
+
+static int count = 100;
+
+/***** NUM TESTS *****/
+
+void random_num_negate(secp256k1_num_t *num) {
+    if (secp256k1_rand32() & 1)
+        secp256k1_num_negate(num);
+}
+
+void random_num_order_test(secp256k1_num_t *num) {
+    do {
+        unsigned char b32[32];
+        secp256k1_rand256_test(b32);
+        secp256k1_num_set_bin(num, b32, 32);
+        if (secp256k1_num_is_zero(num))
+            continue;
+        if (secp256k1_num_cmp(num, &secp256k1_ge_consts->order) >= 0)
+            continue;
+        break;
+    } while(1);
+}
+
+void random_num_order(secp256k1_num_t *num) {
+    do {
+        unsigned char b32[32];
+        secp256k1_rand256(b32);
+        secp256k1_num_set_bin(num, b32, 32);
+        if (secp256k1_num_is_zero(num))
+            continue;
+        if (secp256k1_num_cmp(num, &secp256k1_ge_consts->order) >= 0)
+            continue;
+        break;
+    } while(1);
+}
+
+void test_num_copy_inc_cmp() {
+    secp256k1_num_t n1,n2;
+    secp256k1_num_init(&n1);
+    secp256k1_num_init(&n2);
+    random_num_order(&n1);
+    secp256k1_num_copy(&n2, &n1);
+    assert(secp256k1_num_cmp(&n1, &n2) == 0);
+    assert(secp256k1_num_cmp(&n2, &n1) == 0);
+    secp256k1_num_inc(&n2);
+    assert(secp256k1_num_cmp(&n1, &n2) != 0);
+    assert(secp256k1_num_cmp(&n2, &n1) != 0);
+    secp256k1_num_free(&n1);
+    secp256k1_num_free(&n2);
+}
+
+
+void test_num_get_set_hex() {
+    secp256k1_num_t n1,n2;
+    secp256k1_num_init(&n1);
+    secp256k1_num_init(&n2);
+    random_num_order_test(&n1);
+    char c[64];
+    secp256k1_num_get_hex(c, 64, &n1);
+    secp256k1_num_set_hex(&n2, c, 64);
+    assert(secp256k1_num_cmp(&n1, &n2) == 0);
+    for (int i=0; i<64; i++) {
+        // check whether the lower 4 bits correspond to the last hex character
+        int low1 = secp256k1_num_shift(&n1, 4);
+        int lowh = c[63];
+        int low2 = (lowh>>6)*9+(lowh-'0')&15;
+        assert(low1 == low2);
+        // shift bits off the hex representation, and compare
+        memmove(c+1, c, 63);
+        c[0] = '0';
+        secp256k1_num_set_hex(&n2, c, 64);
+        assert(secp256k1_num_cmp(&n1, &n2) == 0);
+    }
+    secp256k1_num_free(&n2);
+    secp256k1_num_free(&n1);
+}
+
+void test_num_get_set_bin() {
+    secp256k1_num_t n1,n2;
+    secp256k1_num_init(&n1);
+    secp256k1_num_init(&n2);
+    random_num_order_test(&n1);
+    unsigned char c[32];
+    secp256k1_num_get_bin(c, 32, &n1);
+    secp256k1_num_set_bin(&n2, c, 32);
+    assert(secp256k1_num_cmp(&n1, &n2) == 0);
+    for (int i=0; i<32; i++) {
+        // check whether the lower 8 bits correspond to the last byte
+        int low1 = secp256k1_num_shift(&n1, 8);
+        int low2 = c[31];
+        assert(low1 == low2);
+        // shift bits off the byte representation, and compare
+        memmove(c+1, c, 31);
+        c[0] = 0;
+        secp256k1_num_set_bin(&n2, c, 32);
+        assert(secp256k1_num_cmp(&n1, &n2) == 0);
+    }
+    secp256k1_num_free(&n2);
+    secp256k1_num_free(&n1);
+}
+
+void run_num_int() {
+    secp256k1_num_t n1;
+    secp256k1_num_init(&n1);
+    for (int i=-255; i<256; i++) {
+        unsigned char c1[3] = {};
+        c1[2] = abs(i);
+        unsigned char c2[3] = {0x11,0x22,0x33};
+        secp256k1_num_set_int(&n1, i);
+        secp256k1_num_get_bin(c2, 3, &n1);
+        assert(memcmp(c1, c2, 3) == 0);
+    }
+    secp256k1_num_free(&n1);
+}
+
+void test_num_negate() {
+    secp256k1_num_t n1;
+    secp256k1_num_t n2;
+    secp256k1_num_init(&n1);
+    secp256k1_num_init(&n2);
+    random_num_order_test(&n1); // n1 = R
+    random_num_negate(&n1);
+    secp256k1_num_copy(&n2, &n1); // n2 = R
+    secp256k1_num_sub(&n1, &n2, &n1); // n1 = n2-n1 = 0
+    assert(secp256k1_num_is_zero(&n1));
+    secp256k1_num_copy(&n1, &n2); // n1 = R
+    secp256k1_num_negate(&n1); // n1 = -R
+    assert(!secp256k1_num_is_zero(&n1));
+    secp256k1_num_add(&n1, &n2, &n1); // n1 = n2+n1 = 0
+    assert(secp256k1_num_is_zero(&n1));
+    secp256k1_num_copy(&n1, &n2); // n1 = R
+    secp256k1_num_negate(&n1); // n1 = -R
+    assert(secp256k1_num_is_neg(&n1) != secp256k1_num_is_neg(&n2));
+    secp256k1_num_negate(&n1); // n1 = R
+    assert(secp256k1_num_cmp(&n1, &n2) == 0);
+    assert(secp256k1_num_is_neg(&n1) == secp256k1_num_is_neg(&n2));
+    secp256k1_num_free(&n2);
+    secp256k1_num_free(&n1);
+}
+
+void test_num_add_sub() {
+    secp256k1_num_t n1;
+    secp256k1_num_t n2;
+    secp256k1_num_init(&n1);
+    secp256k1_num_init(&n2);
+    random_num_order_test(&n1); // n1 = R1
+    random_num_negate(&n1);
+    random_num_order_test(&n2); // n2 = R2
+    random_num_negate(&n2);
+    secp256k1_num_t n1p2, n2p1, n1m2, n2m1;
+    secp256k1_num_init(&n1p2);
+    secp256k1_num_init(&n2p1);
+    secp256k1_num_init(&n1m2);
+    secp256k1_num_init(&n2m1);
+    secp256k1_num_add(&n1p2, &n1, &n2); // n1p2 = R1 + R2
+    secp256k1_num_add(&n2p1, &n2, &n1); // n2p1 = R2 + R1
+    secp256k1_num_sub(&n1m2, &n1, &n2); // n1m2 = R1 - R2
+    secp256k1_num_sub(&n2m1, &n2, &n1); // n2m1 = R2 - R1
+    assert(secp256k1_num_cmp(&n1p2, &n2p1) == 0);
+    assert(secp256k1_num_cmp(&n1p2, &n1m2) != 0);
+    secp256k1_num_negate(&n2m1); // n2m1 = -R2 + R1
+    assert(secp256k1_num_cmp(&n2m1, &n1m2) == 0);
+    assert(secp256k1_num_cmp(&n2m1, &n1) != 0);
+    secp256k1_num_add(&n2m1, &n2m1, &n2); // n2m1 = -R2 + R1 + R2 = R1
+    assert(secp256k1_num_cmp(&n2m1, &n1) == 0);
+    assert(secp256k1_num_cmp(&n2p1, &n1) != 0);
+    secp256k1_num_sub(&n2p1, &n2p1, &n2); // n2p1 = R2 + R1 - R2 = R1
+    assert(secp256k1_num_cmp(&n2p1, &n1) == 0);
+    secp256k1_num_free(&n2m1);
+    secp256k1_num_free(&n1m2);
+    secp256k1_num_free(&n2p1);
+    secp256k1_num_free(&n1p2);
+    secp256k1_num_free(&n2);
+    secp256k1_num_free(&n1);
+}
+
+void run_num_smalltests() {
+    for (int i=0; i<100*count; i++) {
+        test_num_copy_inc_cmp();
+        test_num_get_set_hex();
+        test_num_get_set_bin();
+        test_num_negate();
+        test_num_add_sub();
+    }
+    run_num_int();
+}
+
+void run_ecmult_chain() {
+    // random starting point A (on the curve)
+    secp256k1_fe_t ax; secp256k1_fe_set_hex(&ax, "8b30bbe9ae2a990696b22f670709dff3727fd8bc04d3362c6c7bf458e2846004", 64);
+    secp256k1_fe_t ay; secp256k1_fe_set_hex(&ay, "a357ae915c4a65281309edf20504740f0eb3343990216b4f81063cb65f2f7e0f", 64);
+    secp256k1_gej_t a; secp256k1_gej_set_xy(&a, &ax, &ay);
+    // two random initial factors xn and gn
+    secp256k1_num_t xn;
+    secp256k1_num_init(&xn);
+    secp256k1_num_set_hex(&xn, "84cc5452f7fde1edb4d38a8ce9b1b84ccef31f146e569be9705d357a42985407", 64);
+    secp256k1_num_t gn;
+    secp256k1_num_init(&gn);
+    secp256k1_num_set_hex(&gn, "a1e58d22553dcd42b23980625d4c57a96e9323d42b3152e5ca2c3990edc7c9de", 64);
+    // two small multipliers to be applied to xn and gn in every iteration:
+    secp256k1_num_t xf;
+    secp256k1_num_init(&xf);
+    secp256k1_num_set_hex(&xf, "1337", 4);
+    secp256k1_num_t gf;
+    secp256k1_num_init(&gf);
+    secp256k1_num_set_hex(&gf, "7113", 4);
+    // accumulators with the resulting coefficients to A and G
+    secp256k1_num_t ae;
+    secp256k1_num_init(&ae);
+    secp256k1_num_set_int(&ae, 1);
+    secp256k1_num_t ge;
+    secp256k1_num_init(&ge);
+    secp256k1_num_set_int(&ge, 0);
+    // the point being computed
+    secp256k1_gej_t x = a;
+    const secp256k1_num_t *order = &secp256k1_ge_consts->order;
+    for (int i=0; i<200*count; i++) {
+        // in each iteration, compute X = xn*X + gn*G;
+        secp256k1_ecmult(&x, &x, &xn, &gn);
+        // also compute ae and ge: the actual accumulated factors for A and G
+        // if X was (ae*A+ge*G), xn*X + gn*G results in (xn*ae*A + (xn*ge+gn)*G)
+        secp256k1_num_mod_mul(&ae, &ae, &xn, order);
+        secp256k1_num_mod_mul(&ge, &ge, &xn, order);
+        secp256k1_num_add(&ge, &ge, &gn);
+        secp256k1_num_mod(&ge, order);
+        // modify xn and gn
+        secp256k1_num_mod_mul(&xn, &xn, &xf, order);
+        secp256k1_num_mod_mul(&gn, &gn, &gf, order);
+
+        // verify
+        if (i == 19999) {
+            char res[132]; int resl = 132;
+            secp256k1_gej_get_hex(res, &resl, &x);
+            assert(strcmp(res, "(D6E96687F9B10D092A6F35439D86CEBEA4535D0D409F53586440BD74B933E830,B95CBCA2C77DA786539BE8FD53354D2D3B4F566AE658045407ED6015EE1B2A88)") == 0);
+        }
+    }
+    // redo the computation, but directly with the resulting ae and ge coefficients:
+    secp256k1_gej_t x2; secp256k1_ecmult(&x2, &a, &ae, &ge);
+    char res[132]; int resl = 132;
+    char res2[132]; int resl2 = 132;
+    secp256k1_gej_get_hex(res, &resl, &x);
+    secp256k1_gej_get_hex(res2, &resl2, &x2);
+    assert(strcmp(res, res2) == 0);
+    assert(strlen(res) == 131);
+    secp256k1_num_free(&xn);
+    secp256k1_num_free(&gn);
+    secp256k1_num_free(&xf);
+    secp256k1_num_free(&gf);
+    secp256k1_num_free(&ae);
+    secp256k1_num_free(&ge);
+}
+
+void test_point_times_order(const secp256k1_gej_t *point) {
+    // either the point is not on the curve, or multiplying it by the order results in O
+    if (!secp256k1_gej_is_valid(point))
+        return;
+
+    const secp256k1_num_t *order = &secp256k1_ge_consts->order;
+    secp256k1_num_t zero;
+    secp256k1_num_init(&zero);
+    secp256k1_num_set_int(&zero, 0);
+    secp256k1_gej_t res;
+    secp256k1_ecmult(&res, point, order, order); // calc res = order * point + order * G;
+    assert(secp256k1_gej_is_infinity(&res));
+    secp256k1_num_free(&zero);
+}
+
+void run_point_times_order() {
+    secp256k1_fe_t x; secp256k1_fe_set_hex(&x, "02", 2);
+    for (int i=0; i<500; i++) {
+        secp256k1_ge_t p; secp256k1_ge_set_xo(&p, &x, 1);
+        secp256k1_gej_t j; secp256k1_gej_set_ge(&j, &p);
+        test_point_times_order(&j);
+        secp256k1_fe_sqr(&x, &x);
+    }
+    char c[65]; int cl=65;
+    secp256k1_fe_get_hex(c, &cl, &x);
+    assert(strcmp(c, "7603CB59B0EF6C63FE6084792A0C378CDB3233A80F8A9A09A877DEAD31B38C45") == 0);
+}
+
+void test_wnaf(const secp256k1_num_t *number, int w) {
+    secp256k1_num_t x, two, t;
+    secp256k1_num_init(&x);
+    secp256k1_num_init(&two);
+    secp256k1_num_init(&t);
+    secp256k1_num_set_int(&x, 0);
+    secp256k1_num_set_int(&two, 2);
+    int wnaf[257];
+    int bits = secp256k1_ecmult_wnaf(wnaf, number, w);
+    int zeroes = -1;
+    for (int i=bits-1; i>=0; i--) {
+        secp256k1_num_mul(&x, &x, &two);
+        int v = wnaf[i];
+        if (v) {
+            assert(zeroes == -1 || zeroes >= w-1); // check that distance between non-zero elements is at least w-1
+            zeroes=0;
+            assert((v & 1) == 1); // check non-zero elements are odd
+            assert(v <= (1 << (w-1)) - 1); // check range below
+            assert(v >= -(1 << (w-1)) - 1); // check range above
+        } else {
+            assert(zeroes != -1); // check that no unnecessary zero padding exists
+            zeroes++;
+        }
+        secp256k1_num_set_int(&t, v);
+        secp256k1_num_add(&x, &x, &t);
+    }
+    assert(secp256k1_num_cmp(&x, number) == 0); // check that wnaf represents number
+    secp256k1_num_free(&x);
+    secp256k1_num_free(&two);
+    secp256k1_num_free(&t);
+}
+
+void run_wnaf() {
+    secp256k1_num_t n;
+    secp256k1_num_init(&n);
+    for (int i=0; i<count; i++) {
+        random_num_order(&n);
+        if (i % 1)
+            secp256k1_num_negate(&n);
+        test_wnaf(&n, 4+(i%10));
+    }
+    secp256k1_num_free(&n);
+}
+
+void random_sign(secp256k1_ecdsa_sig_t *sig, const secp256k1_num_t *key, const secp256k1_num_t *msg, int *recid) {
+    secp256k1_num_t nonce;
+    secp256k1_num_init(&nonce);
+    do {
+        random_num_order_test(&nonce);
+    } while(!secp256k1_ecdsa_sig_sign(sig, key, msg, &nonce, recid));
+    secp256k1_num_free(&nonce);
+}
+
+void test_ecdsa_sign_verify() {
+    const secp256k1_ge_consts_t *c = secp256k1_ge_consts;
+    secp256k1_num_t msg, key;
+    secp256k1_num_init(&msg);
+    random_num_order_test(&msg);
+    secp256k1_num_init(&key);
+    random_num_order_test(&key);
+    secp256k1_gej_t pubj; secp256k1_ecmult_gen(&pubj, &key);
+    secp256k1_ge_t pub; secp256k1_ge_set_gej(&pub, &pubj);
+    secp256k1_ecdsa_sig_t sig;
+    secp256k1_ecdsa_sig_init(&sig);
+    random_sign(&sig, &key, &msg, NULL);
+    assert(secp256k1_ecdsa_sig_verify(&sig, &pub, &msg));
+    secp256k1_num_inc(&msg);
+    assert(!secp256k1_ecdsa_sig_verify(&sig, &pub, &msg));
+    secp256k1_ecdsa_sig_free(&sig);
+    secp256k1_num_free(&msg);
+    secp256k1_num_free(&key);
+}
+
+void run_ecdsa_sign_verify() {
+    for (int i=0; i<10*count; i++) {
+        test_ecdsa_sign_verify();
+    }
+}
+
+#ifdef ENABLE_OPENSSL_TESTS
+EC_KEY *get_openssl_key(const secp256k1_num_t *key) {
+    unsigned char privkey[300];
+    int privkeylen;
+    int compr = secp256k1_rand32() & 1;
+    const unsigned char* pbegin = privkey;
+    EC_KEY *ec_key = EC_KEY_new_by_curve_name(NID_secp256k1);
+    assert(secp256k1_ecdsa_privkey_serialize(privkey, &privkeylen, key, compr));
+    assert(d2i_ECPrivateKey(&ec_key, &pbegin, privkeylen));
+    assert(EC_KEY_check_key(ec_key));
+    return ec_key;
+}
+
+void test_ecdsa_openssl() {
+    const secp256k1_ge_consts_t *c = secp256k1_ge_consts;
+    secp256k1_num_t key, msg;
+    secp256k1_num_init(&msg);
+    unsigned char message[32];
+    secp256k1_rand256_test(message);
+    secp256k1_num_set_bin(&msg, message, 32);
+    secp256k1_num_init(&key);
+    random_num_order_test(&key);
+    secp256k1_gej_t qj;
+    secp256k1_ecmult_gen(&qj, &key);
+    secp256k1_ge_t q;
+    secp256k1_ge_set_gej(&q, &qj);
+    EC_KEY *ec_key = get_openssl_key(&key);
+    assert(ec_key);
+    unsigned char signature[80];
+    int sigsize = 80;
+    assert(ECDSA_sign(0, message, sizeof(message), signature, &sigsize, ec_key));
+    secp256k1_ecdsa_sig_t sig;
+    secp256k1_ecdsa_sig_init(&sig);
+    assert(secp256k1_ecdsa_sig_parse(&sig, signature, sigsize));
+    assert(secp256k1_ecdsa_sig_verify(&sig, &q, &msg));
+    secp256k1_num_inc(&sig.r);
+    assert(!secp256k1_ecdsa_sig_verify(&sig, &q, &msg));
+
+    random_sign(&sig, &key, &msg, NULL);
+    sigsize = 80;
+    assert(secp256k1_ecdsa_sig_serialize(signature, &sigsize, &sig));
+    assert(ECDSA_verify(0, message, sizeof(message), signature, sigsize, ec_key) == 1);
+
+    secp256k1_ecdsa_sig_free(&sig);
+    EC_KEY_free(ec_key);
+    secp256k1_num_free(&key);
+    secp256k1_num_free(&msg);
+}
+
+void run_ecdsa_openssl() {
+    for (int i=0; i<10*count; i++) {
+        test_ecdsa_openssl();
+    }
+}
+#endif
+
+int main(int argc, char **argv) {
+    if (argc > 1)
+        count = strtol(argv[1], NULL, 0)*47;
+
+    printf("test count = %i\n", count);
+
+    // initialize
+    secp256k1_fe_start();
+    secp256k1_ge_start();
+    secp256k1_ecmult_start();
+
+    // num tests
+    run_num_smalltests();
+
+    // ecmult tests
+    run_wnaf();
+    run_point_times_order();
+    run_ecmult_chain();
+
+    // ecdsa tests
+    run_ecdsa_sign_verify();
+#ifdef ENABLE_OPENSSL_TESTS
+    run_ecdsa_openssl();
+#endif
+
+    // shutdown
+    secp256k1_ecmult_stop();
+    secp256k1_ge_stop();
+    secp256k1_fe_stop();
+    return 0;
+}
diff --git a/crypto/secp256k1/secp256k1/src/util.h b/crypto/secp256k1/secp256k1/src/util.h
new file mode 100644
index 000000000..357c7e06b
--- /dev/null
+++ b/crypto/secp256k1/secp256k1/src/util.h
@@ -0,0 +1,19 @@
+// Copyright (c) 2013 Pieter Wuille
+// Distributed under the MIT/X11 software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef _SECP256K1_UTIL_H_
+#define _SECP256K1_UTIL_H_
+
+/** Generate a pseudorandom 32-bit number. */
+static uint32_t secp256k1_rand32(void);
+
+/** Generate a pseudorandom 32-byte array. */
+static void secp256k1_rand256(unsigned char *b32);
+
+/** Generate a pseudorandom 32-byte array with long sequences of zero and one bits. */
+static void secp256k1_rand256_test(unsigned char *b32);
+
+#include "impl/util.h"
+
+#endif
-- 
cgit v1.2.3