p2p/enr: avoid using btcec directly

This commit is contained in:
Felix Lange 2017-12-19 13:35:03 +01:00
parent dd97fb7bd5
commit 08cdd66304
3 changed files with 28 additions and 50 deletions

View file

@ -33,11 +33,8 @@ import (
"errors" "errors"
"fmt" "fmt"
"io" "io"
"math/big"
"sort" "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"
"github.com/ethereum/go-ethereum/crypto/sha3" "github.com/ethereum/go-ethereum/crypto/sha3"
"github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rlp"
@ -206,25 +203,27 @@ func (r *Record) DecodeRLP(s *rlp.Stream) error {
return nil 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 // NodeAddr returns the node address. The return value will be nil if the record is
// unsigned. // unsigned.
func (r *Record) NodeAddr() []byte { func (r *Record) NodeAddr() []byte {
var secp256k1 Secp256k1 var key s256raw
if r.Load(&secp256k1) != nil { if r.Load(&key) != nil {
return nil return nil
} }
pk := btcec.PublicKey(secp256k1) return crypto.Keccak256(key)
return crypto.Keccak256(pk.SerializeCompressed())
} }
// Sign signs the record with the given private key. It updates the record's identity // 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 // scheme, public key and increments the sequence number. Sign returns an error if the
// encoded record is larger than the size limit. // encoded record is larger than the size limit.
func (r *Record) Sign(privkey *ecdsa.PrivateKey) error { func (r *Record) Sign(privkey *ecdsa.PrivateKey) error {
pk := (*btcec.PublicKey)(&privkey.PublicKey)
r.seq = r.seq + 1 r.seq = r.seq + 1
r.Set(ID_SECP256k1_KECCAK) r.Set(ID_SECP256k1_KECCAK)
r.Set(Secp256k1(*pk)) r.Set(Secp256k1(privkey.PublicKey))
return r.signAndEncode(privkey) return r.signAndEncode(privkey)
} }
@ -244,14 +243,14 @@ func (r *Record) signAndEncode(privkey *ecdsa.PrivateKey) error {
// Sign the tail of the list. // Sign the tail of the list.
h := sha3.NewKeccak256() h := sha3.NewKeccak256()
rlp.Encode(h, list[1:]) 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 { if err != nil {
return err return err
} }
sig = sig[:len(sig)-1] // remove v
// Put signature in front. // Put signature in front.
r.signature = encodeCompactSignature(sig) r.signature, list[0] = sig, sig
list[0] = r.signature
r.raw, err = rlp.EncodeToBytes(list) r.raw, err = rlp.EncodeToBytes(list)
if err != nil { if err != nil {
return err return err
@ -265,18 +264,16 @@ func (r *Record) signAndEncode(privkey *ecdsa.PrivateKey) error {
func (r *Record) verifySignature() error { func (r *Record) verifySignature() error {
// Get identity scheme, public key, signature. // Get identity scheme, public key, signature.
var id ID var id ID
var secp256k1 Secp256k1 var key s256raw
if err := r.Load(&id); err != nil { if err := r.Load(&id); err != nil {
return err return err
} else if id != ID_SECP256k1_KECCAK { } else if id != ID_SECP256k1_KECCAK {
return errNoID return errNoID
} }
if err := r.Load(&secp256k1); err != nil { if err := r.Load(&key); err != nil {
return err
}
sig, err := parseCompactSignature(r.signature)
if err != nil {
return err return err
} else if len(key) != 33 {
return fmt.Errorf("invalid public key")
} }
// Verify the signature. // Verify the signature.
@ -284,22 +281,11 @@ func (r *Record) verifySignature() error {
list = r.appendPairs(list) list = r.appendPairs(list)
h := sha3.NewKeccak256() h := sha3.NewKeccak256()
rlp.Encode(h, list) 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 errInvalidSig
} }
return nil 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
}

View file

@ -24,7 +24,6 @@ import (
"testing" "testing"
"time" "time"
"github.com/btcsuite/btcd/btcec"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rlp"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
@ -32,10 +31,8 @@ import (
) )
var ( var (
privkeyHex = "b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291" privkey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
privkey, _ = crypto.HexToECDSA(privkeyHex) pubkey = &privkey.PublicKey
pubkeyBytes, _ = hex.DecodeString("03ca634cae0d49acb401d8a4c6b6fe8c55b70d115bf400769cc1400f3258cd3138")
pubkey, _ = btcec.ParsePubKey(pubkeyBytes, btcec.S256())
) )
var rnd = rand.New(rand.NewSource(time.Now().UnixNano())) var rnd = rand.New(rand.NewSource(time.Now().UnixNano()))

View file

@ -22,7 +22,7 @@ import (
"io" "io"
"net" "net"
"github.com/btcsuite/btcd/btcec" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rlp"
) )
@ -121,25 +121,20 @@ func (v Secp256k1) ENRKey() string { return "secp256k1" }
// EncodeRLP implements rlp.Encoder. // EncodeRLP implements rlp.Encoder.
func (v Secp256k1) EncodeRLP(w io.Writer) error { func (v Secp256k1) EncodeRLP(w io.Writer) error {
pk := btcec.PublicKey(v) return rlp.Encode(w, crypto.CompressPubkey((*ecdsa.PublicKey)(&v)))
return rlp.Encode(w, pk.SerializeCompressed())
} }
// DecodeRLP implements rlp.Decoder. // DecodeRLP implements rlp.Decoder.
func (v *Secp256k1) DecodeRLP(s *rlp.Stream) error { func (v *Secp256k1) DecodeRLP(s *rlp.Stream) error {
buf := make([]byte, 33) buf, err := s.Bytes()
if err := s.Decode(&buf); err != nil { if err != nil {
return err return err
} }
pk, err := crypto.DecompressPubkey(buf)
pk, err := btcec.ParsePubKey(buf, btcec.S256())
if err != nil { if err != nil {
return err return err
} }
*v = (Secp256k1)(*pk) *v = (Secp256k1)(*pk)
return nil return nil
} }