github.com/insight-chain/inb-go@v1.1.3-0.20191221022159-da049980ae38/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/insight-chain/inb-go/common" 31 "github.com/insight-chain/inb-go/crypto" 32 "github.com/insight-chain/inb-go/crypto/sha3" 33 "github.com/insight-chain/inb-go/metrics" 34 "github.com/insight-chain/inb-go/p2p" 35 "github.com/insight-chain/inb-go/p2p/enode" 36 "github.com/insight-chain/inb-go/p2p/protocols" 37 "github.com/insight-chain/inb-go/rpc" 38 "github.com/insight-chain/inb-go/swarm/log" 39 "github.com/insight-chain/inb-go/swarm/network" 40 "github.com/insight-chain/inb-go/swarm/pot" 41 "github.com/insight-chain/inb-go/swarm/storage" 42 whisper "github.com/insight-chain/inb-go/whisper/whisperv5" 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.NewKeccak256() 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 !p.topicHandlerCaps[psstopic].raw { 400 log.Debug("No handler for raw message", "topic", psstopic) 401 return nil 402 } 403 isRaw = true 404 } 405 406 // check if we can be recipient: 407 // - no prox handler on message and partial address matches 408 // - prox handler on message and we are in prox regardless of partial address match 409 // store this result so we don't calculate again on every handler 410 var isProx bool 411 if _, ok := p.topicHandlerCaps[psstopic]; ok { 412 isProx = p.topicHandlerCaps[psstopic].prox 413 } 414 isRecipient := p.isSelfPossibleRecipient(pssmsg, isProx) 415 if !isRecipient { 416 log.Trace("pss was for someone else :'( ... forwarding", "pss", common.ToHex(p.BaseAddr()), "prox", isProx) 417 return p.enqueue(pssmsg) 418 } 419 420 log.Trace("pss for us, yay! ... let's process!", "pss", common.ToHex(p.BaseAddr()), "prox", isProx, "raw", isRaw, "topic", label(pssmsg.Payload.Topic[:])) 421 if err := p.process(pssmsg, isRaw, isProx); err != nil { 422 qerr := p.enqueue(pssmsg) 423 if qerr != nil { 424 return fmt.Errorf("process fail: processerr %v, queueerr: %v", err, qerr) 425 } 426 } 427 return nil 428 429 } 430 431 // Entry point to processing a message for which the current node can be the intended recipient. 432 // Attempts symmetric and asymmetric decryption with stored keys. 433 // Dispatches message to all handlers matching the message topic 434 func (p *Pss) process(pssmsg *PssMsg, raw bool, prox bool) error { 435 metrics.GetOrRegisterCounter("pss.process", nil).Inc(1) 436 437 var err error 438 var recvmsg *whisper.ReceivedMessage 439 var payload []byte 440 var from *PssAddress 441 var asymmetric bool 442 var keyid string 443 var keyFunc func(envelope *whisper.Envelope) (*whisper.ReceivedMessage, string, *PssAddress, error) 444 445 envelope := pssmsg.Payload 446 psstopic := Topic(envelope.Topic) 447 448 if raw { 449 payload = pssmsg.Payload.Data 450 } else { 451 if pssmsg.isSym() { 452 keyFunc = p.processSym 453 } else { 454 asymmetric = true 455 keyFunc = p.processAsym 456 } 457 458 recvmsg, keyid, from, err = keyFunc(envelope) 459 if err != nil { 460 return errors.New("Decryption failed") 461 } 462 payload = recvmsg.Payload 463 } 464 465 if len(pssmsg.To) < addressLength { 466 if err := p.enqueue(pssmsg); err != nil { 467 return err 468 } 469 } 470 p.executeHandlers(psstopic, payload, from, raw, prox, asymmetric, keyid) 471 472 return nil 473 474 } 475 476 func (p *Pss) executeHandlers(topic Topic, payload []byte, from *PssAddress, raw bool, prox bool, asymmetric bool, keyid string) { 477 handlers := p.getHandlers(topic) 478 peer := p2p.NewPeer(enode.ID{}, fmt.Sprintf("%x", from), []p2p.Cap{}) 479 for h := range handlers { 480 if !h.caps.raw && raw { 481 log.Warn("norawhandler") 482 continue 483 } 484 if !h.caps.prox && prox { 485 log.Warn("noproxhandler") 486 continue 487 } 488 err := (h.f)(payload, peer, asymmetric, keyid) 489 if err != nil { 490 log.Warn("Pss handler failed", "err", err) 491 } 492 } 493 } 494 495 // will return false if using partial address 496 func (p *Pss) isSelfRecipient(msg *PssMsg) bool { 497 return bytes.Equal(msg.To, p.Kademlia.BaseAddr()) 498 } 499 500 // test match of leftmost bytes in given message to node's Kademlia address 501 func (p *Pss) isSelfPossibleRecipient(msg *PssMsg, prox bool) bool { 502 local := p.Kademlia.BaseAddr() 503 504 // if a partial address matches we are possible recipient regardless of prox 505 // if not and prox is not set, we are surely not 506 if bytes.Equal(msg.To, local[:len(msg.To)]) { 507 508 return true 509 } else if !prox { 510 return false 511 } 512 513 depth := p.Kademlia.NeighbourhoodDepth() 514 po, _ := p.Kademlia.Pof(p.Kademlia.BaseAddr(), msg.To, 0) 515 log.Trace("selfpossible", "po", po, "depth", depth) 516 517 return depth <= po 518 } 519 520 ///////////////////////////////////////////////////////////////////// 521 // SECTION: Encryption 522 ///////////////////////////////////////////////////////////////////// 523 524 // Links a peer ECDSA public key to a topic 525 // 526 // This is required for asymmetric message exchange 527 // on the given topic 528 // 529 // The value in `address` will be used as a routing hint for the 530 // public key / topic association 531 func (p *Pss) SetPeerPublicKey(pubkey *ecdsa.PublicKey, topic Topic, address *PssAddress) error { 532 pubkeybytes := crypto.FromECDSAPub(pubkey) 533 if len(pubkeybytes) == 0 { 534 return fmt.Errorf("invalid public key: %v", pubkey) 535 } 536 pubkeyid := common.ToHex(pubkeybytes) 537 psp := &pssPeer{ 538 address: address, 539 } 540 p.pubKeyPoolMu.Lock() 541 if _, ok := p.pubKeyPool[pubkeyid]; !ok { 542 p.pubKeyPool[pubkeyid] = make(map[Topic]*pssPeer) 543 } 544 p.pubKeyPool[pubkeyid][topic] = psp 545 p.pubKeyPoolMu.Unlock() 546 log.Trace("added pubkey", "pubkeyid", pubkeyid, "topic", topic, "address", common.ToHex(*address)) 547 return nil 548 } 549 550 // Automatically generate a new symkey for a topic and address hint 551 func (p *Pss) GenerateSymmetricKey(topic Topic, address *PssAddress, addToCache bool) (string, error) { 552 keyid, err := p.w.GenerateSymKey() 553 if err != nil { 554 return "", err 555 } 556 p.addSymmetricKeyToPool(keyid, topic, address, addToCache, false) 557 return keyid, nil 558 } 559 560 // Links a peer symmetric key (arbitrary byte sequence) to a topic 561 // 562 // This is required for symmetrically encrypted message exchange 563 // on the given topic 564 // 565 // The key is stored in the whisper backend. 566 // 567 // If addtocache is set to true, the key will be added to the cache of keys 568 // used to attempt symmetric decryption of incoming messages. 569 // 570 // Returns a string id that can be used to retrieve the key bytes 571 // from the whisper backend (see pss.GetSymmetricKey()) 572 func (p *Pss) SetSymmetricKey(key []byte, topic Topic, address *PssAddress, addtocache bool) (string, error) { 573 return p.setSymmetricKey(key, topic, address, addtocache, true) 574 } 575 576 func (p *Pss) setSymmetricKey(key []byte, topic Topic, address *PssAddress, addtocache bool, protected bool) (string, error) { 577 keyid, err := p.w.AddSymKeyDirect(key) 578 if err != nil { 579 return "", err 580 } 581 p.addSymmetricKeyToPool(keyid, topic, address, addtocache, protected) 582 return keyid, nil 583 } 584 585 // adds a symmetric key to the pss key pool, and optionally adds the key 586 // to the collection of keys used to attempt symmetric decryption of 587 // incoming messages 588 func (p *Pss) addSymmetricKeyToPool(keyid string, topic Topic, address *PssAddress, addtocache bool, protected bool) { 589 psp := &pssPeer{ 590 address: address, 591 protected: protected, 592 } 593 p.symKeyPoolMu.Lock() 594 if _, ok := p.symKeyPool[keyid]; !ok { 595 p.symKeyPool[keyid] = make(map[Topic]*pssPeer) 596 } 597 p.symKeyPool[keyid][topic] = psp 598 p.symKeyPoolMu.Unlock() 599 if addtocache { 600 p.symKeyDecryptCacheCursor++ 601 p.symKeyDecryptCache[p.symKeyDecryptCacheCursor%cap(p.symKeyDecryptCache)] = &keyid 602 } 603 key, _ := p.GetSymmetricKey(keyid) 604 log.Trace("added symkey", "symkeyid", keyid, "symkey", common.ToHex(key), "topic", topic, "address", fmt.Sprintf("%p", address), "cache", addtocache) 605 } 606 607 // Returns a symmetric key byte seqyence stored in the whisper backend 608 // by its unique id 609 // 610 // Passes on the error value from the whisper backend 611 func (p *Pss) GetSymmetricKey(symkeyid string) ([]byte, error) { 612 symkey, err := p.w.GetSymKey(symkeyid) 613 if err != nil { 614 return nil, err 615 } 616 return symkey, nil 617 } 618 619 // Returns all recorded topic and address combination for a specific public key 620 func (p *Pss) GetPublickeyPeers(keyid string) (topic []Topic, address []PssAddress, err error) { 621 p.pubKeyPoolMu.RLock() 622 defer p.pubKeyPoolMu.RUnlock() 623 for t, peer := range p.pubKeyPool[keyid] { 624 topic = append(topic, t) 625 address = append(address, *peer.address) 626 } 627 628 return topic, address, nil 629 } 630 631 func (p *Pss) getPeerAddress(keyid string, topic Topic) (PssAddress, error) { 632 p.pubKeyPoolMu.RLock() 633 defer p.pubKeyPoolMu.RUnlock() 634 if peers, ok := p.pubKeyPool[keyid]; ok { 635 if t, ok := peers[topic]; ok { 636 return *t.address, nil 637 } 638 } 639 return nil, fmt.Errorf("peer with pubkey %s, topic %x not found", keyid, topic) 640 } 641 642 // Attempt to decrypt, validate and unpack a 643 // symmetrically encrypted message 644 // If successful, returns the unpacked whisper ReceivedMessage struct 645 // encapsulating the decrypted message, and the whisper backend id 646 // of the symmetric key used to decrypt the message. 647 // It fails if decryption of the message fails or if the message is corrupted 648 func (p *Pss) processSym(envelope *whisper.Envelope) (*whisper.ReceivedMessage, string, *PssAddress, error) { 649 metrics.GetOrRegisterCounter("pss.process.sym", nil).Inc(1) 650 651 for i := p.symKeyDecryptCacheCursor; i > p.symKeyDecryptCacheCursor-cap(p.symKeyDecryptCache) && i > 0; i-- { 652 symkeyid := p.symKeyDecryptCache[i%cap(p.symKeyDecryptCache)] 653 symkey, err := p.w.GetSymKey(*symkeyid) 654 if err != nil { 655 continue 656 } 657 recvmsg, err := envelope.OpenSymmetric(symkey) 658 if err != nil { 659 continue 660 } 661 if !recvmsg.Validate() { 662 return nil, "", nil, fmt.Errorf("symmetrically encrypted message has invalid signature or is corrupt") 663 } 664 p.symKeyPoolMu.Lock() 665 from := p.symKeyPool[*symkeyid][Topic(envelope.Topic)].address 666 p.symKeyPoolMu.Unlock() 667 p.symKeyDecryptCacheCursor++ 668 p.symKeyDecryptCache[p.symKeyDecryptCacheCursor%cap(p.symKeyDecryptCache)] = symkeyid 669 return recvmsg, *symkeyid, from, nil 670 } 671 return nil, "", nil, fmt.Errorf("could not decrypt message") 672 } 673 674 // Attempt to decrypt, validate and unpack an 675 // asymmetrically encrypted message 676 // If successful, returns the unpacked whisper ReceivedMessage struct 677 // encapsulating the decrypted message, and the byte representation of 678 // the public key used to decrypt the message. 679 // It fails if decryption of message fails, or if the message is corrupted 680 func (p *Pss) processAsym(envelope *whisper.Envelope) (*whisper.ReceivedMessage, string, *PssAddress, error) { 681 metrics.GetOrRegisterCounter("pss.process.asym", nil).Inc(1) 682 683 recvmsg, err := envelope.OpenAsymmetric(p.privateKey) 684 if err != nil { 685 return nil, "", nil, fmt.Errorf("could not decrypt message: %s", err) 686 } 687 // check signature (if signed), strip padding 688 if !recvmsg.Validate() { 689 return nil, "", nil, fmt.Errorf("invalid message") 690 } 691 pubkeyid := common.ToHex(crypto.FromECDSAPub(recvmsg.Src)) 692 var from *PssAddress 693 p.pubKeyPoolMu.Lock() 694 if p.pubKeyPool[pubkeyid][Topic(envelope.Topic)] != nil { 695 from = p.pubKeyPool[pubkeyid][Topic(envelope.Topic)].address 696 } 697 p.pubKeyPoolMu.Unlock() 698 return recvmsg, pubkeyid, from, nil 699 } 700 701 // Symkey garbage collection 702 // a key is removed if: 703 // - it is not marked as protected 704 // - it is not in the incoming decryption cache 705 func (p *Pss) cleanKeys() (count int) { 706 for keyid, peertopics := range p.symKeyPool { 707 var expiredtopics []Topic 708 for topic, psp := range peertopics { 709 if psp.protected { 710 continue 711 } 712 713 var match bool 714 for i := p.symKeyDecryptCacheCursor; i > p.symKeyDecryptCacheCursor-cap(p.symKeyDecryptCache) && i > 0; i-- { 715 cacheid := p.symKeyDecryptCache[i%cap(p.symKeyDecryptCache)] 716 if *cacheid == keyid { 717 match = true 718 } 719 } 720 if !match { 721 expiredtopics = append(expiredtopics, topic) 722 } 723 } 724 for _, topic := range expiredtopics { 725 p.symKeyPoolMu.Lock() 726 delete(p.symKeyPool[keyid], topic) 727 log.Trace("symkey cleanup deletion", "symkeyid", keyid, "topic", topic, "val", p.symKeyPool[keyid]) 728 p.symKeyPoolMu.Unlock() 729 count++ 730 } 731 } 732 return 733 } 734 735 ///////////////////////////////////////////////////////////////////// 736 // SECTION: Message sending 737 ///////////////////////////////////////////////////////////////////// 738 739 func (p *Pss) enqueue(msg *PssMsg) error { 740 select { 741 case p.outbox <- msg: 742 return nil 743 default: 744 } 745 746 metrics.GetOrRegisterCounter("pss.enqueue.outbox.full", nil).Inc(1) 747 return errors.New("outbox full") 748 } 749 750 // Send a raw message (any encryption is responsibility of calling client) 751 // 752 // Will fail if raw messages are disallowed 753 func (p *Pss) SendRaw(address PssAddress, topic Topic, msg []byte) error { 754 pssMsgParams := &msgParams{ 755 raw: true, 756 } 757 payload := &whisper.Envelope{ 758 Data: msg, 759 Topic: whisper.TopicType(topic), 760 } 761 pssMsg := newPssMsg(pssMsgParams) 762 pssMsg.To = address 763 pssMsg.Expire = uint32(time.Now().Add(p.msgTTL).Unix()) 764 pssMsg.Payload = payload 765 p.addFwdCache(pssMsg) 766 err := p.enqueue(pssMsg) 767 if err != nil { 768 return err 769 } 770 771 // if we have a proxhandler on this topic 772 // also deliver message to ourselves 773 if p.isSelfPossibleRecipient(pssMsg, true) && p.topicHandlerCaps[topic].prox { 774 return p.process(pssMsg, true, true) 775 } 776 return nil 777 } 778 779 // Send a message using symmetric encryption 780 // 781 // Fails if the key id does not match any of the stored symmetric keys 782 func (p *Pss) SendSym(symkeyid string, topic Topic, msg []byte) error { 783 symkey, err := p.GetSymmetricKey(symkeyid) 784 if err != nil { 785 return fmt.Errorf("missing valid send symkey %s: %v", symkeyid, err) 786 } 787 p.symKeyPoolMu.Lock() 788 psp, ok := p.symKeyPool[symkeyid][topic] 789 p.symKeyPoolMu.Unlock() 790 if !ok { 791 return fmt.Errorf("invalid topic '%s' for symkey '%s'", topic.String(), symkeyid) 792 } else if psp.address == nil { 793 return fmt.Errorf("no address hint for topic '%s' symkey '%s'", topic.String(), symkeyid) 794 } 795 err = p.send(*psp.address, topic, msg, false, symkey) 796 return err 797 } 798 799 // Send a message using asymmetric encryption 800 // 801 // Fails if the key id does not match any in of the stored public keys 802 func (p *Pss) SendAsym(pubkeyid string, topic Topic, msg []byte) error { 803 if _, err := crypto.UnmarshalPubkey(common.FromHex(pubkeyid)); err != nil { 804 return fmt.Errorf("Cannot unmarshal pubkey: %x", pubkeyid) 805 } 806 p.pubKeyPoolMu.Lock() 807 psp, ok := p.pubKeyPool[pubkeyid][topic] 808 p.pubKeyPoolMu.Unlock() 809 if !ok { 810 return fmt.Errorf("invalid topic '%s' for pubkey '%s'", topic.String(), pubkeyid) 811 } else if psp.address == nil { 812 return fmt.Errorf("no address hint for topic '%s' pubkey '%s'", topic.String(), pubkeyid) 813 } 814 go func() { 815 p.send(*psp.address, topic, msg, true, common.FromHex(pubkeyid)) 816 }() 817 return nil 818 } 819 820 // Send is payload agnostic, and will accept any byte slice as payload 821 // It generates an whisper envelope for the specified recipient and topic, 822 // and wraps the message payload in it. 823 // TODO: Implement proper message padding 824 func (p *Pss) send(to []byte, topic Topic, msg []byte, asymmetric bool, key []byte) error { 825 metrics.GetOrRegisterCounter("pss.send", nil).Inc(1) 826 827 if key == nil || bytes.Equal(key, []byte{}) { 828 return fmt.Errorf("Zero length key passed to pss send") 829 } 830 padding := make([]byte, p.paddingByteSize) 831 c, err := rand.Read(padding) 832 if err != nil { 833 return err 834 } else if c < p.paddingByteSize { 835 return fmt.Errorf("invalid padding length: %d", c) 836 } 837 wparams := &whisper.MessageParams{ 838 TTL: defaultWhisperTTL, 839 Src: p.privateKey, 840 Topic: whisper.TopicType(topic), 841 WorkTime: defaultWhisperWorkTime, 842 PoW: defaultWhisperPoW, 843 Payload: msg, 844 Padding: padding, 845 } 846 if asymmetric { 847 pk, err := crypto.UnmarshalPubkey(key) 848 if err != nil { 849 return fmt.Errorf("Cannot unmarshal pubkey: %x", key) 850 } 851 wparams.Dst = pk 852 } else { 853 wparams.KeySym = key 854 } 855 // set up outgoing message container, which does encryption and envelope wrapping 856 woutmsg, err := whisper.NewSentMessage(wparams) 857 if err != nil { 858 return fmt.Errorf("failed to generate whisper message encapsulation: %v", err) 859 } 860 // performs encryption. 861 // Does NOT perform / performs negligible PoW due to very low difficulty setting 862 // after this the message is ready for sending 863 envelope, err := woutmsg.Wrap(wparams) 864 if err != nil { 865 return fmt.Errorf("failed to perform whisper encryption: %v", err) 866 } 867 log.Trace("pssmsg whisper done", "env", envelope, "wparams payload", common.ToHex(wparams.Payload), "to", common.ToHex(to), "asym", asymmetric, "key", common.ToHex(key)) 868 869 // prepare for devp2p transport 870 pssMsgParams := &msgParams{ 871 sym: !asymmetric, 872 } 873 pssMsg := newPssMsg(pssMsgParams) 874 pssMsg.To = to 875 pssMsg.Expire = uint32(time.Now().Add(p.msgTTL).Unix()) 876 pssMsg.Payload = envelope 877 err = p.enqueue(pssMsg) 878 if err != nil { 879 return err 880 } 881 if _, ok := p.topicHandlerCaps[topic]; ok { 882 if p.isSelfPossibleRecipient(pssMsg, true) && p.topicHandlerCaps[topic].prox { 883 return p.process(pssMsg, true, true) 884 } 885 } 886 return nil 887 } 888 889 // Forwards a pss message to the peer(s) closest to the to recipient address in the PssMsg struct 890 // The recipient address can be of any length, and the byte slice will be matched to the MSB slice 891 // of the peer address of the equivalent length. 892 func (p *Pss) forward(msg *PssMsg) error { 893 metrics.GetOrRegisterCounter("pss.forward", nil).Inc(1) 894 895 to := make([]byte, addressLength) 896 copy(to[:len(msg.To)], msg.To) 897 898 // send with kademlia 899 // find the closest peer to the recipient and attempt to send 900 sent := 0 901 p.Kademlia.EachConn(to, 256, func(sp *network.Peer, po int, isproxbin bool) bool { 902 info := sp.Info() 903 904 // check if the peer is running pss 905 var ispss bool 906 for _, cap := range info.Caps { 907 if cap == p.capstring { 908 ispss = true 909 break 910 } 911 } 912 if !ispss { 913 log.Trace("peer doesn't have matching pss capabilities, skipping", "peer", info.Name, "caps", info.Caps) 914 return true 915 } 916 917 // get the protocol peer from the forwarding peer cache 918 sendMsg := fmt.Sprintf("MSG TO %x FROM %x VIA %x", to, p.BaseAddr(), sp.Address()) 919 p.fwdPoolMu.RLock() 920 pp := p.fwdPool[sp.Info().ID] 921 p.fwdPoolMu.RUnlock() 922 923 // attempt to send the message 924 err := pp.Send(context.TODO(), msg) 925 if err != nil { 926 metrics.GetOrRegisterCounter("pss.pp.send.error", nil).Inc(1) 927 log.Error(err.Error()) 928 return true 929 } 930 sent++ 931 log.Trace(fmt.Sprintf("%v: successfully forwarded", sendMsg)) 932 933 // continue forwarding if: 934 // - if the peer is end recipient but the full address has not been disclosed 935 // - if the peer address matches the partial address fully 936 // - if the peer is in proxbin 937 if len(msg.To) < addressLength && bytes.Equal(msg.To, sp.Address()[:len(msg.To)]) { 938 log.Trace(fmt.Sprintf("Pss keep forwarding: Partial address + full partial match")) 939 return true 940 } else if isproxbin { 941 log.Trace(fmt.Sprintf("%x is in proxbin, keep forwarding", common.ToHex(sp.Address()))) 942 return true 943 } 944 // at this point we stop forwarding, and the state is as follows: 945 // - the peer is end recipient and we have full address 946 // - we are not in proxbin (directed routing) 947 // - partial addresses don't fully match 948 return false 949 }) 950 951 if sent == 0 { 952 log.Debug("unable to forward to any peers") 953 if err := p.enqueue(msg); err != nil { 954 metrics.GetOrRegisterCounter("pss.forward.enqueue.error", nil).Inc(1) 955 log.Error(err.Error()) 956 return err 957 } 958 } 959 960 // cache the message 961 p.addFwdCache(msg) 962 return nil 963 } 964 965 ///////////////////////////////////////////////////////////////////// 966 // SECTION: Caching 967 ///////////////////////////////////////////////////////////////////// 968 969 // cleanFwdCache is used to periodically remove expired entries from the forward cache 970 func (p *Pss) cleanFwdCache() { 971 metrics.GetOrRegisterCounter("pss.cleanfwdcache", nil).Inc(1) 972 p.fwdCacheMu.Lock() 973 defer p.fwdCacheMu.Unlock() 974 for k, v := range p.fwdCache { 975 if v.expiresAt.Before(time.Now()) { 976 delete(p.fwdCache, k) 977 } 978 } 979 } 980 981 func label(b []byte) string { 982 return fmt.Sprintf("%04x", b[:2]) 983 } 984 985 // add a message to the cache 986 func (p *Pss) addFwdCache(msg *PssMsg) error { 987 metrics.GetOrRegisterCounter("pss.addfwdcache", nil).Inc(1) 988 989 var entry pssCacheEntry 990 var ok bool 991 992 p.fwdCacheMu.Lock() 993 defer p.fwdCacheMu.Unlock() 994 995 digest := p.digest(msg) 996 if entry, ok = p.fwdCache[digest]; !ok { 997 entry = pssCacheEntry{} 998 } 999 entry.expiresAt = time.Now().Add(p.cacheTTL) 1000 p.fwdCache[digest] = entry 1001 return nil 1002 } 1003 1004 // check if message is in the cache 1005 func (p *Pss) checkFwdCache(msg *PssMsg) bool { 1006 p.fwdCacheMu.Lock() 1007 defer p.fwdCacheMu.Unlock() 1008 1009 digest := p.digest(msg) 1010 entry, ok := p.fwdCache[digest] 1011 if ok { 1012 if entry.expiresAt.After(time.Now()) { 1013 log.Trace("unexpired cache", "digest", fmt.Sprintf("%x", digest)) 1014 metrics.GetOrRegisterCounter("pss.checkfwdcache.unexpired", nil).Inc(1) 1015 return true 1016 } 1017 metrics.GetOrRegisterCounter("pss.checkfwdcache.expired", nil).Inc(1) 1018 } 1019 return false 1020 } 1021 1022 // Digest of message 1023 func (p *Pss) digest(msg *PssMsg) pssDigest { 1024 return p.digestBytes(msg.serialize()) 1025 } 1026 1027 func (p *Pss) digestBytes(msg []byte) pssDigest { 1028 hasher := p.hashPool.Get().(hash.Hash) 1029 defer p.hashPool.Put(hasher) 1030 hasher.Reset() 1031 hasher.Write(msg) 1032 digest := pssDigest{} 1033 key := hasher.Sum(nil) 1034 copy(digest[:], key[:digestLength]) 1035 return digest 1036 }