github.com/luckypickle/go-ethereum-vet@v1.14.2/p2p/enr/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 enr
    18  
    19  import (
    20  	"crypto/ecdsa"
    21  	"fmt"
    22  	"sync"
    23  
    24  	"github.com/luckypickle/go-ethereum-vet/common/math"
    25  	"github.com/luckypickle/go-ethereum-vet/crypto"
    26  	"github.com/luckypickle/go-ethereum-vet/crypto/sha3"
    27  	"github.com/luckypickle/go-ethereum-vet/rlp"
    28  )
    29  
    30  // Registry of known identity schemes.
    31  var schemes sync.Map
    32  
    33  // An IdentityScheme is capable of verifying record signatures and
    34  // deriving node addresses.
    35  type IdentityScheme interface {
    36  	Verify(r *Record, sig []byte) error
    37  	NodeAddr(r *Record) []byte
    38  }
    39  
    40  // RegisterIdentityScheme adds an identity scheme to the global registry.
    41  func RegisterIdentityScheme(name string, scheme IdentityScheme) {
    42  	if _, loaded := schemes.LoadOrStore(name, scheme); loaded {
    43  		panic("identity scheme " + name + " already registered")
    44  	}
    45  }
    46  
    47  // FindIdentityScheme resolves name to an identity scheme in the global registry.
    48  func FindIdentityScheme(name string) IdentityScheme {
    49  	s, ok := schemes.Load(name)
    50  	if !ok {
    51  		return nil
    52  	}
    53  	return s.(IdentityScheme)
    54  }
    55  
    56  // v4ID is the "v4" identity scheme.
    57  type v4ID struct{}
    58  
    59  func init() {
    60  	RegisterIdentityScheme("v4", v4ID{})
    61  }
    62  
    63  // SignV4 signs a record using the v4 scheme.
    64  func SignV4(r *Record, privkey *ecdsa.PrivateKey) error {
    65  	// Copy r to avoid modifying it if signing fails.
    66  	cpy := *r
    67  	cpy.Set(ID("v4"))
    68  	cpy.Set(Secp256k1(privkey.PublicKey))
    69  
    70  	h := sha3.NewKeccak256()
    71  	rlp.Encode(h, cpy.AppendElements(nil))
    72  	sig, err := crypto.Sign(h.Sum(nil), privkey)
    73  	if err != nil {
    74  		return err
    75  	}
    76  	sig = sig[:len(sig)-1] // remove v
    77  	if err = cpy.SetSig("v4", sig); err == nil {
    78  		*r = cpy
    79  	}
    80  	return err
    81  }
    82  
    83  // s256raw is an unparsed secp256k1 public key entry.
    84  type s256raw []byte
    85  
    86  func (s256raw) ENRKey() string { return "secp256k1" }
    87  
    88  func (v4ID) Verify(r *Record, sig []byte) error {
    89  	var entry s256raw
    90  	if err := r.Load(&entry); err != nil {
    91  		return err
    92  	} else if len(entry) != 33 {
    93  		return fmt.Errorf("invalid public key")
    94  	}
    95  
    96  	h := sha3.NewKeccak256()
    97  	rlp.Encode(h, r.AppendElements(nil))
    98  	if !crypto.VerifySignature(entry, h.Sum(nil), sig) {
    99  		return errInvalidSig
   100  	}
   101  	return nil
   102  }
   103  
   104  func (v4ID) NodeAddr(r *Record) []byte {
   105  	var pubkey Secp256k1
   106  	err := r.Load(&pubkey)
   107  	if err != nil {
   108  		return nil
   109  	}
   110  	buf := make([]byte, 64)
   111  	math.ReadBits(pubkey.X, buf[:32])
   112  	math.ReadBits(pubkey.Y, buf[32:])
   113  	return crypto.Keccak256(buf)
   114  }