idscheme.go 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  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. package enode
  17. import (
  18. "crypto/ecdsa"
  19. "fmt"
  20. "io"
  21. "github.com/ethereum/go-ethereum/common/math"
  22. "github.com/ethereum/go-ethereum/crypto"
  23. "github.com/ethereum/go-ethereum/p2p/enr"
  24. "github.com/ethereum/go-ethereum/rlp"
  25. "golang.org/x/crypto/sha3"
  26. )
  27. // List of known secure identity schemes.
  28. var ValidSchemes = enr.SchemeMap{
  29. "v4": V4ID{},
  30. }
  31. var ValidSchemesForTesting = enr.SchemeMap{
  32. "v4": V4ID{},
  33. "null": NullID{},
  34. }
  35. // v4ID is the "v4" identity scheme.
  36. type V4ID struct{}
  37. // SignV4 signs a record using the v4 scheme.
  38. func SignV4(r *enr.Record, privkey *ecdsa.PrivateKey) error {
  39. // Copy r to avoid modifying it if signing fails.
  40. cpy := *r
  41. cpy.Set(enr.ID("v4"))
  42. cpy.Set(Secp256k1(privkey.PublicKey))
  43. h := sha3.NewLegacyKeccak256()
  44. rlp.Encode(h, cpy.AppendElements(nil))
  45. sig, err := crypto.Sign(h.Sum(nil), privkey)
  46. if err != nil {
  47. return err
  48. }
  49. sig = sig[:len(sig)-1] // remove v
  50. if err = cpy.SetSig(V4ID{}, sig); err == nil {
  51. *r = cpy
  52. }
  53. return err
  54. }
  55. func (V4ID) Verify(r *enr.Record, sig []byte) error {
  56. var entry s256raw
  57. if err := r.Load(&entry); err != nil {
  58. return err
  59. } else if len(entry) != 33 {
  60. return fmt.Errorf("invalid public key")
  61. }
  62. h := sha3.NewLegacyKeccak256()
  63. rlp.Encode(h, r.AppendElements(nil))
  64. if !crypto.VerifySignature(entry, h.Sum(nil), sig) {
  65. return enr.ErrInvalidSig
  66. }
  67. return nil
  68. }
  69. func (V4ID) NodeAddr(r *enr.Record) []byte {
  70. var pubkey Secp256k1
  71. err := r.Load(&pubkey)
  72. if err != nil {
  73. return nil
  74. }
  75. buf := make([]byte, 64)
  76. math.ReadBits(pubkey.X, buf[:32])
  77. math.ReadBits(pubkey.Y, buf[32:])
  78. return crypto.Keccak256(buf)
  79. }
  80. // Secp256k1 is the "secp256k1" key, which holds a public key.
  81. type Secp256k1 ecdsa.PublicKey
  82. func (v Secp256k1) ENRKey() string { return "secp256k1" }
  83. // EncodeRLP implements rlp.Encoder.
  84. func (v Secp256k1) EncodeRLP(w io.Writer) error {
  85. return rlp.Encode(w, crypto.CompressPubkey((*ecdsa.PublicKey)(&v)))
  86. }
  87. // DecodeRLP implements rlp.Decoder.
  88. func (v *Secp256k1) DecodeRLP(s *rlp.Stream) error {
  89. buf, err := s.Bytes()
  90. if err != nil {
  91. return err
  92. }
  93. pk, err := crypto.DecompressPubkey(buf)
  94. if err != nil {
  95. return err
  96. }
  97. *v = (Secp256k1)(*pk)
  98. return nil
  99. }
  100. // s256raw is an unparsed secp256k1 public key entry.
  101. type s256raw []byte
  102. func (s256raw) ENRKey() string { return "secp256k1" }
  103. // v4CompatID is a weaker and insecure version of the "v4" scheme which only checks for the
  104. // presence of a secp256k1 public key, but doesn't verify the signature.
  105. type v4CompatID struct {
  106. V4ID
  107. }
  108. func (v4CompatID) Verify(r *enr.Record, sig []byte) error {
  109. var pubkey Secp256k1
  110. return r.Load(&pubkey)
  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. // NullID is the "null" ENR identity scheme. This scheme stores the node
  119. // ID in the record without any signature.
  120. type NullID struct{}
  121. func (NullID) Verify(r *enr.Record, sig []byte) error {
  122. return nil
  123. }
  124. func (NullID) NodeAddr(r *enr.Record) []byte {
  125. var id ID
  126. r.Load(enr.WithEntry("nulladdr", &id))
  127. return id[:]
  128. }
  129. func SignNull(r *enr.Record, id ID) *Node {
  130. r.Set(enr.ID("null"))
  131. r.Set(enr.WithEntry("nulladdr", id))
  132. if err := r.SetSig(NullID{}, []byte{}); err != nil {
  133. panic(err)
  134. }
  135. return &Node{r: *r, id: id}
  136. }