github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/p2p/enr/idscheme.go (about) 1 2 //此源码被清华学神尹成大魔王专业翻译分析并修改 3 //尹成QQ77025077 4 //尹成微信18510341407 5 //尹成所在QQ群721929980 6 //尹成邮箱 yinc13@mails.tsinghua.edu.cn 7 //尹成毕业于清华大学,微软区块链领域全球最有价值专家 8 //https://mvp.microsoft.com/zh-cn/PublicProfile/4033620 9 //版权所有2018 Go Ethereum作者 10 //此文件是Go以太坊库的一部分。 11 // 12 //Go-Ethereum库是免费软件:您可以重新分发它和/或修改 13 //根据GNU发布的较低通用公共许可证的条款 14 //自由软件基金会,或者许可证的第3版,或者 15 //(由您选择)任何更高版本。 16 // 17 //Go以太坊图书馆的发行目的是希望它会有用, 18 //但没有任何保证;甚至没有 19 //适销性或特定用途的适用性。见 20 //GNU较低的通用公共许可证,了解更多详细信息。 21 // 22 //你应该收到一份GNU较低级别的公共许可证副本 23 //以及Go以太坊图书馆。如果没有,请参见<http://www.gnu.org/licenses/>。 24 25 package enr 26 27 import ( 28 "crypto/ecdsa" 29 "fmt" 30 "sync" 31 32 "github.com/ethereum/go-ethereum/common/math" 33 "github.com/ethereum/go-ethereum/crypto" 34 "github.com/ethereum/go-ethereum/crypto/sha3" 35 "github.com/ethereum/go-ethereum/rlp" 36 ) 37 38 //已知身份方案的注册表。 39 var schemes sync.Map 40 41 //标识方案能够验证记录签名和 42 //派生节点地址。 43 type IdentityScheme interface { 44 Verify(r *Record, sig []byte) error 45 NodeAddr(r *Record) []byte 46 } 47 48 //RegisterIdentityScheme向全局注册表添加标识方案。 49 func RegisterIdentityScheme(name string, scheme IdentityScheme) { 50 if _, loaded := schemes.LoadOrStore(name, scheme); loaded { 51 panic("identity scheme " + name + " already registered") 52 } 53 } 54 55 //findidentityScheme将名称解析为全局注册表中的标识方案。 56 func FindIdentityScheme(name string) IdentityScheme { 57 s, ok := schemes.Load(name) 58 if !ok { 59 return nil 60 } 61 return s.(IdentityScheme) 62 } 63 64 //v4id是“v4”标识方案。 65 type v4ID struct{} 66 67 func init() { 68 RegisterIdentityScheme("v4", v4ID{}) 69 } 70 71 //signv4使用v4方案对记录进行签名。 72 func SignV4(r *Record, privkey *ecdsa.PrivateKey) error { 73 //复制r以避免在签名失败时修改它。 74 cpy := *r 75 cpy.Set(ID("v4")) 76 cpy.Set(Secp256k1(privkey.PublicKey)) 77 78 h := sha3.NewKeccak256() 79 rlp.Encode(h, cpy.AppendElements(nil)) 80 sig, err := crypto.Sign(h.Sum(nil), privkey) 81 if err != nil { 82 return err 83 } 84 sig = sig[:len(sig)-1] //移除V 85 if err = cpy.SetSig("v4", sig); err == nil { 86 *r = cpy 87 } 88 return err 89 } 90 91 //s256raw是一个未分析的secp256k1公钥条目。 92 type s256raw []byte 93 94 func (s256raw) ENRKey() string { return "secp256k1" } 95 96 func (v4ID) Verify(r *Record, sig []byte) error { 97 var entry s256raw 98 if err := r.Load(&entry); err != nil { 99 return err 100 } else if len(entry) != 33 { 101 return fmt.Errorf("invalid public key") 102 } 103 104 h := sha3.NewKeccak256() 105 rlp.Encode(h, r.AppendElements(nil)) 106 if !crypto.VerifySignature(entry, h.Sum(nil), sig) { 107 return errInvalidSig 108 } 109 return nil 110 } 111 112 func (v4ID) NodeAddr(r *Record) []byte { 113 var pubkey Secp256k1 114 err := r.Load(&pubkey) 115 if err != nil { 116 return nil 117 } 118 buf := make([]byte, 64) 119 math.ReadBits(pubkey.X, buf[:32]) 120 math.ReadBits(pubkey.Y, buf[32:]) 121 return crypto.Keccak256(buf) 122 }