瀏覽代碼

Add EC signature validations before call to libsecp256k1

Gustav Simonsson 10 年之前
父節點
當前提交
32e1b104f8
共有 3 個文件被更改,包括 29 次插入22 次删除
  1. 0 6
      core/transaction_pool.go
  2. 15 16
      core/types/transaction.go
  3. 14 0
      crypto/crypto.go

+ 0 - 6
core/transaction_pool.go

@@ -112,12 +112,6 @@ func (pool *TxPool) ValidateTransaction(tx *types.Transaction) error {
 		return ErrInvalidSender
 	}
 
-	// Validate curve param
-	v, _, _ := tx.Curve()
-	if v > 28 || v < 27 {
-		return fmt.Errorf("tx.v != (28 || 27) => %v", v)
-	}
-
 	if !pool.currentState().HasAccount(from) {
 		return ErrNonExistentAccount
 	}

+ 15 - 16
core/types/transaction.go

@@ -8,7 +8,6 @@ import (
 
 	"github.com/ethereum/go-ethereum/common"
 	"github.com/ethereum/go-ethereum/crypto"
-	"github.com/ethereum/go-ethereum/crypto/secp256k1"
 	"github.com/ethereum/go-ethereum/logger"
 	"github.com/ethereum/go-ethereum/logger/glog"
 	"github.com/ethereum/go-ethereum/rlp"
@@ -93,9 +92,9 @@ func (self *Transaction) SetNonce(AccountNonce uint64) {
 }
 
 func (self *Transaction) From() (common.Address, error) {
-	pubkey := self.PublicKey()
-	if len(pubkey) == 0 || pubkey[0] != 4 {
-		return common.Address{}, errors.New("invalid public key")
+	pubkey, err := self.PublicKey()
+	if err != nil {
+		return common.Address{}, err
 	}
 
 	var addr common.Address
@@ -110,34 +109,34 @@ func (tx *Transaction) To() *common.Address {
 	return tx.Recipient
 }
 
-func (tx *Transaction) Curve() (v byte, r []byte, s []byte) {
+func (tx *Transaction) GetSignatureValues() (v byte, r []byte, s []byte) {
 	v = byte(tx.V)
 	r = common.LeftPadBytes(tx.R.Bytes(), 32)
 	s = common.LeftPadBytes(tx.S.Bytes(), 32)
 	return
 }
 
-func (tx *Transaction) Signature(key []byte) []byte {
-	hash := tx.Hash()
-	sig, _ := secp256k1.Sign(hash[:], key)
-	return sig
-}
+func (tx *Transaction) PublicKey() ([]byte, error) {
+	if !crypto.ValidateSignatureValues(tx.V, tx.R, tx.S) {
+		return nil, errors.New("invalid v, r, s values")
+	}
 
-func (tx *Transaction) PublicKey() []byte {
 	hash := tx.Hash()
-	v, r, s := tx.Curve()
+	v, r, s := tx.GetSignatureValues()
 	sig := append(r, s...)
 	sig = append(sig, v-27)
 
-	//pubkey := crypto.Ecrecover(append(hash[:], sig...))
-	//pubkey, _ := secp256k1.RecoverPubkey(hash[:], sig)
 	p, err := crypto.SigToPub(hash[:], sig)
 	if err != nil {
 		glog.V(logger.Error).Infof("Could not get pubkey from signature: ", err)
-		return nil
+		return nil, err
 	}
+
 	pubkey := crypto.FromECDSAPub(p)
-	return pubkey
+	if len(pubkey) == 0 || pubkey[0] != 4 {
+		return nil, errors.New("invalid public key")
+	}
+	return pubkey, nil
 }
 
 func (tx *Transaction) SetSignatureValues(sig []byte) error {

+ 14 - 0
crypto/crypto.go

@@ -10,6 +10,7 @@ import (
 	"fmt"
 	"io"
 	"io/ioutil"
+	"math/big"
 	"os"
 
 	"encoding/hex"
@@ -151,6 +152,19 @@ func GenerateKey() (*ecdsa.PrivateKey, error) {
 	return ecdsa.GenerateKey(S256(), rand.Reader)
 }
 
+func ValidateSignatureValues(v byte, r, s *big.Int) bool {
+	secp256k1n := common.String2Big("0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141")
+	vint := uint32(v)
+	if r.Cmp(common.Big0) == 0 || s.Cmp(common.Big0) == 0 {
+		return false
+	}
+	if r.Cmp(secp256k1n) < 0 && s.Cmp(secp256k1n) < 0 && (vint == 27 || vint == 28) {
+		return true
+	} else {
+		return false
+	}
+}
+
 func SigToPub(hash, sig []byte) (*ecdsa.PublicKey, error) {
 	s, err := Ecrecover(hash, sig)
 	if err != nil {