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  }