github.com/ylsgit/go-ethereum@v1.6.5/whisper/whisperv5/whisper.go (about) 1 // Copyright 2016 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 whisperv5 18 19 import ( 20 "bytes" 21 "crypto/ecdsa" 22 crand "crypto/rand" 23 "crypto/sha256" 24 "fmt" 25 "runtime" 26 "sync" 27 "time" 28 29 "github.com/ethereum/go-ethereum/common" 30 "github.com/ethereum/go-ethereum/crypto" 31 "github.com/ethereum/go-ethereum/log" 32 "github.com/ethereum/go-ethereum/p2p" 33 "github.com/ethereum/go-ethereum/rpc" 34 "github.com/syndtr/goleveldb/leveldb/errors" 35 "golang.org/x/crypto/pbkdf2" 36 set "gopkg.in/fatih/set.v0" 37 ) 38 39 type Statistics struct { 40 messagesCleared int 41 memoryCleared int 42 memoryUsed int 43 cycles int 44 totalMessagesCleared int 45 } 46 47 // Whisper represents a dark communication interface through the Ethereum 48 // network, using its very own P2P communication layer. 49 type Whisper struct { 50 protocol p2p.Protocol // Protocol description and parameters 51 filters *Filters // Message filters installed with Subscribe function 52 53 privateKeys map[string]*ecdsa.PrivateKey // Private key storage 54 symKeys map[string][]byte // Symmetric key storage 55 keyMu sync.RWMutex // Mutex associated with key storages 56 57 envelopes map[common.Hash]*Envelope // Pool of envelopes currently tracked by this node 58 expirations map[uint32]*set.SetNonTS // Message expiration pool 59 poolMu sync.RWMutex // Mutex to sync the message and expiration pools 60 61 peers map[*Peer]struct{} // Set of currently active peers 62 peerMu sync.RWMutex // Mutex to sync the active peer set 63 64 messageQueue chan *Envelope // Message queue for normal whisper messages 65 p2pMsgQueue chan *Envelope // Message queue for peer-to-peer messages (not to be forwarded any further) 66 quit chan struct{} // Channel used for graceful exit 67 68 minPoW float64 // Minimal PoW required by the whisper node 69 maxMsgLength int // Maximal message length allowed by the whisper node 70 overflow bool // Indicator of message queue overflow 71 72 stats Statistics // Statistics of whisper node 73 74 mailServer MailServer // MailServer interface 75 } 76 77 // New creates a Whisper client ready to communicate through the Ethereum P2P network. 78 func New() *Whisper { 79 whisper := &Whisper{ 80 privateKeys: make(map[string]*ecdsa.PrivateKey), 81 symKeys: make(map[string][]byte), 82 envelopes: make(map[common.Hash]*Envelope), 83 expirations: make(map[uint32]*set.SetNonTS), 84 peers: make(map[*Peer]struct{}), 85 messageQueue: make(chan *Envelope, messageQueueLimit), 86 p2pMsgQueue: make(chan *Envelope, messageQueueLimit), 87 quit: make(chan struct{}), 88 minPoW: DefaultMinimumPoW, 89 maxMsgLength: DefaultMaxMessageLength, 90 } 91 whisper.filters = NewFilters(whisper) 92 93 // p2p whisper sub protocol handler 94 whisper.protocol = p2p.Protocol{ 95 Name: ProtocolName, 96 Version: uint(ProtocolVersion), 97 Length: NumberOfMessageCodes, 98 Run: whisper.HandlePeer, 99 } 100 101 return whisper 102 } 103 104 // APIs returns the RPC descriptors the Whisper implementation offers 105 func (w *Whisper) APIs() []rpc.API { 106 return []rpc.API{ 107 { 108 Namespace: ProtocolName, 109 Version: ProtocolVersionStr, 110 Service: NewPublicWhisperAPI(w), 111 Public: true, 112 }, 113 } 114 } 115 116 // RegisterServer registers MailServer interface. 117 // MailServer will process all the incoming messages with p2pRequestCode. 118 func (w *Whisper) RegisterServer(server MailServer) { 119 w.mailServer = server 120 } 121 122 // Protocols returns the whisper sub-protocols ran by this particular client. 123 func (w *Whisper) Protocols() []p2p.Protocol { 124 return []p2p.Protocol{w.protocol} 125 } 126 127 // Version returns the whisper sub-protocols version number. 128 func (w *Whisper) Version() uint { 129 return w.protocol.Version 130 } 131 132 // SetMaxMessageLength sets the maximal message length allowed by this node 133 func (w *Whisper) SetMaxMessageLength(val int) error { 134 if val <= 0 { 135 return fmt.Errorf("invalid message length: %d", val) 136 } 137 w.maxMsgLength = val 138 return nil 139 } 140 141 // SetMinimumPoW sets the minimal PoW required by this node 142 func (w *Whisper) SetMinimumPoW(val float64) error { 143 if val <= 0.0 { 144 return fmt.Errorf("invalid PoW: %f", val) 145 } 146 w.minPoW = val 147 return nil 148 } 149 150 // getPeer retrieves peer by ID 151 func (w *Whisper) getPeer(peerID []byte) (*Peer, error) { 152 w.peerMu.Lock() 153 defer w.peerMu.Unlock() 154 for p := range w.peers { 155 id := p.peer.ID() 156 if bytes.Equal(peerID, id[:]) { 157 return p, nil 158 } 159 } 160 return nil, fmt.Errorf("Could not find peer with ID: %x", peerID) 161 } 162 163 // AllowP2PMessagesFromPeer marks specific peer trusted, 164 // which will allow it to send historic (expired) messages. 165 func (w *Whisper) AllowP2PMessagesFromPeer(peerID []byte) error { 166 p, err := w.getPeer(peerID) 167 if err != nil { 168 return err 169 } 170 p.trusted = true 171 return nil 172 } 173 174 // RequestHistoricMessages sends a message with p2pRequestCode to a specific peer, 175 // which is known to implement MailServer interface, and is supposed to process this 176 // request and respond with a number of peer-to-peer messages (possibly expired), 177 // which are not supposed to be forwarded any further. 178 // The whisper protocol is agnostic of the format and contents of envelope. 179 func (w *Whisper) RequestHistoricMessages(peerID []byte, envelope *Envelope) error { 180 p, err := w.getPeer(peerID) 181 if err != nil { 182 return err 183 } 184 p.trusted = true 185 return p2p.Send(p.ws, p2pRequestCode, envelope) 186 } 187 188 // SendP2PMessage sends a peer-to-peer message to a specific peer. 189 func (w *Whisper) SendP2PMessage(peerID []byte, envelope *Envelope) error { 190 p, err := w.getPeer(peerID) 191 if err != nil { 192 return err 193 } 194 return w.SendP2PDirect(p, envelope) 195 } 196 197 // SendP2PDirect sends a peer-to-peer message to a specific peer. 198 func (w *Whisper) SendP2PDirect(peer *Peer, envelope *Envelope) error { 199 return p2p.Send(peer.ws, p2pCode, envelope) 200 } 201 202 // NewKeyPair generates a new cryptographic identity for the client, and injects 203 // it into the known identities for message decryption. Returns ID of the new key pair. 204 func (w *Whisper) NewKeyPair() (string, error) { 205 key, err := crypto.GenerateKey() 206 if err != nil || !validatePrivateKey(key) { 207 key, err = crypto.GenerateKey() // retry once 208 } 209 if err != nil { 210 return "", err 211 } 212 if !validatePrivateKey(key) { 213 return "", fmt.Errorf("failed to generate valid key") 214 } 215 216 id, err := GenerateRandomID() 217 if err != nil { 218 return "", fmt.Errorf("failed to generate ID: %s", err) 219 } 220 221 w.keyMu.Lock() 222 defer w.keyMu.Unlock() 223 224 if w.privateKeys[id] != nil { 225 return "", fmt.Errorf("failed to generate unique ID") 226 } 227 w.privateKeys[id] = key 228 return id, nil 229 } 230 231 // DeleteKeyPair deletes the specified key if it exists. 232 func (w *Whisper) DeleteKeyPair(key string) bool { 233 w.keyMu.Lock() 234 defer w.keyMu.Unlock() 235 236 if w.privateKeys[key] != nil { 237 delete(w.privateKeys, key) 238 return true 239 } 240 return false 241 } 242 243 // HasKeyPair checks if the the whisper node is configured with the private key 244 // of the specified public pair. 245 func (w *Whisper) HasKeyPair(id string) bool { 246 w.keyMu.RLock() 247 defer w.keyMu.RUnlock() 248 return w.privateKeys[id] != nil 249 } 250 251 // GetPrivateKey retrieves the private key of the specified identity. 252 func (w *Whisper) GetPrivateKey(id string) (*ecdsa.PrivateKey, error) { 253 w.keyMu.RLock() 254 defer w.keyMu.RUnlock() 255 key := w.privateKeys[id] 256 if key == nil { 257 return nil, fmt.Errorf("invalid id") 258 } 259 return key, nil 260 } 261 262 // GenerateSymKey generates a random symmetric key and stores it under id, 263 // which is then returned. Will be used in the future for session key exchange. 264 func (w *Whisper) GenerateSymKey() (string, error) { 265 key := make([]byte, aesKeyLength) 266 _, err := crand.Read(key) 267 if err != nil { 268 return "", err 269 } else if !validateSymmetricKey(key) { 270 return "", fmt.Errorf("error in GenerateSymKey: crypto/rand failed to generate random data") 271 } 272 273 id, err := GenerateRandomID() 274 if err != nil { 275 return "", fmt.Errorf("failed to generate ID: %s", err) 276 } 277 278 w.keyMu.Lock() 279 defer w.keyMu.Unlock() 280 281 if w.symKeys[id] != nil { 282 return "", fmt.Errorf("failed to generate unique ID") 283 } 284 w.symKeys[id] = key 285 return id, nil 286 } 287 288 // AddSymKeyDirect stores the key, and returns its id. 289 func (w *Whisper) AddSymKeyDirect(key []byte) (string, error) { 290 if len(key) != aesKeyLength { 291 return "", fmt.Errorf("wrong key size: %d", len(key)) 292 } 293 294 id, err := GenerateRandomID() 295 if err != nil { 296 return "", fmt.Errorf("failed to generate ID: %s", err) 297 } 298 299 w.keyMu.Lock() 300 defer w.keyMu.Unlock() 301 302 if w.symKeys[id] != nil { 303 return "", fmt.Errorf("failed to generate unique ID") 304 } 305 w.symKeys[id] = key 306 return id, nil 307 } 308 309 // AddSymKeyFromPassword generates the key from password, stores it, and returns its id. 310 func (w *Whisper) AddSymKeyFromPassword(password string) (string, error) { 311 id, err := GenerateRandomID() 312 if err != nil { 313 return "", fmt.Errorf("failed to generate ID: %s", err) 314 } 315 if w.HasSymKey(id) { 316 return "", fmt.Errorf("failed to generate unique ID") 317 } 318 319 derived, err := deriveKeyMaterial([]byte(password), EnvelopeVersion) 320 if err != nil { 321 return "", err 322 } 323 324 w.keyMu.Lock() 325 defer w.keyMu.Unlock() 326 327 // double check is necessary, because deriveKeyMaterial() is very slow 328 if w.symKeys[id] != nil { 329 return "", fmt.Errorf("critical error: failed to generate unique ID") 330 } 331 w.symKeys[id] = derived 332 return id, nil 333 } 334 335 // HasSymKey returns true if there is a key associated with the given id. 336 // Otherwise returns false. 337 func (w *Whisper) HasSymKey(id string) bool { 338 w.keyMu.RLock() 339 defer w.keyMu.RUnlock() 340 return w.symKeys[id] != nil 341 } 342 343 // DeleteSymKey deletes the key associated with the name string if it exists. 344 func (w *Whisper) DeleteSymKey(id string) bool { 345 w.keyMu.Lock() 346 defer w.keyMu.Unlock() 347 if w.symKeys[id] != nil { 348 delete(w.symKeys, id) 349 return true 350 } 351 return false 352 } 353 354 // GetSymKey returns the symmetric key associated with the given id. 355 func (w *Whisper) GetSymKey(id string) ([]byte, error) { 356 w.keyMu.RLock() 357 defer w.keyMu.RUnlock() 358 if w.symKeys[id] != nil { 359 return w.symKeys[id], nil 360 } 361 return nil, fmt.Errorf("non-existent key ID") 362 } 363 364 // Subscribe installs a new message handler used for filtering, decrypting 365 // and subsequent storing of incoming messages. 366 func (w *Whisper) Subscribe(f *Filter) (string, error) { 367 return w.filters.Install(f) 368 } 369 370 // GetFilter returns the filter by id. 371 func (w *Whisper) GetFilter(id string) *Filter { 372 return w.filters.Get(id) 373 } 374 375 // Unsubscribe removes an installed message handler. 376 func (w *Whisper) Unsubscribe(id string) error { 377 ok := w.filters.Uninstall(id) 378 if !ok { 379 return fmt.Errorf("Unsubscribe: Invalid ID") 380 } 381 return nil 382 } 383 384 // Send injects a message into the whisper send queue, to be distributed in the 385 // network in the coming cycles. 386 func (w *Whisper) Send(envelope *Envelope) error { 387 ok, err := w.add(envelope) 388 if err != nil { 389 return err 390 } 391 if !ok { 392 return fmt.Errorf("failed to add envelope") 393 } 394 return err 395 } 396 397 // Start implements node.Service, starting the background data propagation thread 398 // of the Whisper protocol. 399 func (w *Whisper) Start(*p2p.Server) error { 400 log.Info("started whisper v." + ProtocolVersionStr) 401 go w.update() 402 403 numCPU := runtime.NumCPU() 404 for i := 0; i < numCPU; i++ { 405 go w.processQueue() 406 } 407 408 return nil 409 } 410 411 // Stop implements node.Service, stopping the background data propagation thread 412 // of the Whisper protocol. 413 func (w *Whisper) Stop() error { 414 close(w.quit) 415 log.Info("whisper stopped") 416 return nil 417 } 418 419 // HandlePeer is called by the underlying P2P layer when the whisper sub-protocol 420 // connection is negotiated. 421 func (wh *Whisper) HandlePeer(peer *p2p.Peer, rw p2p.MsgReadWriter) error { 422 // Create the new peer and start tracking it 423 whisperPeer := newPeer(wh, peer, rw) 424 425 wh.peerMu.Lock() 426 wh.peers[whisperPeer] = struct{}{} 427 wh.peerMu.Unlock() 428 429 defer func() { 430 wh.peerMu.Lock() 431 delete(wh.peers, whisperPeer) 432 wh.peerMu.Unlock() 433 }() 434 435 // Run the peer handshake and state updates 436 if err := whisperPeer.handshake(); err != nil { 437 return err 438 } 439 whisperPeer.start() 440 defer whisperPeer.stop() 441 442 return wh.runMessageLoop(whisperPeer, rw) 443 } 444 445 // runMessageLoop reads and processes inbound messages directly to merge into client-global state. 446 func (wh *Whisper) runMessageLoop(p *Peer, rw p2p.MsgReadWriter) error { 447 for { 448 // fetch the next packet 449 packet, err := rw.ReadMsg() 450 if err != nil { 451 log.Warn("message loop", "peer", p.peer.ID(), "err", err) 452 return err 453 } 454 if packet.Size > uint32(wh.maxMsgLength) { 455 log.Warn("oversized message received", "peer", p.peer.ID()) 456 return errors.New("oversized message received") 457 } 458 459 switch packet.Code { 460 case statusCode: 461 // this should not happen, but no need to panic; just ignore this message. 462 log.Warn("unxepected status message received", "peer", p.peer.ID()) 463 case messagesCode: 464 // decode the contained envelopes 465 var envelope Envelope 466 if err := packet.Decode(&envelope); err != nil { 467 log.Warn("failed to decode envelope, peer will be disconnected", "peer", p.peer.ID(), "err", err) 468 return errors.New("invalid envelope") 469 } 470 cached, err := wh.add(&envelope) 471 if err != nil { 472 log.Warn("bad envelope received, peer will be disconnected", "peer", p.peer.ID(), "err", err) 473 return errors.New("invalid envelope") 474 } 475 if cached { 476 p.mark(&envelope) 477 } 478 case p2pCode: 479 // peer-to-peer message, sent directly to peer bypassing PoW checks, etc. 480 // this message is not supposed to be forwarded to other peers, and 481 // therefore might not satisfy the PoW, expiry and other requirements. 482 // these messages are only accepted from the trusted peer. 483 if p.trusted { 484 var envelope Envelope 485 if err := packet.Decode(&envelope); err != nil { 486 log.Warn("failed to decode direct message, peer will be disconnected", "peer", p.peer.ID(), "err", err) 487 return errors.New("invalid direct message") 488 } 489 wh.postEvent(&envelope, true) 490 } 491 case p2pRequestCode: 492 // Must be processed if mail server is implemented. Otherwise ignore. 493 if wh.mailServer != nil { 494 var request Envelope 495 if err := packet.Decode(&request); err != nil { 496 log.Warn("failed to decode p2p request message, peer will be disconnected", "peer", p.peer.ID(), "err", err) 497 return errors.New("invalid p2p request") 498 } 499 wh.mailServer.DeliverMail(p, &request) 500 } 501 default: 502 // New message types might be implemented in the future versions of Whisper. 503 // For forward compatibility, just ignore. 504 } 505 506 packet.Discard() 507 } 508 } 509 510 // add inserts a new envelope into the message pool to be distributed within the 511 // whisper network. It also inserts the envelope into the expiration pool at the 512 // appropriate time-stamp. In case of error, connection should be dropped. 513 func (wh *Whisper) add(envelope *Envelope) (bool, error) { 514 now := uint32(time.Now().Unix()) 515 sent := envelope.Expiry - envelope.TTL 516 517 if sent > now { 518 if sent-SynchAllowance > now { 519 return false, fmt.Errorf("envelope created in the future [%x]", envelope.Hash()) 520 } else { 521 // recalculate PoW, adjusted for the time difference, plus one second for latency 522 envelope.calculatePoW(sent - now + 1) 523 } 524 } 525 526 if envelope.Expiry < now { 527 if envelope.Expiry+SynchAllowance*2 < now { 528 return false, fmt.Errorf("very old message") 529 } else { 530 log.Debug("expired envelope dropped", "hash", envelope.Hash().Hex()) 531 return false, nil // drop envelope without error 532 } 533 } 534 535 if envelope.size() > wh.maxMsgLength { 536 return false, fmt.Errorf("huge messages are not allowed [%x]", envelope.Hash()) 537 } 538 539 if len(envelope.Version) > 4 { 540 return false, fmt.Errorf("oversized version [%x]", envelope.Hash()) 541 } 542 543 aesNonceSize := len(envelope.AESNonce) 544 if aesNonceSize != 0 && aesNonceSize != AESNonceLength { 545 // the standard AES GCM nonce size is 12 bytes, 546 // but constant gcmStandardNonceSize cannot be accessed (not exported) 547 return false, fmt.Errorf("wrong size of AESNonce: %d bytes [env: %x]", aesNonceSize, envelope.Hash()) 548 } 549 550 if envelope.PoW() < wh.minPoW { 551 log.Debug("envelope with low PoW dropped", "PoW", envelope.PoW(), "hash", envelope.Hash().Hex()) 552 return false, nil // drop envelope without error 553 } 554 555 hash := envelope.Hash() 556 557 wh.poolMu.Lock() 558 _, alreadyCached := wh.envelopes[hash] 559 if !alreadyCached { 560 wh.envelopes[hash] = envelope 561 if wh.expirations[envelope.Expiry] == nil { 562 wh.expirations[envelope.Expiry] = set.NewNonTS() 563 } 564 if !wh.expirations[envelope.Expiry].Has(hash) { 565 wh.expirations[envelope.Expiry].Add(hash) 566 } 567 } 568 wh.poolMu.Unlock() 569 570 if alreadyCached { 571 log.Trace("whisper envelope already cached", "hash", envelope.Hash().Hex()) 572 } else { 573 log.Trace("cached whisper envelope", "hash", envelope.Hash().Hex()) 574 wh.stats.memoryUsed += envelope.size() 575 wh.postEvent(envelope, false) // notify the local node about the new message 576 if wh.mailServer != nil { 577 wh.mailServer.Archive(envelope) 578 } 579 } 580 return true, nil 581 } 582 583 // postEvent queues the message for further processing. 584 func (w *Whisper) postEvent(envelope *Envelope, isP2P bool) { 585 // if the version of incoming message is higher than 586 // currently supported version, we can not decrypt it, 587 // and therefore just ignore this message 588 if envelope.Ver() <= EnvelopeVersion { 589 if isP2P { 590 w.p2pMsgQueue <- envelope 591 } else { 592 w.checkOverflow() 593 w.messageQueue <- envelope 594 } 595 } 596 } 597 598 // checkOverflow checks if message queue overflow occurs and reports it if necessary. 599 func (w *Whisper) checkOverflow() { 600 queueSize := len(w.messageQueue) 601 602 if queueSize == messageQueueLimit { 603 if !w.overflow { 604 w.overflow = true 605 log.Warn("message queue overflow") 606 } 607 } else if queueSize <= messageQueueLimit/2 { 608 if w.overflow { 609 w.overflow = false 610 log.Warn("message queue overflow fixed (back to normal)") 611 } 612 } 613 } 614 615 // processQueue delivers the messages to the watchers during the lifetime of the whisper node. 616 func (w *Whisper) processQueue() { 617 var e *Envelope 618 for { 619 select { 620 case <-w.quit: 621 return 622 623 case e = <-w.messageQueue: 624 w.filters.NotifyWatchers(e, false) 625 626 case e = <-w.p2pMsgQueue: 627 w.filters.NotifyWatchers(e, true) 628 } 629 } 630 } 631 632 // update loops until the lifetime of the whisper node, updating its internal 633 // state by expiring stale messages from the pool. 634 func (w *Whisper) update() { 635 // Start a ticker to check for expirations 636 expire := time.NewTicker(expirationCycle) 637 638 // Repeat updates until termination is requested 639 for { 640 select { 641 case <-expire.C: 642 w.expire() 643 644 case <-w.quit: 645 return 646 } 647 } 648 } 649 650 // expire iterates over all the expiration timestamps, removing all stale 651 // messages from the pools. 652 func (w *Whisper) expire() { 653 w.poolMu.Lock() 654 defer w.poolMu.Unlock() 655 656 w.stats.reset() 657 now := uint32(time.Now().Unix()) 658 for expiry, hashSet := range w.expirations { 659 if expiry < now { 660 // Dump all expired messages and remove timestamp 661 hashSet.Each(func(v interface{}) bool { 662 sz := w.envelopes[v.(common.Hash)].size() 663 delete(w.envelopes, v.(common.Hash)) 664 w.stats.messagesCleared++ 665 w.stats.memoryCleared += sz 666 w.stats.memoryUsed -= sz 667 return true 668 }) 669 w.expirations[expiry].Clear() 670 delete(w.expirations, expiry) 671 } 672 } 673 } 674 675 // Stats returns the whisper node statistics. 676 func (w *Whisper) Stats() string { 677 result := fmt.Sprintf("Memory usage: %d bytes. Average messages cleared per expiry cycle: %d. Total messages cleared: %d.", 678 w.stats.memoryUsed, w.stats.totalMessagesCleared/w.stats.cycles, w.stats.totalMessagesCleared) 679 if w.stats.messagesCleared > 0 { 680 result += fmt.Sprintf(" Latest expiry cycle cleared %d messages (%d bytes).", 681 w.stats.messagesCleared, w.stats.memoryCleared) 682 } 683 if w.overflow { 684 result += " Message queue state: overflow." 685 } 686 return result 687 } 688 689 // Envelopes retrieves all the messages currently pooled by the node. 690 func (w *Whisper) Envelopes() []*Envelope { 691 w.poolMu.RLock() 692 defer w.poolMu.RUnlock() 693 694 all := make([]*Envelope, 0, len(w.envelopes)) 695 for _, envelope := range w.envelopes { 696 all = append(all, envelope) 697 } 698 return all 699 } 700 701 // Messages iterates through all currently floating envelopes 702 // and retrieves all the messages, that this filter could decrypt. 703 func (w *Whisper) Messages(id string) []*ReceivedMessage { 704 result := make([]*ReceivedMessage, 0) 705 w.poolMu.RLock() 706 defer w.poolMu.RUnlock() 707 708 if filter := w.filters.Get(id); filter != nil { 709 for _, env := range w.envelopes { 710 msg := filter.processEnvelope(env) 711 if msg != nil { 712 result = append(result, msg) 713 } 714 } 715 } 716 return result 717 } 718 719 // isEnvelopeCached checks if envelope with specific hash has already been received and cached. 720 func (w *Whisper) isEnvelopeCached(hash common.Hash) bool { 721 w.poolMu.Lock() 722 defer w.poolMu.Unlock() 723 724 _, exist := w.envelopes[hash] 725 return exist 726 } 727 728 // reset resets the node's statistics after each expiry cycle. 729 func (s *Statistics) reset() { 730 s.cycles++ 731 s.totalMessagesCleared += s.messagesCleared 732 733 s.memoryCleared = 0 734 s.messagesCleared = 0 735 } 736 737 // ValidateKeyID checks the format of key id. 738 func ValidateKeyID(id string) error { 739 const target = keyIdSize * 2 740 if len(id) != target { 741 return fmt.Errorf("wrong size of key ID (expected %d bytes, got %d)", target, len(id)) 742 } 743 return nil 744 } 745 746 // ValidatePublicKey checks the format of the given public key. 747 func ValidatePublicKey(k *ecdsa.PublicKey) bool { 748 return k != nil && k.X != nil && k.Y != nil && k.X.Sign() != 0 && k.Y.Sign() != 0 749 } 750 751 // validatePrivateKey checks the format of the given private key. 752 func validatePrivateKey(k *ecdsa.PrivateKey) bool { 753 if k == nil || k.D == nil || k.D.Sign() == 0 { 754 return false 755 } 756 return ValidatePublicKey(&k.PublicKey) 757 } 758 759 // validateSymmetricKey returns false if the key contains all zeros 760 func validateSymmetricKey(k []byte) bool { 761 return len(k) > 0 && !containsOnlyZeros(k) 762 } 763 764 // containsOnlyZeros checks if the data contain only zeros. 765 func containsOnlyZeros(data []byte) bool { 766 for _, b := range data { 767 if b != 0 { 768 return false 769 } 770 } 771 return true 772 } 773 774 // bytesToUintLittleEndian converts the slice to 64-bit unsigned integer. 775 func bytesToUintLittleEndian(b []byte) (res uint64) { 776 mul := uint64(1) 777 for i := 0; i < len(b); i++ { 778 res += uint64(b[i]) * mul 779 mul *= 256 780 } 781 return res 782 } 783 784 // BytesToUintBigEndian converts the slice to 64-bit unsigned integer. 785 func BytesToUintBigEndian(b []byte) (res uint64) { 786 for i := 0; i < len(b); i++ { 787 res *= 256 788 res += uint64(b[i]) 789 } 790 return res 791 } 792 793 // deriveKeyMaterial derives symmetric key material from the key or password. 794 // pbkdf2 is used for security, in case people use password instead of randomly generated keys. 795 func deriveKeyMaterial(key []byte, version uint64) (derivedKey []byte, err error) { 796 if version == 0 { 797 // kdf should run no less than 0.1 seconds on average compute, 798 // because it's a once in a session experience 799 derivedKey := pbkdf2.Key(key, nil, 65356, aesKeyLength, sha256.New) 800 return derivedKey, nil 801 } else { 802 return nil, unknownVersionError(version) 803 } 804 } 805 806 // GenerateRandomID generates a random string, which is then returned to be used as a key id 807 func GenerateRandomID() (id string, err error) { 808 buf := make([]byte, keyIdSize) 809 _, err = crand.Read(buf) 810 if err != nil { 811 return "", err 812 } 813 if !validateSymmetricKey(buf) { 814 return "", fmt.Errorf("error in generateRandomID: crypto/rand failed to generate random data") 815 } 816 id = common.Bytes2Hex(buf) 817 return id, err 818 }