github.com/sunjiahui/go-ethereum@v1.10.31/p2p/enode/idscheme.go (about)

     1  // Copyright 2018 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-ethereum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package enode
    18  
    19  import (
    20  	"crypto/ecdsa"
    21  	"fmt"
    22  	"io"
    23  
    24  	"github.com/sunjiahui/go-ethereum/common/math"
    25  	"github.com/sunjiahui/go-ethereum/crypto"
    26  	"github.com/sunjiahui/go-ethereum/p2p/enr"
    27  	"github.com/sunjiahui/go-ethereum/rlp"
    28  	"golang.org/x/crypto/sha3"
    29  )
    30  
    31  // ValidSchemes is a List of known secure identity schemes.
    32  var ValidSchemes = enr.SchemeMap{
    33  	"v4": V4ID{},
    34  }
    35  
    36  // ValidSchemesForTesting is a List of identity schemes for testing.
    37  var ValidSchemesForTesting = enr.SchemeMap{
    38  	"v4":   V4ID{},
    39  	"null": NullID{},
    40  }
    41  
    42  // V4ID is the "v4" identity scheme.
    43  type V4ID struct{}
    44  
    45  // SignV4 signs a record using the v4 scheme.
    46  func SignV4(r *enr.Record, privkey *ecdsa.PrivateKey) error {
    47  	// Copy r to avoid modifying it if signing fails.
    48  	cpy := *r
    49  	cpy.Set(enr.ID("v4"))
    50  	cpy.Set(Secp256k1(privkey.PublicKey))
    51  
    52  	h := sha3.NewLegacyKeccak256()
    53  	rlp.Encode(h, cpy.AppendElements(nil))
    54  	sig, err := crypto.Sign(h.Sum(nil), privkey)
    55  	if err != nil {
    56  		return err
    57  	}
    58  	sig = sig[:len(sig)-1] // remove v
    59  	if err = cpy.SetSig(V4ID{}, sig); err == nil {
    60  		*r = cpy
    61  	}
    62  	return err
    63  }
    64  
    65  func (V4ID) Verify(r *enr.Record, sig []byte) error {
    66  	var entry s256raw
    67  	if err := r.Load(&entry); err != nil {
    68  		return err
    69  	} else if len(entry) != 33 {
    70  		return fmt.Errorf("invalid public key")
    71  	}
    72  
    73  	h := sha3.NewLegacyKeccak256()
    74  	rlp.Encode(h, r.AppendElements(nil))
    75  	if !crypto.VerifySignature(entry, h.Sum(nil), sig) {
    76  		return enr.ErrInvalidSig
    77  	}
    78  	return nil
    79  }
    80  
    81  func (V4ID) NodeAddr(r *enr.Record) []byte {
    82  	var pubkey Secp256k1
    83  	err := r.Load(&pubkey)
    84  	if err != nil {
    85  		return nil
    86  	}
    87  	buf := make([]byte, 64)
    88  	math.ReadBits(pubkey.X, buf[:32])
    89  	math.ReadBits(pubkey.Y, buf[32:])
    90  	return crypto.Keccak256(buf)
    91  }
    92  
    93  // Secp256k1 is the "secp256k1" key, which holds a public key.
    94  type Secp256k1 ecdsa.PublicKey
    95  
    96  func (v Secp256k1) ENRKey() string { return "secp256k1" }
    97  
    98  // EncodeRLP implements rlp.Encoder.
    99  func (v Secp256k1) EncodeRLP(w io.Writer) error {
   100  	return rlp.Encode(w, crypto.CompressPubkey((*ecdsa.PublicKey)(&v)))
   101  }
   102  
   103  // DecodeRLP implements rlp.Decoder.
   104  func (v *Secp256k1) DecodeRLP(s *rlp.Stream) error {
   105  	buf, err := s.Bytes()
   106  	if err != nil {
   107  		return err
   108  	}
   109  	pk, err := crypto.DecompressPubkey(buf)
   110  	if err != nil {
   111  		return err
   112  	}
   113  	*v = (Secp256k1)(*pk)
   114  	return nil
   115  }
   116  
   117  // s256raw is an unparsed secp256k1 public key entry.
   118  type s256raw []byte
   119  
   120  func (s256raw) ENRKey() string { return "secp256k1" }
   121  
   122  // v4CompatID is a weaker and insecure version of the "v4" scheme which only checks for the
   123  // presence of a secp256k1 public key, but doesn't verify the signature.
   124  type v4CompatID struct {
   125  	V4ID
   126  }
   127  
   128  func (v4CompatID) Verify(r *enr.Record, sig []byte) error {
   129  	var pubkey Secp256k1
   130  	return r.Load(&pubkey)
   131  }
   132  
   133  func signV4Compat(r *enr.Record, pubkey *ecdsa.PublicKey) {
   134  	r.Set((*Secp256k1)(pubkey))
   135  	if err := r.SetSig(v4CompatID{}, []byte{}); err != nil {
   136  		panic(err)
   137  	}
   138  }
   139  
   140  // NullID is the "null" ENR identity scheme. This scheme stores the node
   141  // ID in the record without any signature.
   142  type NullID struct{}
   143  
   144  func (NullID) Verify(r *enr.Record, sig []byte) error {
   145  	return nil
   146  }
   147  
   148  func (NullID) NodeAddr(r *enr.Record) []byte {
   149  	var id ID
   150  	r.Load(enr.WithEntry("nulladdr", &id))
   151  	return id[:]
   152  }
   153  
   154  func SignNull(r *enr.Record, id ID) *Node {
   155  	r.Set(enr.ID("null"))
   156  	r.Set(enr.WithEntry("nulladdr", id))
   157  	if err := r.SetSig(NullID{}, []byte{}); err != nil {
   158  		panic(err)
   159  	}
   160  	return &Node{r: *r, id: id}
   161  }