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