github.com/core-coin/go-core/v2@v2.1.9/p2p/enode/idscheme.go (about)

     1  // Copyright 2018 by the Authors
     2  // This file is part of the go-core library.
     3  //
     4  // The go-core 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-core 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-core library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package enode
    18  
    19  import (
    20  	"fmt"
    21  	"io"
    22  
    23  	"golang.org/x/crypto/sha3"
    24  
    25  	"github.com/core-coin/go-core/v2/crypto"
    26  	"github.com/core-coin/go-core/v2/p2p/enr"
    27  	"github.com/core-coin/go-core/v2/rlp"
    28  )
    29  
    30  // List of known secure identity schemes.
    31  var ValidSchemes = enr.SchemeMap{
    32  	"v4": V4ID{},
    33  }
    34  
    35  var ValidSchemesForTesting = enr.SchemeMap{
    36  	"v4":   V4ID{},
    37  	"null": NullID{},
    38  }
    39  
    40  // v4ID is the "v4" identity scheme.
    41  type V4ID struct{}
    42  
    43  // SignV4 signs a record using the v4 scheme.
    44  func SignV4(r *enr.Record, privkey *crypto.PrivateKey) error {
    45  	// Copy r to avoid modifying it if signing fails.
    46  	cpy := *r
    47  	cpy.Set(enr.ID("v4"))
    48  	cpy.Set(Ed448(*privkey.PublicKey()))
    49  
    50  	h := sha3.New256()
    51  	err := rlp.Encode(h, cpy.AppendElements(nil))
    52  	if err != nil {
    53  		return err
    54  	}
    55  
    56  	sig, err := crypto.Sign(h.Sum(nil), privkey)
    57  	if err != nil {
    58  		return err
    59  	}
    60  	if err = cpy.SetSig(V4ID{}, sig); err == nil {
    61  		*r = cpy
    62  	}
    63  	return err
    64  }
    65  
    66  func (V4ID) Verify(r *enr.Record, sig []byte) error {
    67  	var entry ed448raw
    68  	if err := r.Load(&entry); err != nil {
    69  		return err
    70  	} else if len(entry) != 57 {
    71  		return fmt.Errorf("invalid public key")
    72  	}
    73  
    74  	h := sha3.New256()
    75  	err := rlp.Encode(h, r.AppendElements(nil))
    76  	if err != nil {
    77  		return err
    78  	}
    79  
    80  	if !crypto.VerifySignature(entry, h.Sum(nil), sig) {
    81  		return enr.ErrInvalidSig
    82  	}
    83  	return nil
    84  }
    85  
    86  func (V4ID) NodeAddr(r *enr.Record) []byte {
    87  	var pubkey Ed448
    88  	err := r.Load(&pubkey)
    89  	if err != nil {
    90  		return nil
    91  	}
    92  	return crypto.SHA3(pubkey[:])
    93  }
    94  
    95  // Ed448 is the "ed448" key, which holds a public key.
    96  type Ed448 crypto.PublicKey
    97  
    98  func (v Ed448) ENRKey() string { return "secp256k1" }
    99  
   100  // EncodeRLP implements rlp.Encoder.
   101  func (v Ed448) EncodeRLP(w io.Writer) error {
   102  	return rlp.Encode(w, (*crypto.PublicKey)(&v))
   103  }
   104  
   105  // DecodeRLP implements rlp.Decoder.
   106  func (v *Ed448) DecodeRLP(s *rlp.Stream) error {
   107  	buf, err := s.Bytes()
   108  	if err != nil {
   109  		return err
   110  	}
   111  	pk, err := crypto.UnmarshalPubKey(buf)
   112  	if err != nil {
   113  		return err
   114  	}
   115  	*v = (Ed448)(*pk)
   116  	return nil
   117  }
   118  
   119  // ed448raw is an unparsed ed448 public key entry.
   120  type ed448raw []byte
   121  
   122  func (ed448raw) ENRKey() string { return "secp256k1" }
   123  
   124  // v4CompatID is a weaker and insecure version of the "v4" scheme which only checks for the
   125  // presence of a ed448 public key, but doesn't verify the signature.
   126  type v4CompatID struct {
   127  	V4ID
   128  }
   129  
   130  func (v4CompatID) Verify(r *enr.Record, sig []byte) error {
   131  	var pubkey Ed448
   132  	return r.Load(&pubkey)
   133  }
   134  
   135  func signV4Compat(r *enr.Record, pubkey *crypto.PublicKey) {
   136  	r.Set((*Ed448)(pubkey))
   137  	if err := r.SetSig(v4CompatID{}, []byte{}); err != nil {
   138  		panic(err)
   139  	}
   140  }
   141  
   142  // NullID is the "null" ENR identity scheme. This scheme stores the node
   143  // ID in the record without any signature.
   144  type NullID struct{}
   145  
   146  func (NullID) Verify(r *enr.Record, sig []byte) error {
   147  	return nil
   148  }
   149  
   150  func (NullID) NodeAddr(r *enr.Record) []byte {
   151  	var id ID
   152  	r.Load(enr.WithEntry("nulladdr", &id))
   153  	return id[:]
   154  }
   155  
   156  func SignNull(r *enr.Record, id ID) *Node {
   157  	r.Set(enr.ID("null"))
   158  	r.Set(enr.WithEntry("nulladdr", id))
   159  	if err := r.SetSig(NullID{}, []byte{}); err != nil {
   160  		panic(err)
   161  	}
   162  	return &Node{r: *r, id: id}
   163  }