github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/swarm/pss/handshake.go (about) 1 2 //<developer> 3 // <name>linapex 曹一峰</name> 4 // <email>linapex@163.com</email> 5 // <wx>superexc</wx> 6 // <qqgroup>128148617</qqgroup> 7 // <url>https://jsq.ink</url> 8 // <role>pku engineer</role> 9 // <date>2019-03-16 19:16:44</date> 10 //</624450116601778176> 11 12 13 //+建设!诺普桑德摇晃 14 15 package pss 16 17 import ( 18 "context" 19 "errors" 20 "fmt" 21 "sync" 22 "time" 23 24 "github.com/ethereum/go-ethereum/common" 25 "github.com/ethereum/go-ethereum/common/hexutil" 26 "github.com/ethereum/go-ethereum/crypto" 27 "github.com/ethereum/go-ethereum/p2p" 28 "github.com/ethereum/go-ethereum/rlp" 29 "github.com/ethereum/go-ethereum/rpc" 30 "github.com/ethereum/go-ethereum/swarm/log" 31 ) 32 33 const ( 34 IsActiveHandshake = true 35 ) 36 37 var ( 38 ctrlSingleton *HandshakeController 39 ) 40 41 const ( 42 defaultSymKeyRequestTimeout = 1000 * 8 //接收对握手符号请求的响应的最大等待毫秒数 43 defaultSymKeyExpiryTimeout = 1000 * 10 //ms等待,然后允许垃圾收集过期的symkey 44 defaultSymKeySendLimit = 256 //symkey的有效消息量 45 defaultSymKeyCapacity = 4 //同时存储/发送的最大符号键数 46 ) 47 48 //对称密钥交换消息负载 49 type handshakeMsg struct { 50 From []byte 51 Limit uint16 52 Keys [][]byte 53 Request uint8 54 Topic Topic 55 } 56 57 //单个对称密钥的内部表示法 58 type handshakeKey struct { 59 symKeyID *string 60 pubKeyID *string 61 limit uint16 62 count uint16 63 expiredAt time.Time 64 } 65 66 //所有输入和输出密钥的容器 67 //对于一个特定的对等(公钥)和主题 68 type handshake struct { 69 outKeys []handshakeKey 70 inKeys []handshakeKey 71 } 72 73 //握手控制器的初始化参数 74 // 75 //symkeyrequestexpiry:等待握手回复超时 76 //(默认8000 ms) 77 // 78 //symkeysendlimit:对称密钥问题的消息量 79 //此节点的有效期为(默认256) 80 // 81 //symkeycapacity:对称密钥的理想(和最大)数量 82 //每个对等端的每个方向保持(默认为4) 83 type HandshakeParams struct { 84 SymKeyRequestTimeout time.Duration 85 SymKeyExpiryTimeout time.Duration 86 SymKeySendLimit uint16 87 SymKeyCapacity uint8 88 } 89 90 //握手控制器初始化的正常默认值 91 func NewHandshakeParams() *HandshakeParams { 92 return &HandshakeParams{ 93 SymKeyRequestTimeout: defaultSymKeyRequestTimeout * time.Millisecond, 94 SymKeyExpiryTimeout: defaultSymKeyExpiryTimeout * time.Millisecond, 95 SymKeySendLimit: defaultSymKeySendLimit, 96 SymKeyCapacity: defaultSymKeyCapacity, 97 } 98 } 99 100 //启用半自动diffie-hellman的singleton对象 101 //交换短暂对称密钥 102 type HandshakeController struct { 103 pss *Pss 104 keyC map[string]chan []string //添加握手成功时要报告的频道 105 lock sync.Mutex 106 symKeyRequestTimeout time.Duration 107 symKeyExpiryTimeout time.Duration 108 symKeySendLimit uint16 109 symKeyCapacity uint8 110 symKeyIndex map[string]*handshakeKey 111 handshakes map[string]map[Topic]*handshake 112 deregisterFuncs map[Topic]func() 113 } 114 115 //将握手控制器连接到PSS节点 116 // 117 //必须在启动PSS节点服务之前调用 118 func SetHandshakeController(pss *Pss, params *HandshakeParams) error { 119 ctrl := &HandshakeController{ 120 pss: pss, 121 keyC: make(map[string]chan []string), 122 symKeyRequestTimeout: params.SymKeyRequestTimeout, 123 symKeyExpiryTimeout: params.SymKeyExpiryTimeout, 124 symKeySendLimit: params.SymKeySendLimit, 125 symKeyCapacity: params.SymKeyCapacity, 126 symKeyIndex: make(map[string]*handshakeKey), 127 handshakes: make(map[string]map[Topic]*handshake), 128 deregisterFuncs: make(map[Topic]func()), 129 } 130 api := &HandshakeAPI{ 131 namespace: "pss", 132 ctrl: ctrl, 133 } 134 pss.addAPI(rpc.API{ 135 Namespace: api.namespace, 136 Version: "0.2", 137 Service: api, 138 Public: true, 139 }) 140 ctrlSingleton = ctrl 141 return nil 142 } 143 144 //返回存储区中所有未过期的对称密钥 145 //对等(公钥)、主题和指定方向 146 func (ctl *HandshakeController) validKeys(pubkeyid string, topic *Topic, in bool) (validkeys []*string) { 147 ctl.lock.Lock() 148 defer ctl.lock.Unlock() 149 now := time.Now() 150 if _, ok := ctl.handshakes[pubkeyid]; !ok { 151 return []*string{} 152 } else if _, ok := ctl.handshakes[pubkeyid][*topic]; !ok { 153 return []*string{} 154 } 155 var keystore *[]handshakeKey 156 if in { 157 keystore = &(ctl.handshakes[pubkeyid][*topic].inKeys) 158 } else { 159 keystore = &(ctl.handshakes[pubkeyid][*topic].outKeys) 160 } 161 162 for _, key := range *keystore { 163 if key.limit <= key.count { 164 ctl.releaseKey(*key.symKeyID, topic) 165 } else if !key.expiredAt.IsZero() && key.expiredAt.Before(now) { 166 ctl.releaseKey(*key.symKeyID, topic) 167 } else { 168 validkeys = append(validkeys, key.symKeyID) 169 } 170 } 171 return 172 } 173 174 //将具有有效性限制的所有给定对称密钥添加到存储方式 175 //对等(公钥)、主题和指定方向 176 func (ctl *HandshakeController) updateKeys(pubkeyid string, topic *Topic, in bool, symkeyids []string, limit uint16) { 177 ctl.lock.Lock() 178 defer ctl.lock.Unlock() 179 if _, ok := ctl.handshakes[pubkeyid]; !ok { 180 ctl.handshakes[pubkeyid] = make(map[Topic]*handshake) 181 182 } 183 if ctl.handshakes[pubkeyid][*topic] == nil { 184 ctl.handshakes[pubkeyid][*topic] = &handshake{} 185 } 186 var keystore *[]handshakeKey 187 expire := time.Now() 188 if in { 189 keystore = &(ctl.handshakes[pubkeyid][*topic].inKeys) 190 } else { 191 keystore = &(ctl.handshakes[pubkeyid][*topic].outKeys) 192 expire = expire.Add(time.Millisecond * ctl.symKeyExpiryTimeout) 193 } 194 for _, storekey := range *keystore { 195 storekey.expiredAt = expire 196 } 197 for i := 0; i < len(symkeyids); i++ { 198 storekey := handshakeKey{ 199 symKeyID: &symkeyids[i], 200 pubKeyID: &pubkeyid, 201 limit: limit, 202 } 203 *keystore = append(*keystore, storekey) 204 ctl.pss.symKeyPool[*storekey.symKeyID][*topic].protected = true 205 } 206 for i := 0; i < len(*keystore); i++ { 207 ctl.symKeyIndex[*(*keystore)[i].symKeyID] = &((*keystore)[i]) 208 } 209 } 210 211 //使对称密钥过期,使其可用于垃圾收集 212 func (ctl *HandshakeController) releaseKey(symkeyid string, topic *Topic) bool { 213 if ctl.symKeyIndex[symkeyid] == nil { 214 log.Debug("no symkey", "symkeyid", symkeyid) 215 return false 216 } 217 ctl.symKeyIndex[symkeyid].expiredAt = time.Now() 218 log.Debug("handshake release", "symkeyid", symkeyid) 219 return true 220 } 221 222 //检查给定方向上的所有对称密钥 223 //指定的对等机(公钥)和到期主题。 224 //过期手段: 225 //-设置了到期时间戳,超过了宽限期 226 //-已达到消息有效性限制 227 func (ctl *HandshakeController) cleanHandshake(pubkeyid string, topic *Topic, in bool, out bool) int { 228 ctl.lock.Lock() 229 defer ctl.lock.Unlock() 230 var deletecount int 231 var deletes []string 232 now := time.Now() 233 handshake := ctl.handshakes[pubkeyid][*topic] 234 log.Debug("handshake clean", "pubkey", pubkeyid, "topic", topic) 235 if in { 236 for i, key := range handshake.inKeys { 237 if key.expiredAt.Before(now) || (key.expiredAt.IsZero() && key.limit <= key.count) { 238 log.Trace("handshake in clean remove", "symkeyid", *key.symKeyID) 239 deletes = append(deletes, *key.symKeyID) 240 handshake.inKeys[deletecount] = handshake.inKeys[i] 241 deletecount++ 242 } 243 } 244 handshake.inKeys = handshake.inKeys[:len(handshake.inKeys)-deletecount] 245 } 246 if out { 247 deletecount = 0 248 for i, key := range handshake.outKeys { 249 if key.expiredAt.Before(now) && (key.expiredAt.IsZero() && key.limit <= key.count) { 250 log.Trace("handshake out clean remove", "symkeyid", *key.symKeyID) 251 deletes = append(deletes, *key.symKeyID) 252 handshake.outKeys[deletecount] = handshake.outKeys[i] 253 deletecount++ 254 } 255 } 256 handshake.outKeys = handshake.outKeys[:len(handshake.outKeys)-deletecount] 257 } 258 for _, keyid := range deletes { 259 delete(ctl.symKeyIndex, keyid) 260 ctl.pss.symKeyPool[keyid][*topic].protected = false 261 } 262 return len(deletes) 263 } 264 265 //对所有对等端和主题运行cleanhandshake()。 266 func (ctl *HandshakeController) clean() { 267 peerpubkeys := ctl.handshakes 268 for pubkeyid, peertopics := range peerpubkeys { 269 for topic := range peertopics { 270 ctl.cleanHandshake(pubkeyid, &topic, true, true) 271 } 272 } 273 } 274 275 //作为主题握手的pssmsg处理程序传递将在上激活 276 //处理传入的密钥交换消息和 277 //按对称密钥使用的CCUNTS消息(到期限制控制) 278 //仅当密钥处理程序失败时返回错误 279 func (ctl *HandshakeController) handler(msg []byte, p *p2p.Peer, asymmetric bool, symkeyid string) error { 280 if !asymmetric { 281 if ctl.symKeyIndex[symkeyid] != nil { 282 if ctl.symKeyIndex[symkeyid].count >= ctl.symKeyIndex[symkeyid].limit { 283 return fmt.Errorf("discarding message using expired key: %s", symkeyid) 284 } 285 ctl.symKeyIndex[symkeyid].count++ 286 log.Trace("increment symkey recv use", "symsymkeyid", symkeyid, "count", ctl.symKeyIndex[symkeyid].count, "limit", ctl.symKeyIndex[symkeyid].limit, "receiver", common.ToHex(crypto.FromECDSAPub(ctl.pss.PublicKey()))) 287 } 288 return nil 289 } 290 keymsg := &handshakeMsg{} 291 err := rlp.DecodeBytes(msg, keymsg) 292 if err == nil { 293 err := ctl.handleKeys(symkeyid, keymsg) 294 if err != nil { 295 log.Error("handlekeys fail", "error", err) 296 } 297 return err 298 } 299 return nil 300 } 301 302 //处理传入密钥交换消息 303 //将从对等端接收到的密钥添加到存储区 304 //生成并发送对等机请求的密钥数量 305 // 306 //TODO: 307 //防洪堤 308 //-键长检查 309 //-更新地址提示,如果: 310 //1)新地址中最左边的字节与存储的不匹配 311 //2)否则,如果新地址较长 312 func (ctl *HandshakeController) handleKeys(pubkeyid string, keymsg *handshakeMsg) error { 313 //来自对等机的新密钥 314 if len(keymsg.Keys) > 0 { 315 log.Debug("received handshake keys", "pubkeyid", pubkeyid, "from", keymsg.From, "count", len(keymsg.Keys)) 316 var sendsymkeyids []string 317 for _, key := range keymsg.Keys { 318 sendsymkey := make([]byte, len(key)) 319 copy(sendsymkey, key) 320 sendsymkeyid, err := ctl.pss.setSymmetricKey(sendsymkey, keymsg.Topic, PssAddress(keymsg.From), false, false) 321 if err != nil { 322 return err 323 } 324 sendsymkeyids = append(sendsymkeyids, sendsymkeyid) 325 } 326 if len(sendsymkeyids) > 0 { 327 ctl.updateKeys(pubkeyid, &keymsg.Topic, false, sendsymkeyids, keymsg.Limit) 328 329 ctl.alertHandshake(pubkeyid, sendsymkeyids) 330 } 331 } 332 333 //对等密钥请求 334 if keymsg.Request > 0 { 335 _, err := ctl.sendKey(pubkeyid, &keymsg.Topic, keymsg.Request) 336 if err != nil { 337 return err 338 } 339 } 340 341 return nil 342 } 343 344 //将密钥交换发送到对“topic”有效的对等方(公钥) 345 //将发送“keycount”指定的密钥数 346 //“msglmit”中指定的有效限制 347 //如果有效的传出密钥数小于理想/最大值 348 //金额,发送一个请求以获取要补足的密钥数量 349 //差异 350 func (ctl *HandshakeController) sendKey(pubkeyid string, topic *Topic, keycount uint8) ([]string, error) { 351 352 var requestcount uint8 353 to := PssAddress{} 354 if _, ok := ctl.pss.pubKeyPool[pubkeyid]; !ok { 355 return []string{}, errors.New("Invalid public key") 356 } else if psp, ok := ctl.pss.pubKeyPool[pubkeyid][*topic]; ok { 357 to = psp.address 358 } 359 360 recvkeys := make([][]byte, keycount) 361 recvkeyids := make([]string, keycount) 362 ctl.lock.Lock() 363 if _, ok := ctl.handshakes[pubkeyid]; !ok { 364 ctl.handshakes[pubkeyid] = make(map[Topic]*handshake) 365 } 366 ctl.lock.Unlock() 367 368 //检查缓冲区是否未满 369 outkeys := ctl.validKeys(pubkeyid, topic, false) 370 if len(outkeys) < int(ctl.symKeyCapacity) { 371 //请求计数=uint8(self.symkeycapacity-uint8(len(outkeys))) 372 requestcount = ctl.symKeyCapacity 373 } 374 //如果没有什么事要做就回来 375 if requestcount == 0 && keycount == 0 { 376 return []string{}, nil 377 } 378 379 //生成要发送的新密钥 380 for i := 0; i < len(recvkeyids); i++ { 381 var err error 382 recvkeyids[i], err = ctl.pss.GenerateSymmetricKey(*topic, to, true) 383 if err != nil { 384 return []string{}, fmt.Errorf("set receive symkey fail (pubkey %x topic %x): %v", pubkeyid, topic, err) 385 } 386 recvkeys[i], err = ctl.pss.GetSymmetricKey(recvkeyids[i]) 387 if err != nil { 388 return []string{}, fmt.Errorf("GET Generated outgoing symkey fail (pubkey %x topic %x): %v", pubkeyid, topic, err) 389 } 390 } 391 ctl.updateKeys(pubkeyid, topic, true, recvkeyids, ctl.symKeySendLimit) 392 393 //编码并发送消息 394 recvkeymsg := &handshakeMsg{ 395 From: ctl.pss.BaseAddr(), 396 Keys: recvkeys, 397 Request: requestcount, 398 Limit: ctl.symKeySendLimit, 399 Topic: *topic, 400 } 401 log.Debug("sending our symkeys", "pubkey", pubkeyid, "symkeys", recvkeyids, "limit", ctl.symKeySendLimit, "requestcount", requestcount, "keycount", len(recvkeys)) 402 recvkeybytes, err := rlp.EncodeToBytes(recvkeymsg) 403 if err != nil { 404 return []string{}, fmt.Errorf("rlp keymsg encode fail: %v", err) 405 } 406 //如果发送失败,则表示此公钥没有为此特定地址和主题注册。 407 err = ctl.pss.SendAsym(pubkeyid, *topic, recvkeybytes) 408 if err != nil { 409 return []string{}, fmt.Errorf("Send symkey failed: %v", err) 410 } 411 return recvkeyids, nil 412 } 413 414 //对从密钥交换请求接收的密钥启用回调 415 func (ctl *HandshakeController) alertHandshake(pubkeyid string, symkeys []string) chan []string { 416 if len(symkeys) > 0 { 417 if _, ok := ctl.keyC[pubkeyid]; ok { 418 ctl.keyC[pubkeyid] <- symkeys 419 close(ctl.keyC[pubkeyid]) 420 delete(ctl.keyC, pubkeyid) 421 } 422 return nil 423 } 424 if _, ok := ctl.keyC[pubkeyid]; !ok { 425 ctl.keyC[pubkeyid] = make(chan []string) 426 } 427 return ctl.keyC[pubkeyid] 428 } 429 430 type HandshakeAPI struct { 431 namespace string 432 ctrl *HandshakeController 433 } 434 435 //为对等机(公钥)和主题启动握手会话 436 //组合。 437 // 438 //如果设置了“sync”,则调用将被阻止,直到从对等机收到密钥为止, 439 //或者如果握手请求超时 440 // 441 //如果设置了“flush”,将向对等机发送最大数量的密钥。 442 //不管存储区中当前存在多少有效密钥。 443 // 444 //返回可传递给pss.getSymmetricKey()的对称密钥ID的列表 445 //用于检索对称密钥字节本身。 446 // 447 //如果传入的对称密钥存储已满(并且'flush'为false),则失败, 448 //或者如果基础密钥调度程序失败 449 func (api *HandshakeAPI) Handshake(pubkeyid string, topic Topic, sync bool, flush bool) (keys []string, err error) { 450 var hsc chan []string 451 var keycount uint8 452 if flush { 453 keycount = api.ctrl.symKeyCapacity 454 } else { 455 validkeys := api.ctrl.validKeys(pubkeyid, &topic, false) 456 keycount = api.ctrl.symKeyCapacity - uint8(len(validkeys)) 457 } 458 if keycount == 0 { 459 return keys, errors.New("Incoming symmetric key store is already full") 460 } 461 if sync { 462 hsc = api.ctrl.alertHandshake(pubkeyid, []string{}) 463 } 464 _, err = api.ctrl.sendKey(pubkeyid, &topic, keycount) 465 if err != nil { 466 return keys, err 467 } 468 if sync { 469 ctx, cancel := context.WithTimeout(context.Background(), api.ctrl.symKeyRequestTimeout) 470 defer cancel() 471 select { 472 case keys = <-hsc: 473 log.Trace("sync handshake response receive", "key", keys) 474 case <-ctx.Done(): 475 return []string{}, errors.New("timeout") 476 } 477 } 478 return keys, nil 479 } 480 481 //激活主题的握手功能 482 func (api *HandshakeAPI) AddHandshake(topic Topic) error { 483 api.ctrl.deregisterFuncs[topic] = api.ctrl.pss.Register(&topic, NewHandler(api.ctrl.handler)) 484 return nil 485 } 486 487 //停用主题的握手功能 488 func (api *HandshakeAPI) RemoveHandshake(topic *Topic) error { 489 if _, ok := api.ctrl.deregisterFuncs[*topic]; ok { 490 api.ctrl.deregisterFuncs[*topic]() 491 } 492 return nil 493 } 494 495 //返回存储中每个对等机的所有有效对称密钥(公钥) 496 //话题。 497 // 498 //“in”和“out”参数指示哪个方向 499 //将返回对称密钥。 500 //如果两者都为假,则不会返回任何键(也不会返回任何错误)。 501 func (api *HandshakeAPI) GetHandshakeKeys(pubkeyid string, topic Topic, in bool, out bool) (keys []string, err error) { 502 if in { 503 for _, inkey := range api.ctrl.validKeys(pubkeyid, &topic, true) { 504 keys = append(keys, *inkey) 505 } 506 } 507 if out { 508 for _, outkey := range api.ctrl.validKeys(pubkeyid, &topic, false) { 509 keys = append(keys, *outkey) 510 } 511 } 512 return keys, nil 513 } 514 515 //返回指定对称密钥的消息量 516 //在握手方案下仍然有效 517 func (api *HandshakeAPI) GetHandshakeKeyCapacity(symkeyid string) (uint16, error) { 518 storekey := api.ctrl.symKeyIndex[symkeyid] 519 if storekey == nil { 520 return 0, fmt.Errorf("invalid symkey id %s", symkeyid) 521 } 522 return storekey.limit - storekey.count, nil 523 } 524 525 //返回公钥的字节表示形式(以ASCII十六进制表示) 526 //与给定的对称密钥关联 527 func (api *HandshakeAPI) GetHandshakePublicKey(symkeyid string) (string, error) { 528 storekey := api.ctrl.symKeyIndex[symkeyid] 529 if storekey == nil { 530 return "", fmt.Errorf("invalid symkey id %s", symkeyid) 531 } 532 return *storekey.pubKeyID, nil 533 } 534 535 //手动终止给定的symkey 536 // 537 //如果设置了“flush”,则在返回之前将执行垃圾收集。 538 // 539 //成功删除时返回true,否则返回false 540 func (api *HandshakeAPI) ReleaseHandshakeKey(pubkeyid string, topic Topic, symkeyid string, flush bool) (removed bool, err error) { 541 removed = api.ctrl.releaseKey(symkeyid, &topic) 542 if removed && flush { 543 api.ctrl.cleanHandshake(pubkeyid, &topic, true, true) 544 } 545 return 546 } 547 548 //在握手方案下发送对称消息 549 // 550 //重载pss.sendsym()API调用,添加对称密钥使用计数 551 //用于消息到期控制 552 func (api *HandshakeAPI) SendSym(symkeyid string, topic Topic, msg hexutil.Bytes) (err error) { 553 err = api.ctrl.pss.SendSym(symkeyid, topic, msg[:]) 554 if api.ctrl.symKeyIndex[symkeyid] != nil { 555 if api.ctrl.symKeyIndex[symkeyid].count >= api.ctrl.symKeyIndex[symkeyid].limit { 556 return errors.New("attempted send with expired key") 557 } 558 api.ctrl.symKeyIndex[symkeyid].count++ 559 log.Trace("increment symkey send use", "symkeyid", symkeyid, "count", api.ctrl.symKeyIndex[symkeyid].count, "limit", api.ctrl.symKeyIndex[symkeyid].limit, "receiver", common.ToHex(crypto.FromECDSAPub(api.ctrl.pss.PublicKey()))) 560 } 561 return err 562 } 563