github.com/FUSIONFoundation/efsn@v3.6.2-0.20200916075423-dbb5dd5d2cc7+incompatible/swarm/pss/pss.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 pss 18 19 import ( 20 "bytes" 21 "context" 22 "crypto/ecdsa" 23 "crypto/rand" 24 "errors" 25 "fmt" 26 "sync" 27 "time" 28 29 "github.com/FusionFoundation/efsn/common" 30 "github.com/FusionFoundation/efsn/crypto" 31 "github.com/FusionFoundation/efsn/metrics" 32 "github.com/FusionFoundation/efsn/p2p" 33 "github.com/FusionFoundation/efsn/p2p/discover" 34 "github.com/FusionFoundation/efsn/p2p/protocols" 35 "github.com/FusionFoundation/efsn/rpc" 36 "github.com/FusionFoundation/efsn/swarm/log" 37 "github.com/FusionFoundation/efsn/swarm/network" 38 "github.com/FusionFoundation/efsn/swarm/pot" 39 "github.com/FusionFoundation/efsn/swarm/storage" 40 whisper "github.com/FusionFoundation/efsn/whisper/whisperv5" 41 ) 42 43 const ( 44 defaultPaddingByteSize = 16 45 DefaultMsgTTL = time.Second * 120 46 defaultDigestCacheTTL = time.Second * 10 47 defaultSymKeyCacheCapacity = 512 48 digestLength = 32 // byte length of digest used for pss cache (currently same as swarm chunk hash) 49 defaultWhisperWorkTime = 3 50 defaultWhisperPoW = 0.0000000001 51 defaultMaxMsgSize = 1024 * 1024 52 defaultCleanInterval = time.Second * 60 * 10 53 defaultOutboxCapacity = 100000 54 pssProtocolName = "pss" 55 pssVersion = 2 56 hasherCount = 8 57 ) 58 59 var ( 60 addressLength = len(pot.Address{}) 61 ) 62 63 // cache is used for preventing backwards routing 64 // will also be instrumental in flood guard mechanism 65 // and mailbox implementation 66 type pssCacheEntry struct { 67 expiresAt time.Time 68 } 69 70 // abstraction to enable access to p2p.protocols.Peer.Send 71 type senderPeer interface { 72 Info() *p2p.PeerInfo 73 ID() discover.NodeID 74 Address() []byte 75 Send(context.Context, interface{}) error 76 } 77 78 // per-key peer related information 79 // member `protected` prevents garbage collection of the instance 80 type pssPeer struct { 81 lastSeen time.Time 82 address *PssAddress 83 protected bool 84 } 85 86 // Pss configuration parameters 87 type PssParams struct { 88 MsgTTL time.Duration 89 CacheTTL time.Duration 90 privateKey *ecdsa.PrivateKey 91 SymKeyCacheCapacity int 92 AllowRaw bool // If true, enables sending and receiving messages without builtin pss encryption 93 } 94 95 // Sane defaults for Pss 96 func NewPssParams() *PssParams { 97 return &PssParams{ 98 MsgTTL: DefaultMsgTTL, 99 CacheTTL: defaultDigestCacheTTL, 100 SymKeyCacheCapacity: defaultSymKeyCacheCapacity, 101 } 102 } 103 104 func (params *PssParams) WithPrivateKey(privatekey *ecdsa.PrivateKey) *PssParams { 105 params.privateKey = privatekey 106 return params 107 } 108 109 // Toplevel pss object, takes care of message sending, receiving, decryption and encryption, message handler dispatchers and message forwarding. 110 // 111 // Implements node.Service 112 type Pss struct { 113 *network.Kademlia // we can get the Kademlia address from this 114 privateKey *ecdsa.PrivateKey // pss can have it's own independent key 115 w *whisper.Whisper // key and encryption backend 116 auxAPIs []rpc.API // builtins (handshake, test) can add APIs 117 118 // sending and forwarding 119 fwdPool map[string]*protocols.Peer // keep track of all peers sitting on the pssmsg routing layer 120 fwdPoolMu sync.RWMutex 121 fwdCache map[pssDigest]pssCacheEntry // checksum of unique fields from pssmsg mapped to expiry, cache to determine whether to drop msg 122 fwdCacheMu sync.RWMutex 123 cacheTTL time.Duration // how long to keep messages in fwdCache (not implemented) 124 msgTTL time.Duration 125 paddingByteSize int 126 capstring string 127 outbox chan *PssMsg 128 129 // keys and peers 130 pubKeyPool map[string]map[Topic]*pssPeer // mapping of hex public keys to peer address by topic. 131 pubKeyPoolMu sync.RWMutex 132 symKeyPool map[string]map[Topic]*pssPeer // mapping of symkeyids to peer address by topic. 133 symKeyPoolMu sync.RWMutex 134 symKeyDecryptCache []*string // fast lookup of symkeys recently used for decryption; last used is on top of stack 135 symKeyDecryptCacheCursor int // modular cursor pointing to last used, wraps on symKeyDecryptCache array 136 symKeyDecryptCacheCapacity int // max amount of symkeys to keep. 137 138 // message handling 139 handlers map[Topic]map[*Handler]bool // topic and version based pss payload handlers. See pss.Handle() 140 handlersMu sync.RWMutex 141 allowRaw bool 142 hashPool sync.Pool 143 144 // process 145 quitC chan struct{} 146 } 147 148 func (p *Pss) String() string { 149 return fmt.Sprintf("pss: addr %x, pubkey %v", p.BaseAddr(), common.ToHex(crypto.FromECDSAPub(&p.privateKey.PublicKey))) 150 } 151 152 // Creates a new Pss instance. 153 // 154 // In addition to params, it takes a swarm network Kademlia 155 // and a FileStore storage for message cache storage. 156 func NewPss(k *network.Kademlia, params *PssParams) (*Pss, error) { 157 if params.privateKey == nil { 158 return nil, errors.New("missing private key for pss") 159 } 160 cap := p2p.Cap{ 161 Name: pssProtocolName, 162 Version: pssVersion, 163 } 164 ps := &Pss{ 165 Kademlia: k, 166 privateKey: params.privateKey, 167 w: whisper.New(&whisper.DefaultConfig), 168 quitC: make(chan struct{}), 169 170 fwdPool: make(map[string]*protocols.Peer), 171 fwdCache: make(map[pssDigest]pssCacheEntry), 172 cacheTTL: params.CacheTTL, 173 msgTTL: params.MsgTTL, 174 paddingByteSize: defaultPaddingByteSize, 175 capstring: cap.String(), 176 outbox: make(chan *PssMsg, defaultOutboxCapacity), 177 178 pubKeyPool: make(map[string]map[Topic]*pssPeer), 179 symKeyPool: make(map[string]map[Topic]*pssPeer), 180 symKeyDecryptCache: make([]*string, params.SymKeyCacheCapacity), 181 symKeyDecryptCacheCapacity: params.SymKeyCacheCapacity, 182 183 handlers: make(map[Topic]map[*Handler]bool), 184 allowRaw: params.AllowRaw, 185 hashPool: sync.Pool{ 186 New: func() interface{} { 187 return storage.MakeHashFunc(storage.DefaultHash)() 188 }, 189 }, 190 } 191 192 for i := 0; i < hasherCount; i++ { 193 hashfunc := storage.MakeHashFunc(storage.DefaultHash)() 194 ps.hashPool.Put(hashfunc) 195 } 196 197 return ps, nil 198 } 199 200 ///////////////////////////////////////////////////////////////////// 201 // SECTION: node.Service interface 202 ///////////////////////////////////////////////////////////////////// 203 204 func (p *Pss) Start(srv *p2p.Server) error { 205 go func() { 206 ticker := time.NewTicker(defaultCleanInterval) 207 cacheTicker := time.NewTicker(p.cacheTTL) 208 defer ticker.Stop() 209 defer cacheTicker.Stop() 210 for { 211 select { 212 case <-cacheTicker.C: 213 p.cleanFwdCache() 214 case <-ticker.C: 215 p.cleanKeys() 216 case <-p.quitC: 217 return 218 } 219 } 220 }() 221 go func() { 222 for { 223 select { 224 case msg := <-p.outbox: 225 err := p.forward(msg) 226 if err != nil { 227 log.Error(err.Error()) 228 metrics.GetOrRegisterCounter("pss.forward.err", nil).Inc(1) 229 } 230 case <-p.quitC: 231 return 232 } 233 } 234 }() 235 log.Info("Started Pss") 236 log.Info("Loaded EC keys", "pubkey", common.ToHex(crypto.FromECDSAPub(p.PublicKey())), "secp256", common.ToHex(crypto.CompressPubkey(p.PublicKey()))) 237 return nil 238 } 239 240 func (p *Pss) Stop() error { 241 log.Info("Pss shutting down") 242 close(p.quitC) 243 return nil 244 } 245 246 var pssSpec = &protocols.Spec{ 247 Name: pssProtocolName, 248 Version: pssVersion, 249 MaxMsgSize: defaultMaxMsgSize, 250 Messages: []interface{}{ 251 PssMsg{}, 252 }, 253 } 254 255 func (p *Pss) Protocols() []p2p.Protocol { 256 return []p2p.Protocol{ 257 { 258 Name: pssSpec.Name, 259 Version: pssSpec.Version, 260 Length: pssSpec.Length(), 261 Run: p.Run, 262 }, 263 } 264 } 265 266 func (p *Pss) Run(peer *p2p.Peer, rw p2p.MsgReadWriter) error { 267 pp := protocols.NewPeer(peer, rw, pssSpec) 268 p.fwdPoolMu.Lock() 269 p.fwdPool[peer.Info().ID] = pp 270 p.fwdPoolMu.Unlock() 271 return pp.Run(p.handlePssMsg) 272 } 273 274 func (p *Pss) APIs() []rpc.API { 275 apis := []rpc.API{ 276 { 277 Namespace: "pss", 278 Version: "1.0", 279 Service: NewAPI(p), 280 Public: true, 281 }, 282 } 283 apis = append(apis, p.auxAPIs...) 284 return apis 285 } 286 287 // add API methods to the pss API 288 // must be run before node is started 289 func (p *Pss) addAPI(api rpc.API) { 290 p.auxAPIs = append(p.auxAPIs, api) 291 } 292 293 // Returns the swarm Kademlia address of the pss node 294 func (p *Pss) BaseAddr() []byte { 295 return p.Kademlia.BaseAddr() 296 } 297 298 // Returns the pss node's public key 299 func (p *Pss) PublicKey() *ecdsa.PublicKey { 300 return &p.privateKey.PublicKey 301 } 302 303 ///////////////////////////////////////////////////////////////////// 304 // SECTION: Message handling 305 ///////////////////////////////////////////////////////////////////// 306 307 // Links a handler function to a Topic 308 // 309 // All incoming messages with an envelope Topic matching the 310 // topic specified will be passed to the given Handler function. 311 // 312 // There may be an arbitrary number of handler functions per topic. 313 // 314 // Returns a deregister function which needs to be called to 315 // deregister the handler, 316 func (p *Pss) Register(topic *Topic, handler Handler) func() { 317 p.handlersMu.Lock() 318 defer p.handlersMu.Unlock() 319 handlers := p.handlers[*topic] 320 if handlers == nil { 321 handlers = make(map[*Handler]bool) 322 p.handlers[*topic] = handlers 323 } 324 handlers[&handler] = true 325 return func() { p.deregister(topic, &handler) } 326 } 327 func (p *Pss) deregister(topic *Topic, h *Handler) { 328 p.handlersMu.Lock() 329 defer p.handlersMu.Unlock() 330 handlers := p.handlers[*topic] 331 if len(handlers) == 1 { 332 delete(p.handlers, *topic) 333 return 334 } 335 delete(handlers, h) 336 } 337 338 // get all registered handlers for respective topics 339 func (p *Pss) getHandlers(topic Topic) map[*Handler]bool { 340 p.handlersMu.RLock() 341 defer p.handlersMu.RUnlock() 342 return p.handlers[topic] 343 } 344 345 // Filters incoming messages for processing or forwarding. 346 // Check if address partially matches 347 // If yes, it CAN be for us, and we process it 348 // Only passes error to pss protocol handler if payload is not valid pssmsg 349 func (p *Pss) handlePssMsg(ctx context.Context, msg interface{}) error { 350 metrics.GetOrRegisterCounter("pss.handlepssmsg", nil).Inc(1) 351 352 pssmsg, ok := msg.(*PssMsg) 353 354 if !ok { 355 return fmt.Errorf("invalid message type. Expected *PssMsg, got %T ", msg) 356 } 357 if int64(pssmsg.Expire) < time.Now().Unix() { 358 metrics.GetOrRegisterCounter("pss.expire", nil).Inc(1) 359 log.Warn("pss filtered expired message", "from", common.ToHex(p.Kademlia.BaseAddr()), "to", common.ToHex(pssmsg.To)) 360 return nil 361 } 362 if p.checkFwdCache(pssmsg) { 363 log.Trace("pss relay block-cache match (process)", "from", common.ToHex(p.Kademlia.BaseAddr()), "to", (common.ToHex(pssmsg.To))) 364 return nil 365 } 366 p.addFwdCache(pssmsg) 367 368 if !p.isSelfPossibleRecipient(pssmsg) { 369 log.Trace("pss was for someone else :'( ... forwarding", "pss", common.ToHex(p.BaseAddr())) 370 return p.enqueue(pssmsg) 371 } 372 373 log.Trace("pss for us, yay! ... let's process!", "pss", common.ToHex(p.BaseAddr())) 374 if err := p.process(pssmsg); err != nil { 375 qerr := p.enqueue(pssmsg) 376 if qerr != nil { 377 return fmt.Errorf("process fail: processerr %v, queueerr: %v", err, qerr) 378 } 379 } 380 return nil 381 382 } 383 384 // Entry point to processing a message for which the current node can be the intended recipient. 385 // Attempts symmetric and asymmetric decryption with stored keys. 386 // Dispatches message to all handlers matching the message topic 387 func (p *Pss) process(pssmsg *PssMsg) error { 388 metrics.GetOrRegisterCounter("pss.process", nil).Inc(1) 389 390 var err error 391 var recvmsg *whisper.ReceivedMessage 392 var payload []byte 393 var from *PssAddress 394 var asymmetric bool 395 var keyid string 396 var keyFunc func(envelope *whisper.Envelope) (*whisper.ReceivedMessage, string, *PssAddress, error) 397 398 envelope := pssmsg.Payload 399 psstopic := Topic(envelope.Topic) 400 if pssmsg.isRaw() { 401 if !p.allowRaw { 402 return errors.New("raw message support disabled") 403 } 404 payload = pssmsg.Payload.Data 405 } else { 406 if pssmsg.isSym() { 407 keyFunc = p.processSym 408 } else { 409 asymmetric = true 410 keyFunc = p.processAsym 411 } 412 413 recvmsg, keyid, from, err = keyFunc(envelope) 414 if err != nil { 415 return errors.New("Decryption failed") 416 } 417 payload = recvmsg.Payload 418 } 419 420 if len(pssmsg.To) < addressLength { 421 if err := p.enqueue(pssmsg); err != nil { 422 return err 423 } 424 } 425 p.executeHandlers(psstopic, payload, from, asymmetric, keyid) 426 427 return nil 428 429 } 430 431 func (p *Pss) executeHandlers(topic Topic, payload []byte, from *PssAddress, asymmetric bool, keyid string) { 432 handlers := p.getHandlers(topic) 433 nid, _ := discover.HexID("0x00") // this hack is needed to satisfy the p2p method 434 peer := p2p.NewPeer(nid, fmt.Sprintf("%x", from), []p2p.Cap{}) 435 for f := range handlers { 436 err := (*f)(payload, peer, asymmetric, keyid) 437 if err != nil { 438 log.Warn("Pss handler %p failed: %v", f, err) 439 } 440 } 441 } 442 443 // will return false if using partial address 444 func (p *Pss) isSelfRecipient(msg *PssMsg) bool { 445 return bytes.Equal(msg.To, p.Kademlia.BaseAddr()) 446 } 447 448 // test match of leftmost bytes in given message to node's Kademlia address 449 func (p *Pss) isSelfPossibleRecipient(msg *PssMsg) bool { 450 local := p.Kademlia.BaseAddr() 451 return bytes.Equal(msg.To, local[:len(msg.To)]) 452 } 453 454 ///////////////////////////////////////////////////////////////////// 455 // SECTION: Encryption 456 ///////////////////////////////////////////////////////////////////// 457 458 // Links a peer ECDSA public key to a topic 459 // 460 // This is required for asymmetric message exchange 461 // on the given topic 462 // 463 // The value in `address` will be used as a routing hint for the 464 // public key / topic association 465 func (p *Pss) SetPeerPublicKey(pubkey *ecdsa.PublicKey, topic Topic, address *PssAddress) error { 466 pubkeybytes := crypto.FromECDSAPub(pubkey) 467 if len(pubkeybytes) == 0 { 468 return fmt.Errorf("invalid public key: %v", pubkey) 469 } 470 pubkeyid := common.ToHex(pubkeybytes) 471 psp := &pssPeer{ 472 address: address, 473 } 474 p.pubKeyPoolMu.Lock() 475 if _, ok := p.pubKeyPool[pubkeyid]; !ok { 476 p.pubKeyPool[pubkeyid] = make(map[Topic]*pssPeer) 477 } 478 p.pubKeyPool[pubkeyid][topic] = psp 479 p.pubKeyPoolMu.Unlock() 480 log.Trace("added pubkey", "pubkeyid", pubkeyid, "topic", topic, "address", common.ToHex(*address)) 481 return nil 482 } 483 484 // Automatically generate a new symkey for a topic and address hint 485 func (p *Pss) GenerateSymmetricKey(topic Topic, address *PssAddress, addToCache bool) (string, error) { 486 keyid, err := p.w.GenerateSymKey() 487 if err != nil { 488 return "", err 489 } 490 p.addSymmetricKeyToPool(keyid, topic, address, addToCache, false) 491 return keyid, nil 492 } 493 494 // Links a peer symmetric key (arbitrary byte sequence) to a topic 495 // 496 // This is required for symmetrically encrypted message exchange 497 // on the given topic 498 // 499 // The key is stored in the whisper backend. 500 // 501 // If addtocache is set to true, the key will be added to the cache of keys 502 // used to attempt symmetric decryption of incoming messages. 503 // 504 // Returns a string id that can be used to retrieve the key bytes 505 // from the whisper backend (see pss.GetSymmetricKey()) 506 func (p *Pss) SetSymmetricKey(key []byte, topic Topic, address *PssAddress, addtocache bool) (string, error) { 507 return p.setSymmetricKey(key, topic, address, addtocache, true) 508 } 509 510 func (p *Pss) setSymmetricKey(key []byte, topic Topic, address *PssAddress, addtocache bool, protected bool) (string, error) { 511 keyid, err := p.w.AddSymKeyDirect(key) 512 if err != nil { 513 return "", err 514 } 515 p.addSymmetricKeyToPool(keyid, topic, address, addtocache, protected) 516 return keyid, nil 517 } 518 519 // adds a symmetric key to the pss key pool, and optionally adds the key 520 // to the collection of keys used to attempt symmetric decryption of 521 // incoming messages 522 func (p *Pss) addSymmetricKeyToPool(keyid string, topic Topic, address *PssAddress, addtocache bool, protected bool) { 523 psp := &pssPeer{ 524 address: address, 525 protected: protected, 526 } 527 p.symKeyPoolMu.Lock() 528 if _, ok := p.symKeyPool[keyid]; !ok { 529 p.symKeyPool[keyid] = make(map[Topic]*pssPeer) 530 } 531 p.symKeyPool[keyid][topic] = psp 532 p.symKeyPoolMu.Unlock() 533 if addtocache { 534 p.symKeyDecryptCacheCursor++ 535 p.symKeyDecryptCache[p.symKeyDecryptCacheCursor%cap(p.symKeyDecryptCache)] = &keyid 536 } 537 key, _ := p.GetSymmetricKey(keyid) 538 log.Trace("added symkey", "symkeyid", keyid, "symkey", common.ToHex(key), "topic", topic, "address", fmt.Sprintf("%p", address), "cache", addtocache) 539 } 540 541 // Returns a symmetric key byte seqyence stored in the whisper backend 542 // by its unique id 543 // 544 // Passes on the error value from the whisper backend 545 func (p *Pss) GetSymmetricKey(symkeyid string) ([]byte, error) { 546 symkey, err := p.w.GetSymKey(symkeyid) 547 if err != nil { 548 return nil, err 549 } 550 return symkey, nil 551 } 552 553 // Returns all recorded topic and address combination for a specific public key 554 func (p *Pss) GetPublickeyPeers(keyid string) (topic []Topic, address []PssAddress, err error) { 555 p.pubKeyPoolMu.RLock() 556 defer p.pubKeyPoolMu.RUnlock() 557 for t, peer := range p.pubKeyPool[keyid] { 558 topic = append(topic, t) 559 address = append(address, *peer.address) 560 } 561 562 return topic, address, nil 563 } 564 565 func (p *Pss) getPeerAddress(keyid string, topic Topic) (PssAddress, error) { 566 p.pubKeyPoolMu.RLock() 567 defer p.pubKeyPoolMu.RUnlock() 568 if peers, ok := p.pubKeyPool[keyid]; ok { 569 if t, ok := peers[topic]; ok { 570 return *t.address, nil 571 } 572 } 573 return nil, fmt.Errorf("peer with pubkey %s, topic %x not found", keyid, topic) 574 } 575 576 // Attempt to decrypt, validate and unpack a 577 // symmetrically encrypted message 578 // If successful, returns the unpacked whisper ReceivedMessage struct 579 // encapsulating the decrypted message, and the whisper backend id 580 // of the symmetric key used to decrypt the message. 581 // It fails if decryption of the message fails or if the message is corrupted 582 func (p *Pss) processSym(envelope *whisper.Envelope) (*whisper.ReceivedMessage, string, *PssAddress, error) { 583 metrics.GetOrRegisterCounter("pss.process.sym", nil).Inc(1) 584 585 for i := p.symKeyDecryptCacheCursor; i > p.symKeyDecryptCacheCursor-cap(p.symKeyDecryptCache) && i > 0; i-- { 586 symkeyid := p.symKeyDecryptCache[i%cap(p.symKeyDecryptCache)] 587 symkey, err := p.w.GetSymKey(*symkeyid) 588 if err != nil { 589 continue 590 } 591 recvmsg, err := envelope.OpenSymmetric(symkey) 592 if err != nil { 593 continue 594 } 595 if !recvmsg.Validate() { 596 return nil, "", nil, fmt.Errorf("symmetrically encrypted message has invalid signature or is corrupt") 597 } 598 p.symKeyPoolMu.Lock() 599 from := p.symKeyPool[*symkeyid][Topic(envelope.Topic)].address 600 p.symKeyPoolMu.Unlock() 601 p.symKeyDecryptCacheCursor++ 602 p.symKeyDecryptCache[p.symKeyDecryptCacheCursor%cap(p.symKeyDecryptCache)] = symkeyid 603 return recvmsg, *symkeyid, from, nil 604 } 605 return nil, "", nil, fmt.Errorf("could not decrypt message") 606 } 607 608 // Attempt to decrypt, validate and unpack an 609 // asymmetrically encrypted message 610 // If successful, returns the unpacked whisper ReceivedMessage struct 611 // encapsulating the decrypted message, and the byte representation of 612 // the public key used to decrypt the message. 613 // It fails if decryption of message fails, or if the message is corrupted 614 func (p *Pss) processAsym(envelope *whisper.Envelope) (*whisper.ReceivedMessage, string, *PssAddress, error) { 615 metrics.GetOrRegisterCounter("pss.process.asym", nil).Inc(1) 616 617 recvmsg, err := envelope.OpenAsymmetric(p.privateKey) 618 if err != nil { 619 return nil, "", nil, fmt.Errorf("could not decrypt message: %s", err) 620 } 621 // check signature (if signed), strip padding 622 if !recvmsg.Validate() { 623 return nil, "", nil, fmt.Errorf("invalid message") 624 } 625 pubkeyid := common.ToHex(crypto.FromECDSAPub(recvmsg.Src)) 626 var from *PssAddress 627 p.pubKeyPoolMu.Lock() 628 if p.pubKeyPool[pubkeyid][Topic(envelope.Topic)] != nil { 629 from = p.pubKeyPool[pubkeyid][Topic(envelope.Topic)].address 630 } 631 p.pubKeyPoolMu.Unlock() 632 return recvmsg, pubkeyid, from, nil 633 } 634 635 // Symkey garbage collection 636 // a key is removed if: 637 // - it is not marked as protected 638 // - it is not in the incoming decryption cache 639 func (p *Pss) cleanKeys() (count int) { 640 for keyid, peertopics := range p.symKeyPool { 641 var expiredtopics []Topic 642 for topic, psp := range peertopics { 643 if psp.protected { 644 continue 645 } 646 647 var match bool 648 for i := p.symKeyDecryptCacheCursor; i > p.symKeyDecryptCacheCursor-cap(p.symKeyDecryptCache) && i > 0; i-- { 649 cacheid := p.symKeyDecryptCache[i%cap(p.symKeyDecryptCache)] 650 if *cacheid == keyid { 651 match = true 652 } 653 } 654 if !match { 655 expiredtopics = append(expiredtopics, topic) 656 } 657 } 658 for _, topic := range expiredtopics { 659 p.symKeyPoolMu.Lock() 660 delete(p.symKeyPool[keyid], topic) 661 log.Trace("symkey cleanup deletion", "symkeyid", keyid, "topic", topic, "val", p.symKeyPool[keyid]) 662 p.symKeyPoolMu.Unlock() 663 count++ 664 } 665 } 666 return 667 } 668 669 ///////////////////////////////////////////////////////////////////// 670 // SECTION: Message sending 671 ///////////////////////////////////////////////////////////////////// 672 673 func (p *Pss) enqueue(msg *PssMsg) error { 674 select { 675 case p.outbox <- msg: 676 return nil 677 default: 678 } 679 680 metrics.GetOrRegisterCounter("pss.enqueue.outbox.full", nil).Inc(1) 681 return errors.New("outbox full") 682 } 683 684 // Send a raw message (any encryption is responsibility of calling client) 685 // 686 // Will fail if raw messages are disallowed 687 func (p *Pss) SendRaw(address PssAddress, topic Topic, msg []byte) error { 688 if !p.allowRaw { 689 return errors.New("Raw messages not enabled") 690 } 691 pssMsgParams := &msgParams{ 692 raw: true, 693 } 694 payload := &whisper.Envelope{ 695 Data: msg, 696 Topic: whisper.TopicType(topic), 697 } 698 pssMsg := newPssMsg(pssMsgParams) 699 pssMsg.To = address 700 pssMsg.Expire = uint32(time.Now().Add(p.msgTTL).Unix()) 701 pssMsg.Payload = payload 702 p.addFwdCache(pssMsg) 703 return p.enqueue(pssMsg) 704 } 705 706 // Send a message using symmetric encryption 707 // 708 // Fails if the key id does not match any of the stored symmetric keys 709 func (p *Pss) SendSym(symkeyid string, topic Topic, msg []byte) error { 710 symkey, err := p.GetSymmetricKey(symkeyid) 711 if err != nil { 712 return fmt.Errorf("missing valid send symkey %s: %v", symkeyid, err) 713 } 714 p.symKeyPoolMu.Lock() 715 psp, ok := p.symKeyPool[symkeyid][topic] 716 p.symKeyPoolMu.Unlock() 717 if !ok { 718 return fmt.Errorf("invalid topic '%s' for symkey '%s'", topic.String(), symkeyid) 719 } else if psp.address == nil { 720 return fmt.Errorf("no address hint for topic '%s' symkey '%s'", topic.String(), symkeyid) 721 } 722 err = p.send(*psp.address, topic, msg, false, symkey) 723 return err 724 } 725 726 // Send a message using asymmetric encryption 727 // 728 // Fails if the key id does not match any in of the stored public keys 729 func (p *Pss) SendAsym(pubkeyid string, topic Topic, msg []byte) error { 730 if _, err := crypto.UnmarshalPubkey(common.FromHex(pubkeyid)); err != nil { 731 return fmt.Errorf("Cannot unmarshal pubkey: %x", pubkeyid) 732 } 733 p.pubKeyPoolMu.Lock() 734 psp, ok := p.pubKeyPool[pubkeyid][topic] 735 p.pubKeyPoolMu.Unlock() 736 if !ok { 737 return fmt.Errorf("invalid topic '%s' for pubkey '%s'", topic.String(), pubkeyid) 738 } else if psp.address == nil { 739 return fmt.Errorf("no address hint for topic '%s' pubkey '%s'", topic.String(), pubkeyid) 740 } 741 go func() { 742 p.send(*psp.address, topic, msg, true, common.FromHex(pubkeyid)) 743 }() 744 return nil 745 } 746 747 // Send is payload agnostic, and will accept any byte slice as payload 748 // It generates an whisper envelope for the specified recipient and topic, 749 // and wraps the message payload in it. 750 // TODO: Implement proper message padding 751 func (p *Pss) send(to []byte, topic Topic, msg []byte, asymmetric bool, key []byte) error { 752 metrics.GetOrRegisterCounter("pss.send", nil).Inc(1) 753 754 if key == nil || bytes.Equal(key, []byte{}) { 755 return fmt.Errorf("Zero length key passed to pss send") 756 } 757 padding := make([]byte, p.paddingByteSize) 758 c, err := rand.Read(padding) 759 if err != nil { 760 return err 761 } else if c < p.paddingByteSize { 762 return fmt.Errorf("invalid padding length: %d", c) 763 } 764 wparams := &whisper.MessageParams{ 765 TTL: defaultWhisperTTL, 766 Src: p.privateKey, 767 Topic: whisper.TopicType(topic), 768 WorkTime: defaultWhisperWorkTime, 769 PoW: defaultWhisperPoW, 770 Payload: msg, 771 Padding: padding, 772 } 773 if asymmetric { 774 pk, err := crypto.UnmarshalPubkey(key) 775 if err != nil { 776 return fmt.Errorf("Cannot unmarshal pubkey: %x", key) 777 } 778 wparams.Dst = pk 779 } else { 780 wparams.KeySym = key 781 } 782 // set up outgoing message container, which does encryption and envelope wrapping 783 woutmsg, err := whisper.NewSentMessage(wparams) 784 if err != nil { 785 return fmt.Errorf("failed to generate whisper message encapsulation: %v", err) 786 } 787 // performs encryption. 788 // Does NOT perform / performs negligible PoW due to very low difficulty setting 789 // after this the message is ready for sending 790 envelope, err := woutmsg.Wrap(wparams) 791 if err != nil { 792 return fmt.Errorf("failed to perform whisper encryption: %v", err) 793 } 794 log.Trace("pssmsg whisper done", "env", envelope, "wparams payload", common.ToHex(wparams.Payload), "to", common.ToHex(to), "asym", asymmetric, "key", common.ToHex(key)) 795 796 // prepare for devp2p transport 797 pssMsgParams := &msgParams{ 798 sym: !asymmetric, 799 } 800 pssMsg := newPssMsg(pssMsgParams) 801 pssMsg.To = to 802 pssMsg.Expire = uint32(time.Now().Add(p.msgTTL).Unix()) 803 pssMsg.Payload = envelope 804 return p.enqueue(pssMsg) 805 } 806 807 // Forwards a pss message to the peer(s) closest to the to recipient address in the PssMsg struct 808 // The recipient address can be of any length, and the byte slice will be matched to the MSB slice 809 // of the peer address of the equivalent length. 810 func (p *Pss) forward(msg *PssMsg) error { 811 metrics.GetOrRegisterCounter("pss.forward", nil).Inc(1) 812 813 to := make([]byte, addressLength) 814 copy(to[:len(msg.To)], msg.To) 815 816 // send with kademlia 817 // find the closest peer to the recipient and attempt to send 818 sent := 0 819 p.Kademlia.EachConn(to, 256, func(sp *network.Peer, po int, isproxbin bool) bool { 820 info := sp.Info() 821 822 // check if the peer is running pss 823 var ispss bool 824 for _, cap := range info.Caps { 825 if cap == p.capstring { 826 ispss = true 827 break 828 } 829 } 830 if !ispss { 831 log.Trace("peer doesn't have matching pss capabilities, skipping", "peer", info.Name, "caps", info.Caps) 832 return true 833 } 834 835 // get the protocol peer from the forwarding peer cache 836 sendMsg := fmt.Sprintf("MSG TO %x FROM %x VIA %x", to, p.BaseAddr(), sp.Address()) 837 p.fwdPoolMu.RLock() 838 pp := p.fwdPool[sp.Info().ID] 839 p.fwdPoolMu.RUnlock() 840 841 // attempt to send the message 842 err := pp.Send(context.TODO(), msg) 843 if err != nil { 844 metrics.GetOrRegisterCounter("pss.pp.send.error", nil).Inc(1) 845 log.Error(err.Error()) 846 return true 847 } 848 sent++ 849 log.Trace(fmt.Sprintf("%v: successfully forwarded", sendMsg)) 850 851 // continue forwarding if: 852 // - if the peer is end recipient but the full address has not been disclosed 853 // - if the peer address matches the partial address fully 854 // - if the peer is in proxbin 855 if len(msg.To) < addressLength && bytes.Equal(msg.To, sp.Address()[:len(msg.To)]) { 856 log.Trace(fmt.Sprintf("Pss keep forwarding: Partial address + full partial match")) 857 return true 858 } else if isproxbin { 859 log.Trace(fmt.Sprintf("%x is in proxbin, keep forwarding", common.ToHex(sp.Address()))) 860 return true 861 } 862 // at this point we stop forwarding, and the state is as follows: 863 // - the peer is end recipient and we have full address 864 // - we are not in proxbin (directed routing) 865 // - partial addresses don't fully match 866 return false 867 }) 868 869 if sent == 0 { 870 log.Debug("unable to forward to any peers") 871 if err := p.enqueue(msg); err != nil { 872 metrics.GetOrRegisterCounter("pss.forward.enqueue.error", nil).Inc(1) 873 log.Error(err.Error()) 874 return err 875 } 876 } 877 878 // cache the message 879 p.addFwdCache(msg) 880 return nil 881 } 882 883 ///////////////////////////////////////////////////////////////////// 884 // SECTION: Caching 885 ///////////////////////////////////////////////////////////////////// 886 887 // cleanFwdCache is used to periodically remove expired entries from the forward cache 888 func (p *Pss) cleanFwdCache() { 889 metrics.GetOrRegisterCounter("pss.cleanfwdcache", nil).Inc(1) 890 p.fwdCacheMu.Lock() 891 defer p.fwdCacheMu.Unlock() 892 for k, v := range p.fwdCache { 893 if v.expiresAt.Before(time.Now()) { 894 delete(p.fwdCache, k) 895 } 896 } 897 } 898 899 // add a message to the cache 900 func (p *Pss) addFwdCache(msg *PssMsg) error { 901 metrics.GetOrRegisterCounter("pss.addfwdcache", nil).Inc(1) 902 903 var entry pssCacheEntry 904 var ok bool 905 906 p.fwdCacheMu.Lock() 907 defer p.fwdCacheMu.Unlock() 908 909 digest := p.digest(msg) 910 if entry, ok = p.fwdCache[digest]; !ok { 911 entry = pssCacheEntry{} 912 } 913 entry.expiresAt = time.Now().Add(p.cacheTTL) 914 p.fwdCache[digest] = entry 915 return nil 916 } 917 918 // check if message is in the cache 919 func (p *Pss) checkFwdCache(msg *PssMsg) bool { 920 p.fwdCacheMu.Lock() 921 defer p.fwdCacheMu.Unlock() 922 923 digest := p.digest(msg) 924 entry, ok := p.fwdCache[digest] 925 if ok { 926 if entry.expiresAt.After(time.Now()) { 927 log.Trace("unexpired cache", "digest", fmt.Sprintf("%x", digest)) 928 metrics.GetOrRegisterCounter("pss.checkfwdcache.unexpired", nil).Inc(1) 929 return true 930 } 931 metrics.GetOrRegisterCounter("pss.checkfwdcache.expired", nil).Inc(1) 932 } 933 return false 934 } 935 936 // Digest of message 937 func (p *Pss) digest(msg *PssMsg) pssDigest { 938 hasher := p.hashPool.Get().(storage.SwarmHash) 939 defer p.hashPool.Put(hasher) 940 hasher.Reset() 941 hasher.Write(msg.serialize()) 942 digest := pssDigest{} 943 key := hasher.Sum(nil) 944 copy(digest[:], key[:digestLength]) 945 return digest 946 }