From 32e1b104f8fbc0f80bf2b6a93492aa01fa323e35 Mon Sep 17 00:00:00 2001 From: Gustav Simonsson Date: Mon, 1 Jun 2015 20:27:20 +0200 Subject: [PATCH] Add EC signature validations before call to libsecp256k1 --- core/transaction_pool.go | 6 ------ core/types/transaction.go | 31 +++++++++++++++---------------- crypto/crypto.go | 14 ++++++++++++++ 3 files changed, 29 insertions(+), 22 deletions(-) diff --git a/core/transaction_pool.go b/core/transaction_pool.go index c896488d1..ee6360614 100644 --- a/core/transaction_pool.go +++ b/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 } diff --git a/core/types/transaction.go b/core/types/transaction.go index d8dcd7424..3d6d31ae7 100644 --- a/core/types/transaction.go +++ b/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 { diff --git a/crypto/crypto.go b/crypto/crypto.go index 4bbd62f7f..d5291fe1d 100644 --- a/crypto/crypto.go +++ b/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 {