github.com/annchain/OG@v0.0.9/p2p/onode/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 onode
    18  
    19  import (
    20  	"crypto/ecdsa"
    21  	"fmt"
    22  	"github.com/annchain/OG/common/math"
    23  	ogcrypto2 "github.com/annchain/OG/deprecated/ogcrypto"
    24  	"github.com/annchain/OG/p2p/enr"
    25  	"github.com/annchain/OG/types/msg"
    26  	"golang.org/x/crypto/sha3"
    27  )
    28  
    29  //go:generate msgp
    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 *ecdsa.PrivateKey) error {
    45  	// Copy r to avoid modifying it if signing fails.
    46  	cpy := *r
    47  	id := enr.ID("v4")
    48  	cpy.Set(&id)
    49  	key := Secp256k1(privkey.PublicKey)
    50  	cpy.Set(&key)
    51  
    52  	h := sha3.NewLegacyKeccak256()
    53  	list := msg.Messages(cpy.AppendElements(nil))
    54  	data, _ := list.MarshalMsg(nil)
    55  	h.Write(data)
    56  	sig, err := ogcrypto2.Sign(h.Sum(nil), privkey)
    57  	if err != nil {
    58  		return err
    59  	}
    60  	sig = sig[:len(sig)-1] // remove v
    61  	if err = cpy.SetSig(V4ID{}, sig); err == nil {
    62  		*r = cpy
    63  	}
    64  	return err
    65  }
    66  
    67  func (V4ID) Verify(r *enr.Record, sig []byte) error {
    68  	var entry S256raw
    69  	if err := r.Load(&entry); err != nil {
    70  		return err
    71  	} else if len(entry) != 33 {
    72  		return fmt.Errorf("invalid public key")
    73  	}
    74  	h := sha3.NewLegacyKeccak256()
    75  	list := msg.Messages(r.AppendElements(nil))
    76  	data, _ := list.MarshalMsg(nil)
    77  	h.Write(data)
    78  	if !ogcrypto2.VerifySignature(entry, h.Sum(nil), sig) {
    79  		return enr.ErrInvalidSig
    80  	}
    81  	return nil
    82  }
    83  
    84  func (V4ID) NodeAddr(r *enr.Record) []byte {
    85  	var pubkey Secp256k1
    86  	err := r.Load(&pubkey)
    87  	if err != nil {
    88  		return nil
    89  	}
    90  	buf := make([]byte, 64)
    91  	math.ReadBits(pubkey.X, buf[:32])
    92  	math.ReadBits(pubkey.Y, buf[32:])
    93  	return ogcrypto2.Keccak256(buf)
    94  }
    95  
    96  // S256raw is an unparsed secp256k1 public key entry.
    97  type S256raw []byte
    98  
    99  func (S256raw) ENRKey() string { return "secp256k1" }
   100  
   101  // v4CompatID is a weaker and insecure version of the "v4" scheme which only checks for the
   102  // presence of a secp256k1 public key, but doesn't verify the signature.
   103  type v4CompatID struct {
   104  	V4ID
   105  }
   106  
   107  func (v4CompatID) Verify(r *enr.Record, sig []byte) error {
   108  	var pubkey Secp256k1
   109  	return r.Load(&pubkey)
   110  }
   111  
   112  func signV4Compat(r *enr.Record, pubkey *ecdsa.PublicKey) {
   113  	r.Set((*Secp256k1)(pubkey))
   114  	if err := r.SetSig(v4CompatID{}, []byte{}); err != nil {
   115  		panic(err)
   116  	}
   117  }
   118  
   119  // NullID is the "null" ENR identity scheme. This scheme stores the node
   120  // ID in the record without any signature.
   121  type NullID struct{}
   122  
   123  func (NullID) Verify(r *enr.Record, sig []byte) error {
   124  	return nil
   125  }
   126  
   127  func (NullID) NodeAddr(r *enr.Record) []byte {
   128  	var id ID
   129  	r.Load(enr.WithEntry("nulladdr", &id))
   130  	return id[:]
   131  }
   132  
   133  func SignNull(r *enr.Record, id ID) *Node {
   134  	i := enr.ID("null")
   135  	r.Set(&i)
   136  	r.Set(enr.WithEntry("nulladdr", &id))
   137  	if err := r.SetSig(NullID{}, []byte{}); err != nil {
   138  		panic(err)
   139  	}
   140  	return &Node{R: *r, Id: id}
   141  }