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