github.com/avence12/go-ethereum@v1.5.10-0.20170320123548-1dfd65f6d047/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 "golang.org/x/crypto/pbkdf2" 35 set "gopkg.in/fatih/set.v0" 36 ) 37 38 type Statistics struct { 39 messagesCleared int 40 memoryCleared int 41 totalMemoryUsed int 42 } 43 44 // Whisper represents a dark communication interface through the Ethereum 45 // network, using its very own P2P communication layer. 46 type Whisper struct { 47 protocol p2p.Protocol 48 filters *Filters 49 50 privateKeys map[string]*ecdsa.PrivateKey 51 symKeys map[string][]byte 52 keyMu sync.RWMutex 53 54 envelopes map[common.Hash]*Envelope // Pool of envelopes currently tracked by this node 55 messages map[common.Hash]*ReceivedMessage // Pool of successfully decrypted messages, which are not expired yet 56 expirations map[uint32]*set.SetNonTS // Message expiration pool 57 poolMu sync.RWMutex // Mutex to sync the message and expiration pools 58 59 peers map[*Peer]struct{} // Set of currently active peers 60 peerMu sync.RWMutex // Mutex to sync the active peer set 61 62 mailServer MailServer 63 64 messageQueue chan *Envelope 65 p2pMsgQueue chan *Envelope 66 quit chan struct{} 67 68 stats Statistics 69 70 overflow bool 71 test bool 72 } 73 74 // New creates a Whisper client ready to communicate through the Ethereum P2P network. 75 // Param s should be passed if you want to implement mail server, otherwise nil. 76 func New() *Whisper { 77 whisper := &Whisper{ 78 privateKeys: make(map[string]*ecdsa.PrivateKey), 79 symKeys: make(map[string][]byte), 80 envelopes: make(map[common.Hash]*Envelope), 81 messages: make(map[common.Hash]*ReceivedMessage), 82 expirations: make(map[uint32]*set.SetNonTS), 83 peers: make(map[*Peer]struct{}), 84 messageQueue: make(chan *Envelope, messageQueueLimit), 85 p2pMsgQueue: make(chan *Envelope, messageQueueLimit), 86 quit: make(chan struct{}), 87 } 88 whisper.filters = NewFilters(whisper) 89 90 // p2p whisper sub protocol handler 91 whisper.protocol = p2p.Protocol{ 92 Name: ProtocolName, 93 Version: uint(ProtocolVersion), 94 Length: NumberOfMessageCodes, 95 Run: whisper.HandlePeer, 96 } 97 98 return whisper 99 } 100 101 // APIs returns the RPC descriptors the Whisper implementation offers 102 func (w *Whisper) APIs() []rpc.API { 103 return []rpc.API{ 104 { 105 Namespace: ProtocolName, 106 Version: ProtocolVersionStr, 107 Service: NewPublicWhisperAPI(w), 108 Public: true, 109 }, 110 } 111 } 112 113 func (w *Whisper) RegisterServer(server MailServer) { 114 w.mailServer = server 115 } 116 117 // Protocols returns the whisper sub-protocols ran by this particular client. 118 func (w *Whisper) Protocols() []p2p.Protocol { 119 return []p2p.Protocol{w.protocol} 120 } 121 122 // Version returns the whisper sub-protocols version number. 123 func (w *Whisper) Version() uint { 124 return w.protocol.Version 125 } 126 127 func (w *Whisper) getPeer(peerID []byte) (*Peer, error) { 128 w.peerMu.Lock() 129 defer w.peerMu.Unlock() 130 for p := range w.peers { 131 id := p.peer.ID() 132 if bytes.Equal(peerID, id[:]) { 133 return p, nil 134 } 135 } 136 return nil, fmt.Errorf("Could not find peer with ID: %x", peerID) 137 } 138 139 // MarkPeerTrusted marks specific peer trusted, which will allow it 140 // to send historic (expired) messages. 141 func (w *Whisper) MarkPeerTrusted(peerID []byte) error { 142 p, err := w.getPeer(peerID) 143 if err != nil { 144 return err 145 } 146 p.trusted = true 147 return nil 148 } 149 150 func (w *Whisper) RequestHistoricMessages(peerID []byte, envelope *Envelope) error { 151 p, err := w.getPeer(peerID) 152 if err != nil { 153 return err 154 } 155 p.trusted = true 156 return p2p.Send(p.ws, p2pRequestCode, envelope) 157 } 158 159 func (w *Whisper) SendP2PMessage(peerID []byte, envelope *Envelope) error { 160 p, err := w.getPeer(peerID) 161 if err != nil { 162 return err 163 } 164 return p2p.Send(p.ws, p2pCode, envelope) 165 } 166 167 func (w *Whisper) SendP2PDirect(peer *Peer, envelope *Envelope) error { 168 return p2p.Send(peer.ws, p2pCode, envelope) 169 } 170 171 // NewIdentity generates a new cryptographic identity for the client, and injects 172 // it into the known identities for message decryption. 173 func (w *Whisper) NewIdentity() *ecdsa.PrivateKey { 174 key, err := crypto.GenerateKey() 175 if err != nil || !validatePrivateKey(key) { 176 key, err = crypto.GenerateKey() // retry once 177 } 178 if err != nil { 179 panic(err) 180 } 181 if !validatePrivateKey(key) { 182 panic("Failed to generate valid key") 183 } 184 w.keyMu.Lock() 185 defer w.keyMu.Unlock() 186 w.privateKeys[common.ToHex(crypto.FromECDSAPub(&key.PublicKey))] = key 187 return key 188 } 189 190 // DeleteIdentity deletes the specified key if it exists. 191 func (w *Whisper) DeleteIdentity(key string) { 192 w.keyMu.Lock() 193 defer w.keyMu.Unlock() 194 delete(w.privateKeys, key) 195 } 196 197 // HasIdentity checks if the the whisper node is configured with the private key 198 // of the specified public pair. 199 func (w *Whisper) HasIdentity(pubKey string) bool { 200 w.keyMu.RLock() 201 defer w.keyMu.RUnlock() 202 return w.privateKeys[pubKey] != nil 203 } 204 205 // GetIdentity retrieves the private key of the specified public identity. 206 func (w *Whisper) GetIdentity(pubKey string) *ecdsa.PrivateKey { 207 w.keyMu.RLock() 208 defer w.keyMu.RUnlock() 209 return w.privateKeys[pubKey] 210 } 211 212 func (w *Whisper) GenerateSymKey(name string) error { 213 const size = aesKeyLength * 2 214 buf := make([]byte, size) 215 _, err := crand.Read(buf) 216 if err != nil { 217 return err 218 } else if !validateSymmetricKey(buf) { 219 return fmt.Errorf("error in GenerateSymKey: crypto/rand failed to generate random data") 220 } 221 222 key := buf[:aesKeyLength] 223 salt := buf[aesKeyLength:] 224 derived, err := DeriveOneTimeKey(key, salt, EnvelopeVersion) 225 if err != nil { 226 return err 227 } else if !validateSymmetricKey(derived) { 228 return fmt.Errorf("failed to derive valid key") 229 } 230 231 w.keyMu.Lock() 232 defer w.keyMu.Unlock() 233 234 if w.symKeys[name] != nil { 235 return fmt.Errorf("Key with name [%s] already exists", name) 236 } 237 w.symKeys[name] = derived 238 return nil 239 } 240 241 func (w *Whisper) AddSymKey(name string, key []byte) error { 242 if w.HasSymKey(name) { 243 return fmt.Errorf("Key with name [%s] already exists", name) 244 } 245 246 derived, err := deriveKeyMaterial(key, EnvelopeVersion) 247 if err != nil { 248 return err 249 } 250 251 w.keyMu.Lock() 252 defer w.keyMu.Unlock() 253 254 // double check is necessary, because deriveKeyMaterial() is slow 255 if w.symKeys[name] != nil { 256 return fmt.Errorf("Key with name [%s] already exists", name) 257 } 258 w.symKeys[name] = derived 259 return nil 260 } 261 262 func (w *Whisper) HasSymKey(name string) bool { 263 w.keyMu.RLock() 264 defer w.keyMu.RUnlock() 265 return w.symKeys[name] != nil 266 } 267 268 func (w *Whisper) DeleteSymKey(name string) { 269 w.keyMu.Lock() 270 defer w.keyMu.Unlock() 271 delete(w.symKeys, name) 272 } 273 274 func (w *Whisper) GetSymKey(name string) []byte { 275 w.keyMu.RLock() 276 defer w.keyMu.RUnlock() 277 return w.symKeys[name] 278 } 279 280 // Watch installs a new message handler to run in case a matching packet arrives 281 // from the whisper network. 282 func (w *Whisper) Watch(f *Filter) (string, error) { 283 return w.filters.Install(f) 284 } 285 286 func (w *Whisper) GetFilter(id string) *Filter { 287 return w.filters.Get(id) 288 } 289 290 // Unwatch removes an installed message handler. 291 func (w *Whisper) Unwatch(id string) { 292 w.filters.Uninstall(id) 293 } 294 295 // Send injects a message into the whisper send queue, to be distributed in the 296 // network in the coming cycles. 297 func (w *Whisper) Send(envelope *Envelope) error { 298 _, err := w.add(envelope) 299 return err 300 } 301 302 // Start implements node.Service, starting the background data propagation thread 303 // of the Whisper protocol. 304 func (w *Whisper) Start(*p2p.Server) error { 305 log.Info(fmt.Sprint("Whisper started")) 306 go w.update() 307 308 numCPU := runtime.NumCPU() 309 for i := 0; i < numCPU; i++ { 310 go w.processQueue() 311 } 312 313 return nil 314 } 315 316 // Stop implements node.Service, stopping the background data propagation thread 317 // of the Whisper protocol. 318 func (w *Whisper) Stop() error { 319 close(w.quit) 320 log.Info(fmt.Sprint("Whisper stopped")) 321 return nil 322 } 323 324 // handlePeer is called by the underlying P2P layer when the whisper sub-protocol 325 // connection is negotiated. 326 func (wh *Whisper) HandlePeer(peer *p2p.Peer, rw p2p.MsgReadWriter) error { 327 // Create the new peer and start tracking it 328 whisperPeer := newPeer(wh, peer, rw) 329 330 wh.peerMu.Lock() 331 wh.peers[whisperPeer] = struct{}{} 332 wh.peerMu.Unlock() 333 334 defer func() { 335 wh.peerMu.Lock() 336 delete(wh.peers, whisperPeer) 337 wh.peerMu.Unlock() 338 }() 339 340 // Run the peer handshake and state updates 341 if err := whisperPeer.handshake(); err != nil { 342 return err 343 } 344 whisperPeer.start() 345 defer whisperPeer.stop() 346 347 return wh.runMessageLoop(whisperPeer, rw) 348 } 349 350 // runMessageLoop reads and processes inbound messages directly to merge into client-global state. 351 func (wh *Whisper) runMessageLoop(p *Peer, rw p2p.MsgReadWriter) error { 352 for { 353 // fetch the next packet 354 packet, err := rw.ReadMsg() 355 if err != nil { 356 return err 357 } 358 359 switch packet.Code { 360 case statusCode: 361 // this should not happen, but no need to panic; just ignore this message. 362 log.Warn(fmt.Sprintf("%v: unxepected status message received", p.peer)) 363 case messagesCode: 364 // decode the contained envelopes 365 var envelopes []*Envelope 366 if err := packet.Decode(&envelopes); err != nil { 367 log.Warn(fmt.Sprintf("%v: failed to decode envelope: [%v], peer will be disconnected", p.peer, err)) 368 return fmt.Errorf("garbage received") 369 } 370 // inject all envelopes into the internal pool 371 for _, envelope := range envelopes { 372 cached, err := wh.add(envelope) 373 if err != nil { 374 log.Warn(fmt.Sprintf("%v: bad envelope received: [%v], peer will be disconnected", p.peer, err)) 375 return fmt.Errorf("invalid envelope") 376 } 377 if cached { 378 p.mark(envelope) 379 } 380 } 381 case p2pCode: 382 // peer-to-peer message, sent directly to peer bypassing PoW checks, etc. 383 // this message is not supposed to be forwarded to other peers, and 384 // therefore might not satisfy the PoW, expiry and other requirements. 385 // these messages are only accepted from the trusted peer. 386 if p.trusted { 387 var envelope Envelope 388 if err := packet.Decode(&envelope); err != nil { 389 log.Warn(fmt.Sprintf("%v: failed to decode direct message: [%v], peer will be disconnected", p.peer, err)) 390 return fmt.Errorf("garbage received (directMessage)") 391 } 392 wh.postEvent(&envelope, true) 393 } 394 case p2pRequestCode: 395 // Must be processed if mail server is implemented. Otherwise ignore. 396 if wh.mailServer != nil { 397 var request Envelope 398 if err := packet.Decode(&request); err != nil { 399 log.Warn(fmt.Sprintf("%v: failed to decode p2p request message: [%v], peer will be disconnected", p.peer, err)) 400 return fmt.Errorf("garbage received (p2p request)") 401 } 402 wh.mailServer.DeliverMail(p, &request) 403 } 404 default: 405 // New message types might be implemented in the future versions of Whisper. 406 // For forward compatibility, just ignore. 407 } 408 409 packet.Discard() 410 } 411 } 412 413 // add inserts a new envelope into the message pool to be distributed within the 414 // whisper network. It also inserts the envelope into the expiration pool at the 415 // appropriate time-stamp. In case of error, connection should be dropped. 416 func (wh *Whisper) add(envelope *Envelope) (bool, error) { 417 now := uint32(time.Now().Unix()) 418 sent := envelope.Expiry - envelope.TTL 419 420 if sent > now { 421 if sent-SynchAllowance > now { 422 return false, fmt.Errorf("envelope created in the future [%x]", envelope.Hash()) 423 } else { 424 // recalculate PoW, adjusted for the time difference, plus one second for latency 425 envelope.calculatePoW(sent - now + 1) 426 } 427 } 428 429 if envelope.Expiry < now { 430 if envelope.Expiry+SynchAllowance*2 < now { 431 return false, fmt.Errorf("very old message") 432 } else { 433 log.Debug(fmt.Sprintf("expired envelope dropped [%x]", envelope.Hash())) 434 return false, nil // drop envelope without error 435 } 436 } 437 438 if len(envelope.Data) > MaxMessageLength { 439 return false, fmt.Errorf("huge messages are not allowed [%x]", envelope.Hash()) 440 } 441 442 if len(envelope.Version) > 4 { 443 return false, fmt.Errorf("oversized version [%x]", envelope.Hash()) 444 } 445 446 if len(envelope.AESNonce) > AESNonceMaxLength { 447 // the standard AES GSM nonce size is 12, 448 // but const gcmStandardNonceSize cannot be accessed directly 449 return false, fmt.Errorf("oversized AESNonce [%x]", envelope.Hash()) 450 } 451 452 if len(envelope.Salt) > saltLength { 453 return false, fmt.Errorf("oversized salt [%x]", envelope.Hash()) 454 } 455 456 if envelope.PoW() < MinimumPoW && !wh.test { 457 log.Debug(fmt.Sprintf("envelope with low PoW dropped: %f [%x]", envelope.PoW(), envelope.Hash())) 458 return false, nil // drop envelope without error 459 } 460 461 hash := envelope.Hash() 462 463 wh.poolMu.Lock() 464 _, alreadyCached := wh.envelopes[hash] 465 if !alreadyCached { 466 wh.envelopes[hash] = envelope 467 if wh.expirations[envelope.Expiry] == nil { 468 wh.expirations[envelope.Expiry] = set.NewNonTS() 469 } 470 if !wh.expirations[envelope.Expiry].Has(hash) { 471 wh.expirations[envelope.Expiry].Add(hash) 472 } 473 } 474 wh.poolMu.Unlock() 475 476 if alreadyCached { 477 log.Trace(fmt.Sprintf("whisper envelope already cached [%x]\n", envelope.Hash())) 478 } else { 479 log.Trace(fmt.Sprintf("cached whisper envelope [%x]: %v\n", envelope.Hash(), envelope)) 480 wh.stats.totalMemoryUsed += envelope.size() 481 wh.postEvent(envelope, false) // notify the local node about the new message 482 if wh.mailServer != nil { 483 wh.mailServer.Archive(envelope) 484 } 485 } 486 return true, nil 487 } 488 489 // postEvent queues the message for further processing. 490 func (w *Whisper) postEvent(envelope *Envelope, isP2P bool) { 491 // if the version of incoming message is higher than 492 // currently supported version, we can not decrypt it, 493 // and therefore just ignore this message 494 if envelope.Ver() <= EnvelopeVersion { 495 if isP2P { 496 w.p2pMsgQueue <- envelope 497 } else { 498 w.checkOverflow() 499 w.messageQueue <- envelope 500 } 501 } 502 } 503 504 // checkOverflow checks if message queue overflow occurs and reports it if necessary. 505 func (w *Whisper) checkOverflow() { 506 queueSize := len(w.messageQueue) 507 508 if queueSize == messageQueueLimit { 509 if !w.overflow { 510 w.overflow = true 511 log.Warn(fmt.Sprint("message queue overflow")) 512 } 513 } else if queueSize <= messageQueueLimit/2 { 514 if w.overflow { 515 w.overflow = false 516 } 517 } 518 } 519 520 // processQueue delivers the messages to the watchers during the lifetime of the whisper node. 521 func (w *Whisper) processQueue() { 522 var e *Envelope 523 for { 524 select { 525 case <-w.quit: 526 return 527 528 case e = <-w.messageQueue: 529 w.filters.NotifyWatchers(e, false) 530 531 case e = <-w.p2pMsgQueue: 532 w.filters.NotifyWatchers(e, true) 533 } 534 } 535 } 536 537 // update loops until the lifetime of the whisper node, updating its internal 538 // state by expiring stale messages from the pool. 539 func (w *Whisper) update() { 540 // Start a ticker to check for expirations 541 expire := time.NewTicker(expirationCycle) 542 543 // Repeat updates until termination is requested 544 for { 545 select { 546 case <-expire.C: 547 w.expire() 548 549 case <-w.quit: 550 return 551 } 552 } 553 } 554 555 // expire iterates over all the expiration timestamps, removing all stale 556 // messages from the pools. 557 func (w *Whisper) expire() { 558 w.poolMu.Lock() 559 defer w.poolMu.Unlock() 560 561 w.stats.clear() 562 now := uint32(time.Now().Unix()) 563 for expiry, hashSet := range w.expirations { 564 if expiry < now { 565 w.stats.messagesCleared++ 566 567 // Dump all expired messages and remove timestamp 568 hashSet.Each(func(v interface{}) bool { 569 sz := w.envelopes[v.(common.Hash)].size() 570 w.stats.memoryCleared += sz 571 w.stats.totalMemoryUsed -= sz 572 delete(w.envelopes, v.(common.Hash)) 573 delete(w.messages, v.(common.Hash)) 574 return true 575 }) 576 w.expirations[expiry].Clear() 577 delete(w.expirations, expiry) 578 } 579 } 580 } 581 582 func (w *Whisper) Stats() string { 583 return fmt.Sprintf("Latest expiry cycle cleared %d messages (%d bytes). Memory usage: %d bytes.", 584 w.stats.messagesCleared, w.stats.memoryCleared, w.stats.totalMemoryUsed) 585 } 586 587 // envelopes retrieves all the messages currently pooled by the node. 588 func (w *Whisper) Envelopes() []*Envelope { 589 w.poolMu.RLock() 590 defer w.poolMu.RUnlock() 591 592 all := make([]*Envelope, 0, len(w.envelopes)) 593 for _, envelope := range w.envelopes { 594 all = append(all, envelope) 595 } 596 return all 597 } 598 599 // Messages retrieves all the decrypted messages matching a filter id. 600 func (w *Whisper) Messages(id string) []*ReceivedMessage { 601 result := make([]*ReceivedMessage, 0) 602 w.poolMu.RLock() 603 defer w.poolMu.RUnlock() 604 605 if filter := w.filters.Get(id); filter != nil { 606 for _, msg := range w.messages { 607 if filter.MatchMessage(msg) { 608 result = append(result, msg) 609 } 610 } 611 } 612 return result 613 } 614 615 func (w *Whisper) isEnvelopeCached(hash common.Hash) bool { 616 w.poolMu.Lock() 617 defer w.poolMu.Unlock() 618 619 _, exist := w.envelopes[hash] 620 return exist 621 } 622 623 func (w *Whisper) addDecryptedMessage(msg *ReceivedMessage) { 624 w.poolMu.Lock() 625 defer w.poolMu.Unlock() 626 627 w.messages[msg.EnvelopeHash] = msg 628 } 629 630 func (s *Statistics) clear() { 631 s.memoryCleared = 0 632 s.messagesCleared = 0 633 } 634 635 func ValidatePublicKey(k *ecdsa.PublicKey) bool { 636 return k != nil && k.X != nil && k.Y != nil && k.X.Sign() != 0 && k.Y.Sign() != 0 637 } 638 639 func validatePrivateKey(k *ecdsa.PrivateKey) bool { 640 if k == nil || k.D == nil || k.D.Sign() == 0 { 641 return false 642 } 643 return ValidatePublicKey(&k.PublicKey) 644 } 645 646 // validateSymmetricKey returns false if the key contains all zeros 647 func validateSymmetricKey(k []byte) bool { 648 return len(k) > 0 && !containsOnlyZeros(k) 649 } 650 651 func containsOnlyZeros(data []byte) bool { 652 for _, b := range data { 653 if b != 0 { 654 return false 655 } 656 } 657 return true 658 } 659 660 func bytesToIntLittleEndian(b []byte) (res uint64) { 661 mul := uint64(1) 662 for i := 0; i < len(b); i++ { 663 res += uint64(b[i]) * mul 664 mul *= 256 665 } 666 return res 667 } 668 669 func BytesToIntBigEndian(b []byte) (res uint64) { 670 for i := 0; i < len(b); i++ { 671 res *= 256 672 res += uint64(b[i]) 673 } 674 return res 675 } 676 677 // DeriveSymmetricKey derives symmetric key material from the key or password. 678 // pbkdf2 is used for security, in case people use password instead of randomly generated keys. 679 func deriveKeyMaterial(key []byte, version uint64) (derivedKey []byte, err error) { 680 if version == 0 { 681 // kdf should run no less than 0.1 seconds on average compute, 682 // because it's a once in a session experience 683 derivedKey := pbkdf2.Key(key, nil, 65356, aesKeyLength, sha256.New) 684 return derivedKey, nil 685 } else { 686 return nil, unknownVersionError(version) 687 } 688 }