浏览代码

crypto: add DecompressPubkey, VerifySignature (#15615)

We need those operations for p2p/enr.

Also upgrade github.com/btcsuite/btcd/btcec to the latest version
and improve BenchmarkSha3. The benchmark printed extra output 
that confused tools like benchstat and ignored N.
Felix Lange 8 年之前
父节点
当前提交
e85b68ef53

+ 1 - 7
crypto/crypto_test.go

@@ -20,12 +20,10 @@ import (
 	"bytes"
 	"crypto/ecdsa"
 	"encoding/hex"
-	"fmt"
 	"io/ioutil"
 	"math/big"
 	"os"
 	"testing"
-	"time"
 
 	"github.com/ethereum/go-ethereum/common"
 )
@@ -44,13 +42,9 @@ func TestKeccak256Hash(t *testing.T) {
 
 func BenchmarkSha3(b *testing.B) {
 	a := []byte("hello world")
-	amount := 1000000
-	start := time.Now()
-	for i := 0; i < amount; i++ {
+	for i := 0; i < b.N; i++ {
 		Keccak256(a)
 	}
-
-	fmt.Println(amount, ":", time.Since(start))
 }
 
 func TestSign(t *testing.T) {

+ 49 - 0
crypto/secp256k1/ext.h

@@ -46,6 +46,55 @@ static int secp256k1_ecdsa_recover_pubkey(
 	return secp256k1_ec_pubkey_serialize(ctx, pubkey_out, &outputlen, &pubkey, SECP256K1_EC_UNCOMPRESSED);
 }
 
+// secp256k1_ecdsa_verify_enc verifies an encoded compact signature.
+//
+// Returns: 1: signature is valid
+//          0: signature is invalid
+// Args:    ctx:        pointer to a context object (cannot be NULL)
+//  In:     sigdata:    pointer to a 64-byte signature (cannot be NULL)
+//          msgdata:    pointer to a 32-byte message (cannot be NULL)
+//          pubkeydata: pointer to public key data (cannot be NULL)
+//          pubkeylen:  length of pubkeydata
+static int secp256k1_ecdsa_verify_enc(
+	const secp256k1_context* ctx,
+	const unsigned char *sigdata,
+	const unsigned char *msgdata,
+	const unsigned char *pubkeydata,
+	size_t pubkeylen
+) {
+	secp256k1_ecdsa_signature sig;
+	secp256k1_pubkey pubkey;
+
+	if (!secp256k1_ecdsa_signature_parse_compact(ctx, &sig, sigdata)) {
+		return 0;
+	}
+	if (!secp256k1_ec_pubkey_parse(ctx, &pubkey, pubkeydata, pubkeylen)) {
+		return 0;
+	}
+	return secp256k1_ecdsa_verify(ctx, &sig, msgdata, &pubkey);
+}
+
+// secp256k1_decompress_pubkey decompresses a public key.
+//
+// Returns: 1: public key is valid
+//          0: public key is invalid
+// Args:    ctx:        pointer to a context object (cannot be NULL)
+//  Out:    pubkey_out: the serialized 65-byte public key (cannot be NULL)
+//  In:     pubkeydata: pointer to 33 bytes of compressed public key data (cannot be NULL)
+static int secp256k1_decompress_pubkey(
+	const secp256k1_context* ctx,
+	unsigned char *pubkey_out,
+	const unsigned char *pubkeydata
+) {
+	secp256k1_pubkey pubkey;
+
+	if (!secp256k1_ec_pubkey_parse(ctx, &pubkey, pubkeydata, 33)) {
+		return 0;
+	}
+	size_t outputlen = 65;
+	return secp256k1_ec_pubkey_serialize(ctx, pubkey_out, &outputlen, &pubkey, SECP256K1_EC_UNCOMPRESSED);
+}
+
 // secp256k1_pubkey_scalar_mul multiplies a point by a scalar in constant time.
 //
 // Returns: 1: multiplication was successful

+ 29 - 0
crypto/secp256k1/secp256.go

@@ -38,6 +38,7 @@ import "C"
 
 import (
 	"errors"
+	"math/big"
 	"unsafe"
 )
 
@@ -55,6 +56,7 @@ var (
 	ErrInvalidSignatureLen = errors.New("invalid signature length")
 	ErrInvalidRecoveryID   = errors.New("invalid signature recovery id")
 	ErrInvalidKey          = errors.New("invalid private key")
+	ErrInvalidPubkey       = errors.New("invalid public key")
 	ErrSignFailed          = errors.New("signing failed")
 	ErrRecoverFailed       = errors.New("recovery failed")
 )
@@ -119,6 +121,33 @@ func RecoverPubkey(msg []byte, sig []byte) ([]byte, error) {
 	return pubkey, nil
 }
 
+// VerifySignature checks that the given pubkey created signature over message.
+// The signature should be in [R || S] format.
+func VerifySignature(pubkey, msg, signature []byte) bool {
+	if len(msg) != 32 || len(signature) != 64 || len(pubkey) == 0 {
+		return false
+	}
+	sigdata := (*C.uchar)(unsafe.Pointer(&signature[0]))
+	msgdata := (*C.uchar)(unsafe.Pointer(&msg[0]))
+	keydata := (*C.uchar)(unsafe.Pointer(&pubkey[0]))
+	return C.secp256k1_ecdsa_verify_enc(context, sigdata, msgdata, keydata, C.size_t(len(pubkey))) != 0
+}
+
+// DecompressPubkey parses a public key in the 33-byte compressed format.
+// It returns non-nil coordinates if the public key is valid.
+func DecompressPubkey(pubkey []byte) (X, Y *big.Int) {
+	if len(pubkey) != 33 {
+		return nil, nil
+	}
+	buf := make([]byte, 65)
+	bufdata := (*C.uchar)(unsafe.Pointer(&buf[0]))
+	pubkeydata := (*C.uchar)(unsafe.Pointer(&pubkey[0]))
+	if C.secp256k1_decompress_pubkey(context, bufdata, pubkeydata) == 0 {
+		return nil, nil
+	}
+	return new(big.Int).SetBytes(buf[1:33]), new(big.Int).SetBytes(buf[33:])
+}
+
 func checkSignature(sig []byte) error {
 	if len(sig) != 65 {
 		return ErrInvalidSignatureLen

+ 18 - 0
crypto/signature_cgo.go

@@ -27,10 +27,12 @@ import (
 	"github.com/ethereum/go-ethereum/crypto/secp256k1"
 )
 
+// Ecrecover returns the uncompressed public key that created the given signature.
 func Ecrecover(hash, sig []byte) ([]byte, error) {
 	return secp256k1.RecoverPubkey(hash, sig)
 }
 
+// SigToPub returns the public key that created the given signature.
 func SigToPub(hash, sig []byte) (*ecdsa.PublicKey, error) {
 	s, err := Ecrecover(hash, sig)
 	if err != nil {
@@ -58,6 +60,22 @@ func Sign(hash []byte, prv *ecdsa.PrivateKey) (sig []byte, err error) {
 	return secp256k1.Sign(hash, seckey)
 }
 
+// VerifySignature checks that the given public key created signature over hash.
+// The public key should be in compressed (33 bytes) or uncompressed (65 bytes) format.
+// The signature should have the 64 byte [R || S] format.
+func VerifySignature(pubkey, hash, signature []byte) bool {
+	return secp256k1.VerifySignature(pubkey, hash, signature)
+}
+
+// DecompressPubkey parses a public key in the 33-byte compressed format.
+func DecompressPubkey(pubkey []byte) (*ecdsa.PublicKey, error) {
+	x, y := secp256k1.DecompressPubkey(pubkey)
+	if x == nil {
+		return nil, fmt.Errorf("invalid public key")
+	}
+	return &ecdsa.PublicKey{X: x, Y: y, Curve: S256()}, nil
+}
+
 // S256 returns an instance of the secp256k1 curve.
 func S256() elliptic.Curve {
 	return secp256k1.S256()

+ 31 - 0
crypto/signature_nocgo.go

@@ -21,11 +21,14 @@ package crypto
 import (
 	"crypto/ecdsa"
 	"crypto/elliptic"
+	"errors"
 	"fmt"
+	"math/big"
 
 	"github.com/btcsuite/btcd/btcec"
 )
 
+// Ecrecover returns the uncompressed public key that created the given signature.
 func Ecrecover(hash, sig []byte) ([]byte, error) {
 	pub, err := SigToPub(hash, sig)
 	if err != nil {
@@ -35,6 +38,7 @@ func Ecrecover(hash, sig []byte) ([]byte, error) {
 	return bytes, err
 }
 
+// SigToPub returns the public key that created the given signature.
 func SigToPub(hash, sig []byte) (*ecdsa.PublicKey, error) {
 	// Convert to btcec input format with 'recovery id' v at the beginning.
 	btcsig := make([]byte, 65)
@@ -71,6 +75,33 @@ func Sign(hash []byte, prv *ecdsa.PrivateKey) ([]byte, error) {
 	return sig, nil
 }
 
+// VerifySignature checks that the given public key created signature over hash.
+// The public key should be in compressed (33 bytes) or uncompressed (65 bytes) format.
+// The signature should have the 64 byte [R || S] format.
+func VerifySignature(pubkey, hash, signature []byte) bool {
+	if len(signature) != 64 {
+		return false
+	}
+	sig := &btcec.Signature{R: new(big.Int).SetBytes(signature[:32]), S: new(big.Int).SetBytes(signature[32:])}
+	key, err := btcec.ParsePubKey(pubkey, btcec.S256())
+	if err != nil {
+		return false
+	}
+	return sig.Verify(hash, key)
+}
+
+// DecompressPubkey parses a public key in the 33-byte compressed format.
+func DecompressPubkey(pubkey []byte) (*ecdsa.PublicKey, error) {
+	if len(pubkey) != 33 {
+		return nil, errors.New("invalid compressed public key length")
+	}
+	key, err := btcec.ParsePubKey(pubkey, btcec.S256())
+	if err != nil {
+		return nil, err
+	}
+	return key.ToECDSA(), nil
+}
+
 // S256 returns an instance of the secp256k1 curve.
 func S256() elliptic.Curve {
 	return btcec.S256()

+ 84 - 8
crypto/signature_test.go

@@ -18,19 +18,95 @@ package crypto
 
 import (
 	"bytes"
-	"encoding/hex"
 	"testing"
+
+	"github.com/ethereum/go-ethereum/common"
+	"github.com/ethereum/go-ethereum/common/hexutil"
+)
+
+var (
+	testmsg     = hexutil.MustDecode("0xce0677bb30baa8cf067c88db9811f4333d131bf8bcf12fe7065d211dce971008")
+	testsig     = hexutil.MustDecode("0x90f27b8b488db00b00606796d2987f6a5f59ae62ea05effe84fef5b8b0e549984a691139ad57a3f0b906637673aa2f63d1f55cb1a69199d4009eea23ceaddc9301")
+	testpubkey  = hexutil.MustDecode("0x04e32df42865e97135acfb65f3bae71bdc86f4d49150ad6a440b6f15878109880a0a2b2667f7e725ceea70c673093bf67663e0312623c8e091b13cf2c0f11ef652")
+	testpubkeyc = hexutil.MustDecode("0x02e32df42865e97135acfb65f3bae71bdc86f4d49150ad6a440b6f15878109880a")
 )
 
-func TestRecoverSanity(t *testing.T) {
-	msg, _ := hex.DecodeString("ce0677bb30baa8cf067c88db9811f4333d131bf8bcf12fe7065d211dce971008")
-	sig, _ := hex.DecodeString("90f27b8b488db00b00606796d2987f6a5f59ae62ea05effe84fef5b8b0e549984a691139ad57a3f0b906637673aa2f63d1f55cb1a69199d4009eea23ceaddc9301")
-	pubkey1, _ := hex.DecodeString("04e32df42865e97135acfb65f3bae71bdc86f4d49150ad6a440b6f15878109880a0a2b2667f7e725ceea70c673093bf67663e0312623c8e091b13cf2c0f11ef652")
-	pubkey2, err := Ecrecover(msg, sig)
+func TestEcrecover(t *testing.T) {
+	pubkey, err := Ecrecover(testmsg, testsig)
 	if err != nil {
 		t.Fatalf("recover error: %s", err)
 	}
-	if !bytes.Equal(pubkey1, pubkey2) {
-		t.Errorf("pubkey mismatch: want: %x have: %x", pubkey1, pubkey2)
+	if !bytes.Equal(pubkey, testpubkey) {
+		t.Errorf("pubkey mismatch: want: %x have: %x", testpubkey, pubkey)
+	}
+}
+
+func TestVerifySignature(t *testing.T) {
+	sig := testsig[:len(testsig)-1] // remove recovery id
+	if !VerifySignature(testpubkey, testmsg, sig) {
+		t.Errorf("can't verify signature with uncompressed key")
+	}
+	if !VerifySignature(testpubkeyc, testmsg, sig) {
+		t.Errorf("can't verify signature with compressed key")
+	}
+
+	if VerifySignature(nil, testmsg, sig) {
+		t.Errorf("signature valid with no key")
+	}
+	if VerifySignature(testpubkey, nil, sig) {
+		t.Errorf("signature valid with no message")
+	}
+	if VerifySignature(testpubkey, testmsg, nil) {
+		t.Errorf("nil signature valid")
+	}
+	if VerifySignature(testpubkey, testmsg, append(common.CopyBytes(sig), 1, 2, 3)) {
+		t.Errorf("signature valid with extra bytes at the end")
+	}
+	if VerifySignature(testpubkey, testmsg, sig[:len(sig)-2]) {
+		t.Errorf("signature valid even though it's incomplete")
+	}
+}
+
+func TestDecompressPubkey(t *testing.T) {
+	key, err := DecompressPubkey(testpubkeyc)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if uncompressed := FromECDSAPub(key); !bytes.Equal(uncompressed, testpubkey) {
+		t.Errorf("wrong public key result: got %x, want %x", uncompressed, testpubkey)
+	}
+	if _, err := DecompressPubkey(nil); err == nil {
+		t.Errorf("no error for nil pubkey")
+	}
+	if _, err := DecompressPubkey(testpubkeyc[:5]); err == nil {
+		t.Errorf("no error for incomplete pubkey")
+	}
+	if _, err := DecompressPubkey(append(common.CopyBytes(testpubkeyc), 1, 2, 3)); err == nil {
+		t.Errorf("no error for pubkey with extra bytes at the end")
+	}
+}
+
+func BenchmarkEcrecoverSignature(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		if _, err := Ecrecover(testmsg, testsig); err != nil {
+			b.Fatal("ecrecover error", err)
+		}
+	}
+}
+
+func BenchmarkVerifySignature(b *testing.B) {
+	sig := testsig[:len(testsig)-1] // remove recovery id
+	for i := 0; i < b.N; i++ {
+		if !VerifySignature(testpubkey, testmsg, sig) {
+			b.Fatal("verify error")
+		}
+	}
+}
+
+func BenchmarkDecompressPubkey(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		if _, err := DecompressPubkey(testpubkeyc); err != nil {
+			b.Fatal(err)
+		}
 	}
 }

+ 7 - 13
vendor/github.com/btcsuite/btcd/btcec/README.md

@@ -1,11 +1,9 @@
 btcec
 =====
 
-[![Build Status](https://travis-ci.org/btcsuite/btcd.png?branch=master)]
-(https://travis-ci.org/btcsuite/btcec) [![ISC License]
-(http://img.shields.io/badge/license-ISC-blue.svg)](http://copyfree.org)
-[![GoDoc](https://godoc.org/github.com/btcsuite/btcd/btcec?status.png)]
-(http://godoc.org/github.com/btcsuite/btcd/btcec)
+[![Build Status](https://travis-ci.org/btcsuite/btcd.png?branch=master)](https://travis-ci.org/btcsuite/btcec)
+[![ISC License](http://img.shields.io/badge/license-ISC-blue.svg)](http://copyfree.org)
+[![GoDoc](https://godoc.org/github.com/btcsuite/btcd/btcec?status.png)](http://godoc.org/github.com/btcsuite/btcd/btcec)
 
 Package btcec implements elliptic curve cryptography needed for working with
 Bitcoin (secp256k1 only for now). It is designed so that it may be used with the
@@ -27,23 +25,19 @@ $ go get -u github.com/btcsuite/btcd/btcec
 
 ## Examples
 
-* [Sign Message]
-  (http://godoc.org/github.com/btcsuite/btcd/btcec#example-package--SignMessage)  
+* [Sign Message](http://godoc.org/github.com/btcsuite/btcd/btcec#example-package--SignMessage)  
   Demonstrates signing a message with a secp256k1 private key that is first
   parsed form raw bytes and serializing the generated signature.
 
-* [Verify Signature]
-  (http://godoc.org/github.com/btcsuite/btcd/btcec#example-package--VerifySignature)  
+* [Verify Signature](http://godoc.org/github.com/btcsuite/btcd/btcec#example-package--VerifySignature)  
   Demonstrates verifying a secp256k1 signature against a public key that is
   first parsed from raw bytes.  The signature is also parsed from raw bytes.
 
-* [Encryption]
-  (http://godoc.org/github.com/btcsuite/btcd/btcec#example-package--EncryptMessage)
+* [Encryption](http://godoc.org/github.com/btcsuite/btcd/btcec#example-package--EncryptMessage)
   Demonstrates encrypting a message for a public key that is first parsed from
   raw bytes, then decrypting it using the corresponding private key.
 
-* [Decryption]
-  (http://godoc.org/github.com/btcsuite/btcd/btcec#example-package--DecryptMessage)
+* [Decryption](http://godoc.org/github.com/btcsuite/btcd/btcec#example-package--DecryptMessage)
   Demonstrates decrypting a message using a private key that is first parsed
   from raw bytes.
 

+ 7 - 5
vendor/github.com/btcsuite/btcd/btcec/btcec.go

@@ -36,8 +36,9 @@ var (
 // interface from crypto/elliptic.
 type KoblitzCurve struct {
 	*elliptic.CurveParams
-	q *big.Int
-	H int // cofactor of the curve.
+	q         *big.Int
+	H         int      // cofactor of the curve.
+	halfOrder *big.Int // half the order N
 
 	// byteSize is simply the bit size / 8 and is provided for convenience
 	// since it is calculated repeatedly.
@@ -747,9 +748,9 @@ func NAF(k []byte) ([]byte, []byte) {
 	}
 	if carry {
 		retPos[0] = 1
+		return retPos, retNeg
 	}
-
-	return retPos, retNeg
+	return retPos[1:], retNeg[1:]
 }
 
 // ScalarMult returns k*(Bx, By) where k is a big endian integer.
@@ -912,9 +913,10 @@ func initS256() {
 	secp256k1.Gx = fromHex("79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798")
 	secp256k1.Gy = fromHex("483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8")
 	secp256k1.BitSize = 256
-	secp256k1.H = 1
 	secp256k1.q = new(big.Int).Div(new(big.Int).Add(secp256k1.P,
 		big.NewInt(1)), big.NewInt(4))
+	secp256k1.H = 1
+	secp256k1.halfOrder = new(big.Int).Rsh(secp256k1.N, 1)
 
 	// Provided for convenience since this gets computed repeatedly.
 	secp256k1.byteSize = secp256k1.BitSize / 8

+ 82 - 121
vendor/github.com/btcsuite/btcd/btcec/field.go

@@ -100,10 +100,6 @@ const (
 	// fieldPrimeWordOne is word one of the secp256k1 prime in the
 	// internal field representation.  It is used during negation.
 	fieldPrimeWordOne = 0x3ffffbf
-
-	// primeLowBits is the lower 2*fieldBase bits of the secp256k1 prime in
-	// its standard normalized form.  It is used during modular reduction.
-	primeLowBits = 0xffffefffffc2f
 )
 
 // fieldVal implements optimized fixed-precision arithmetic over the
@@ -250,39 +246,15 @@ func (f *fieldVal) SetHex(hexString string) *fieldVal {
 // performs fast modular reduction over the secp256k1 prime by making use of the
 // special form of the prime.
 func (f *fieldVal) Normalize() *fieldVal {
-	// The field representation leaves 6 bits of overflow in each
-	// word so intermediate calculations can be performed without needing
-	// to propagate the carry to each higher word during the calculations.
-	// In order to normalize, first we need to "compact" the full 256-bit
-	// value to the right and treat the additional 64 leftmost bits as
-	// the magnitude.
-	m := f.n[0]
-	t0 := m & fieldBaseMask
-	m = (m >> fieldBase) + f.n[1]
-	t1 := m & fieldBaseMask
-	m = (m >> fieldBase) + f.n[2]
-	t2 := m & fieldBaseMask
-	m = (m >> fieldBase) + f.n[3]
-	t3 := m & fieldBaseMask
-	m = (m >> fieldBase) + f.n[4]
-	t4 := m & fieldBaseMask
-	m = (m >> fieldBase) + f.n[5]
-	t5 := m & fieldBaseMask
-	m = (m >> fieldBase) + f.n[6]
-	t6 := m & fieldBaseMask
-	m = (m >> fieldBase) + f.n[7]
-	t7 := m & fieldBaseMask
-	m = (m >> fieldBase) + f.n[8]
-	t8 := m & fieldBaseMask
-	m = (m >> fieldBase) + f.n[9]
-	t9 := m & fieldMSBMask
-	m = m >> fieldMSBBits
-
-	// At this point, if the magnitude is greater than 0, the overall value
-	// is greater than the max possible 256-bit value.  In particular, it is
-	// "how many times larger" than the max value it is.  Since this field
-	// is doing arithmetic modulo the secp256k1 prime, we need to perform
-	// modular reduction over the prime.
+	// The field representation leaves 6 bits of overflow in each word so
+	// intermediate calculations can be performed without needing to
+	// propagate the carry to each higher word during the calculations.  In
+	// order to normalize, we need to "compact" the full 256-bit value to
+	// the right while propagating any carries through to the high order
+	// word.
+	//
+	// Since this field is doing arithmetic modulo the secp256k1 prime, we
+	// also need to perform modular reduction over the prime.
 	//
 	// Per [HAC] section 14.3.4: Reduction method of moduli of special form,
 	// when the modulus is of the special form m = b^t - c, highly efficient
@@ -298,98 +270,87 @@ func (f *fieldVal) Normalize() *fieldVal {
 	//
 	// The algorithm presented in the referenced section typically repeats
 	// until the quotient is zero.  However, due to our field representation
-	// we already know at least how many times we would need to repeat as
-	// it's the value currently in m.  Thus we can simply multiply the
-	// magnitude by the field representation of the prime and do a single
-	// iteration.  Notice that nothing will be changed when the magnitude is
-	// zero, so we could skip this in that case, however always running
-	// regardless allows it to run in constant time.
-	r := t0 + m*977
-	t0 = r & fieldBaseMask
-	r = (r >> fieldBase) + t1 + m*64
-	t1 = r & fieldBaseMask
-	r = (r >> fieldBase) + t2
-	t2 = r & fieldBaseMask
-	r = (r >> fieldBase) + t3
-	t3 = r & fieldBaseMask
-	r = (r >> fieldBase) + t4
-	t4 = r & fieldBaseMask
-	r = (r >> fieldBase) + t5
-	t5 = r & fieldBaseMask
-	r = (r >> fieldBase) + t6
-	t6 = r & fieldBaseMask
-	r = (r >> fieldBase) + t7
-	t7 = r & fieldBaseMask
-	r = (r >> fieldBase) + t8
-	t8 = r & fieldBaseMask
-	r = (r >> fieldBase) + t9
-	t9 = r & fieldMSBMask
-
-	// At this point, the result will be in the range 0 <= result <=
-	// prime + (2^64 - c).  Therefore, one more subtraction of the prime
-	// might be needed if the current result is greater than or equal to the
-	// prime.  The following does the final reduction in constant time.
-	// Note that the if/else here intentionally does the bitwise OR with
-	// zero even though it won't change the value to ensure constant time
-	// between the branches.
-	var mask int32
-	lowBits := uint64(t1)<<fieldBase | uint64(t0)
-	if lowBits < primeLowBits {
-		mask |= -1
-	} else {
-		mask |= 0
-	}
-	if t2 < fieldBaseMask {
-		mask |= -1
-	} else {
-		mask |= 0
-	}
-	if t3 < fieldBaseMask {
-		mask |= -1
-	} else {
-		mask |= 0
-	}
-	if t4 < fieldBaseMask {
-		mask |= -1
-	} else {
-		mask |= 0
-	}
-	if t5 < fieldBaseMask {
-		mask |= -1
-	} else {
-		mask |= 0
-	}
-	if t6 < fieldBaseMask {
-		mask |= -1
+	// we already know to within one reduction how many times we would need
+	// to repeat as it's the uppermost bits of the high order word.  Thus we
+	// can simply multiply the magnitude by the field representation of the
+	// prime and do a single iteration.  After this step there might be an
+	// additional carry to bit 256 (bit 22 of the high order word).
+	t9 := f.n[9]
+	m := t9 >> fieldMSBBits
+	t9 = t9 & fieldMSBMask
+	t0 := f.n[0] + m*977
+	t1 := (t0 >> fieldBase) + f.n[1] + (m << 6)
+	t0 = t0 & fieldBaseMask
+	t2 := (t1 >> fieldBase) + f.n[2]
+	t1 = t1 & fieldBaseMask
+	t3 := (t2 >> fieldBase) + f.n[3]
+	t2 = t2 & fieldBaseMask
+	t4 := (t3 >> fieldBase) + f.n[4]
+	t3 = t3 & fieldBaseMask
+	t5 := (t4 >> fieldBase) + f.n[5]
+	t4 = t4 & fieldBaseMask
+	t6 := (t5 >> fieldBase) + f.n[6]
+	t5 = t5 & fieldBaseMask
+	t7 := (t6 >> fieldBase) + f.n[7]
+	t6 = t6 & fieldBaseMask
+	t8 := (t7 >> fieldBase) + f.n[8]
+	t7 = t7 & fieldBaseMask
+	t9 = (t8 >> fieldBase) + t9
+	t8 = t8 & fieldBaseMask
+
+	// At this point, the magnitude is guaranteed to be one, however, the
+	// value could still be greater than the prime if there was either a
+	// carry through to bit 256 (bit 22 of the higher order word) or the
+	// value is greater than or equal to the field characteristic.  The
+	// following determines if either or these conditions are true and does
+	// the final reduction in constant time.
+	//
+	// Note that the if/else statements here intentionally do the bitwise
+	// operators even when it won't change the value to ensure constant time
+	// between the branches.  Also note that 'm' will be zero when neither
+	// of the aforementioned conditions are true and the value will not be
+	// changed when 'm' is zero.
+	m = 1
+	if t9 == fieldMSBMask {
+		m &= 1
 	} else {
-		mask |= 0
+		m &= 0
 	}
-	if t7 < fieldBaseMask {
-		mask |= -1
+	if t2&t3&t4&t5&t6&t7&t8 == fieldBaseMask {
+		m &= 1
 	} else {
-		mask |= 0
+		m &= 0
 	}
-	if t8 < fieldBaseMask {
-		mask |= -1
+	if ((t0+977)>>fieldBase + t1 + 64) > fieldBaseMask {
+		m &= 1
 	} else {
-		mask |= 0
+		m &= 0
 	}
-	if t9 < fieldMSBMask {
-		mask |= -1
+	if t9>>fieldMSBBits != 0 {
+		m |= 1
 	} else {
-		mask |= 0
+		m |= 0
 	}
-	lowBits -= ^uint64(mask) & primeLowBits
-	t0 = uint32(lowBits & fieldBaseMask)
-	t1 = uint32((lowBits >> fieldBase) & fieldBaseMask)
-	t2 = t2 & uint32(mask)
-	t3 = t3 & uint32(mask)
-	t4 = t4 & uint32(mask)
-	t5 = t5 & uint32(mask)
-	t6 = t6 & uint32(mask)
-	t7 = t7 & uint32(mask)
-	t8 = t8 & uint32(mask)
-	t9 = t9 & uint32(mask)
+	t0 = t0 + m*977
+	t1 = (t0 >> fieldBase) + t1 + (m << 6)
+	t0 = t0 & fieldBaseMask
+	t2 = (t1 >> fieldBase) + t2
+	t1 = t1 & fieldBaseMask
+	t3 = (t2 >> fieldBase) + t3
+	t2 = t2 & fieldBaseMask
+	t4 = (t3 >> fieldBase) + t4
+	t3 = t3 & fieldBaseMask
+	t5 = (t4 >> fieldBase) + t5
+	t4 = t4 & fieldBaseMask
+	t6 = (t5 >> fieldBase) + t6
+	t5 = t5 & fieldBaseMask
+	t7 = (t6 >> fieldBase) + t7
+	t6 = t6 & fieldBaseMask
+	t8 = (t7 >> fieldBase) + t8
+	t7 = t7 & fieldBaseMask
+	t9 = (t8 >> fieldBase) + t9
+	t8 = t8 & fieldBaseMask
+	t9 = t9 & fieldMSBMask // Remove potential multiple of 2^256.
 
 	// Finally, set the normalized and reduced words.
 	f.n[0] = t0

+ 0 - 63
vendor/github.com/btcsuite/btcd/btcec/genprecomps.go

@@ -1,63 +0,0 @@
-// Copyright 2015 The btcsuite developers
-// Use of this source code is governed by an ISC
-// license that can be found in the LICENSE file.
-
-// This file is ignored during the regular build due to the following build tag.
-// It is called by go generate and used to automatically generate pre-computed
-// tables used to accelerate operations.
-// +build ignore
-
-package main
-
-import (
-	"bytes"
-	"compress/zlib"
-	"encoding/base64"
-	"fmt"
-	"log"
-	"os"
-
-	"github.com/btcsuite/btcd/btcec"
-)
-
-func main() {
-	fi, err := os.Create("secp256k1.go")
-	if err != nil {
-		log.Fatal(err)
-	}
-	defer fi.Close()
-
-	// Compress the serialized byte points.
-	serialized := btcec.S256().SerializedBytePoints()
-	var compressed bytes.Buffer
-	w := zlib.NewWriter(&compressed)
-	if _, err := w.Write(serialized); err != nil {
-		fmt.Println(err)
-		os.Exit(1)
-	}
-	w.Close()
-
-	// Encode the compressed byte points with base64.
-	encoded := make([]byte, base64.StdEncoding.EncodedLen(compressed.Len()))
-	base64.StdEncoding.Encode(encoded, compressed.Bytes())
-
-	fmt.Fprintln(fi, "// Copyright (c) 2015 The btcsuite developers")
-	fmt.Fprintln(fi, "// Use of this source code is governed by an ISC")
-	fmt.Fprintln(fi, "// license that can be found in the LICENSE file.")
-	fmt.Fprintln(fi)
-	fmt.Fprintln(fi, "package btcec")
-	fmt.Fprintln(fi)
-	fmt.Fprintln(fi, "// Auto-generated file (see genprecomps.go)")
-	fmt.Fprintln(fi, "// DO NOT EDIT")
-	fmt.Fprintln(fi)
-	fmt.Fprintf(fi, "var secp256k1BytePoints = %q\n", string(encoded))
-
-	a1, b1, a2, b2 := btcec.S256().EndomorphismVectors()
-	fmt.Println("The following values are the computed linearly " +
-		"independent vectors needed to make use of the secp256k1 " +
-		"endomorphism:")
-	fmt.Printf("a1: %x\n", a1)
-	fmt.Printf("b1: %x\n", b1)
-	fmt.Printf("a2: %x\n", a2)
-	fmt.Printf("b2: %x\n", b2)
-}

+ 9 - 0
vendor/github.com/btcsuite/btcd/btcec/pubkey.go

@@ -54,6 +54,15 @@ const (
 	pubkeyHybrid       byte = 0x6 // y_bit + x coord + y coord
 )
 
+// IsCompressedPubKey returns true the the passed serialized public key has
+// been encoded in compressed format, and false otherwise.
+func IsCompressedPubKey(pubKey []byte) bool {
+	// The public key is only compressed if it is the correct length and
+	// the format (first byte) is one of the compressed pubkey values.
+	return len(pubKey) == PubKeyBytesLenCompressed &&
+		(pubKey[0]&^byte(0x1) == pubkeyCompressed)
+}
+
 // ParsePubKey parses a public key for a koblitz curve from a bytestring into a
 // ecdsa.Publickey, verifying that it is valid. It supports compressed,
 // uncompressed and hybrid signature formats.

文件差异内容过多而无法显示
+ 0 - 0
vendor/github.com/btcsuite/btcd/btcec/secp256k1.go


+ 6 - 9
vendor/github.com/btcsuite/btcd/btcec/signature.go

@@ -29,10 +29,6 @@ type Signature struct {
 }
 
 var (
-	// Curve order and halforder, used to tame ECDSA malleability (see BIP-0062)
-	order     = new(big.Int).Set(S256().N)
-	halforder = new(big.Int).Rsh(order, 1)
-
 	// Used in RFC6979 implementation when testing the nonce for correctness
 	one = big.NewInt(1)
 
@@ -51,8 +47,8 @@ var (
 func (sig *Signature) Serialize() []byte {
 	// low 'S' malleability breaker
 	sigS := sig.S
-	if sigS.Cmp(halforder) == 1 {
-		sigS = new(big.Int).Sub(order, sigS)
+	if sigS.Cmp(S256().halfOrder) == 1 {
+		sigS = new(big.Int).Sub(S256().N, sigS)
 	}
 	// Ensure the encoded bytes for the r and s values are canonical and
 	// thus suitable for DER encoding.
@@ -62,7 +58,7 @@ func (sig *Signature) Serialize() []byte {
 	// total length of returned signature is 1 byte for each magic and
 	// length (6 total), plus lengths of r and s
 	length := 6 + len(rb) + len(sb)
-	b := make([]byte, length, length)
+	b := make([]byte, length)
 
 	b[0] = 0x30
 	b[1] = byte(length - 2)
@@ -420,7 +416,8 @@ func RecoverCompact(curve *KoblitzCurve, signature,
 func signRFC6979(privateKey *PrivateKey, hash []byte) (*Signature, error) {
 
 	privkey := privateKey.ToECDSA()
-	N := order
+	N := S256().N
+	halfOrder := S256().halfOrder
 	k := nonceRFC6979(privkey.D, hash)
 	inv := new(big.Int).ModInverse(k, N)
 	r, _ := privkey.Curve.ScalarBaseMult(k.Bytes())
@@ -438,7 +435,7 @@ func signRFC6979(privateKey *PrivateKey, hash []byte) (*Signature, error) {
 	s.Mul(s, inv)
 	s.Mod(s, N)
 
-	if s.Cmp(halforder) == 1 {
+	if s.Cmp(halfOrder) == 1 {
 		s.Sub(N, s)
 	}
 	if s.Sign() == 0 {

+ 3 - 3
vendor/vendor.json

@@ -51,10 +51,10 @@
 			"revisionTime": "2017-02-10T01:56:32Z"
 		},
 		{
-			"checksumSHA1": "fIpm6Vr5a8kgr22gWkQx7vKUTyU=",
+			"checksumSHA1": "gZQ6HheWahvZzIc3phBnOwoWHjE=",
 			"path": "github.com/btcsuite/btcd/btcec",
-			"revision": "d06c0bb181529331be8f8d9350288c420d9e60e4",
-			"revisionTime": "2017-02-01T21:25:25Z"
+			"revision": "2e60448ffcc6bf78332d1fe590260095f554dd78",
+			"revisionTime": "2017-11-28T15:02:46Z"
 		},
 		{
 			"checksumSHA1": "cDMtzKmdTx4CcIpP4broa+16X9g=",

部分文件因为文件数量过多而无法显示