From 08cdd66304fcae178bf5cbb68dcf4320b9c514ea Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Tue, 19 Dec 2017 13:35:03 +0100 Subject: [PATCH] p2p/enr: avoid using btcec directly --- p2p/enr/enr.go | 52 +++++++++++++++++---------------------------- p2p/enr/enr_test.go | 7 ++---- p2p/enr/keys.go | 19 ++++++----------- 3 files changed, 28 insertions(+), 50 deletions(-) diff --git a/p2p/enr/enr.go b/p2p/enr/enr.go index 5340e86138..472c5eafd9 100644 --- a/p2p/enr/enr.go +++ b/p2p/enr/enr.go @@ -33,11 +33,8 @@ import ( "errors" "fmt" "io" - "math/big" "sort" - "github.com/btcsuite/btcd/btcec" - "github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto/sha3" "github.com/ethereum/go-ethereum/rlp" @@ -206,25 +203,27 @@ func (r *Record) DecodeRLP(s *rlp.Stream) error { return nil } +type s256raw []byte + +func (s256raw) ENRKey() string { return "secp256k1" } + // NodeAddr returns the node address. The return value will be nil if the record is // unsigned. func (r *Record) NodeAddr() []byte { - var secp256k1 Secp256k1 - if r.Load(&secp256k1) != nil { + var key s256raw + if r.Load(&key) != nil { return nil } - pk := btcec.PublicKey(secp256k1) - return crypto.Keccak256(pk.SerializeCompressed()) + return crypto.Keccak256(key) } // Sign signs the record with the given private key. It updates the record's identity // scheme, public key and increments the sequence number. Sign returns an error if the // encoded record is larger than the size limit. func (r *Record) Sign(privkey *ecdsa.PrivateKey) error { - pk := (*btcec.PublicKey)(&privkey.PublicKey) r.seq = r.seq + 1 r.Set(ID_SECP256k1_KECCAK) - r.Set(Secp256k1(*pk)) + r.Set(Secp256k1(privkey.PublicKey)) return r.signAndEncode(privkey) } @@ -244,14 +243,14 @@ func (r *Record) signAndEncode(privkey *ecdsa.PrivateKey) error { // Sign the tail of the list. h := sha3.NewKeccak256() rlp.Encode(h, list[1:]) - sig, err := (*btcec.PrivateKey)(privkey).Sign(h.Sum(nil)) + sig, err := crypto.Sign(h.Sum(nil), privkey) if err != nil { return err } + sig = sig[:len(sig)-1] // remove v // Put signature in front. - r.signature = encodeCompactSignature(sig) - list[0] = r.signature + r.signature, list[0] = sig, sig r.raw, err = rlp.EncodeToBytes(list) if err != nil { return err @@ -265,18 +264,16 @@ func (r *Record) signAndEncode(privkey *ecdsa.PrivateKey) error { func (r *Record) verifySignature() error { // Get identity scheme, public key, signature. var id ID - var secp256k1 Secp256k1 + var key s256raw if err := r.Load(&id); err != nil { return err } else if id != ID_SECP256k1_KECCAK { return errNoID } - if err := r.Load(&secp256k1); err != nil { - return err - } - sig, err := parseCompactSignature(r.signature) - if err != nil { + if err := r.Load(&key); err != nil { return err + } else if len(key) != 33 { + return fmt.Errorf("invalid public key") } // Verify the signature. @@ -284,22 +281,11 @@ func (r *Record) verifySignature() error { list = r.appendPairs(list) h := sha3.NewKeccak256() rlp.Encode(h, list) - if !sig.Verify(h.Sum(nil), (*btcec.PublicKey)(&secp256k1)) { + fmt.Printf("sig: %x\n", r.signature) + fmt.Printf("key: %x\n", key) + fmt.Printf("hash: %x\n", h.Sum(nil)) + if !crypto.VerifySignature(key, h.Sum(nil), r.signature) { return errInvalidSig } return nil } - -func encodeCompactSignature(sig *btcec.Signature) []byte { - b := make([]byte, 64) - math.ReadBits(sig.R, b[:32]) - math.ReadBits(sig.S, b[32:]) - return b -} - -func parseCompactSignature(sig []byte) (*btcec.Signature, error) { - if len(sig) != 64 { - return nil, errInvalidSigsize - } - return &btcec.Signature{R: new(big.Int).SetBytes(sig[:32]), S: new(big.Int).SetBytes(sig[32:])}, nil -} diff --git a/p2p/enr/enr_test.go b/p2p/enr/enr_test.go index 07a6494765..ad4df05f00 100644 --- a/p2p/enr/enr_test.go +++ b/p2p/enr/enr_test.go @@ -24,7 +24,6 @@ import ( "testing" "time" - "github.com/btcsuite/btcd/btcec" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/rlp" "github.com/stretchr/testify/assert" @@ -32,10 +31,8 @@ import ( ) var ( - privkeyHex = "b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291" - privkey, _ = crypto.HexToECDSA(privkeyHex) - pubkeyBytes, _ = hex.DecodeString("03ca634cae0d49acb401d8a4c6b6fe8c55b70d115bf400769cc1400f3258cd3138") - pubkey, _ = btcec.ParsePubKey(pubkeyBytes, btcec.S256()) + privkey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") + pubkey = &privkey.PublicKey ) var rnd = rand.New(rand.NewSource(time.Now().UnixNano())) diff --git a/p2p/enr/keys.go b/p2p/enr/keys.go index 12bf6d8fb0..556f8cab2b 100644 --- a/p2p/enr/keys.go +++ b/p2p/enr/keys.go @@ -22,7 +22,7 @@ import ( "io" "net" - "github.com/btcsuite/btcd/btcec" + "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/rlp" ) @@ -121,25 +121,20 @@ func (v Secp256k1) ENRKey() string { return "secp256k1" } // EncodeRLP implements rlp.Encoder. func (v Secp256k1) EncodeRLP(w io.Writer) error { - pk := btcec.PublicKey(v) - - return rlp.Encode(w, pk.SerializeCompressed()) + return rlp.Encode(w, crypto.CompressPubkey((*ecdsa.PublicKey)(&v))) } // DecodeRLP implements rlp.Decoder. func (v *Secp256k1) DecodeRLP(s *rlp.Stream) error { - buf := make([]byte, 33) - if err := s.Decode(&buf); err != nil { - return err - } - - pk, err := btcec.ParsePubKey(buf, btcec.S256()) + buf, err := s.Bytes() + if err != nil { + return err + } + pk, err := crypto.DecompressPubkey(buf) if err != nil { return err } - *v = (Secp256k1)(*pk) - return nil }