diff --git a/swarm/pss/keystore.go b/swarm/pss/keystore.go index 83743c8fdf..4625f627ca 100644 --- a/swarm/pss/keystore.go +++ b/swarm/pss/keystore.go @@ -30,6 +30,8 @@ import ( ) type KeyStore struct { + w *whisper.Whisper // key and encryption backend + mx sync.RWMutex pubKeyPool map[string]map[Topic]*pssPeer // mapping of hex public keys to peer address by topic. symKeyPool map[string]map[Topic]*pssPeer // mapping of symkeyids to peer address by topic. @@ -37,8 +39,10 @@ type KeyStore struct { symKeyDecryptCacheCursor int // modular cursor pointing to last used, wraps on symKeyDecryptCache array } -func newKeyStore() *KeyStore { +func loadKeyStore() *KeyStore { return &KeyStore{ + w: whisper.New(&whisper.DefaultConfig), + pubKeyPool: make(map[string]map[Topic]*pssPeer), symKeyPool: make(map[string]map[Topic]*pssPeer), symKeyDecryptCache: make([]*string, defaultSymKeyCacheCapacity), @@ -146,10 +150,12 @@ func (ks *KeyStore) getPeerAddress(keyid string, topic Topic) (PssAddress, error // encapsulating the decrypted message, and the whisper backend id // of the symmetric key used to decrypt the message. // It fails if decryption of the message fails or if the message is corrupted. -func (ks *KeyStore) processSymMsg(w *whisper.Whisper, envelope *whisper.Envelope) (*whisper.ReceivedMessage, string, PssAddress, error) { +func (ks *KeyStore) processSym(envelope *whisper.Envelope) (*whisper.ReceivedMessage, string, PssAddress, error) { + metrics.GetOrRegisterCounter("pss.process.sym", nil).Inc(1) + for i := ks.symKeyDecryptCacheCursor; i > ks.symKeyDecryptCacheCursor-cap(ks.symKeyDecryptCache) && i > 0; i-- { symkeyid := ks.symKeyDecryptCache[i%cap(ks.symKeyDecryptCache)] - symkey, err := w.GetSymKey(*symkeyid) + symkey, err := ks.w.GetSymKey(*symkeyid) if err != nil { continue } @@ -232,3 +238,44 @@ func (ks *Pss) cleanKeys() (count int) { } return count } + +// Automatically generate a new symkey for a topic and address hint +func (ks *KeyStore) GenerateSymmetricKey(topic Topic, address PssAddress, addToCache bool) (string, error) { + keyid, err := ks.w.GenerateSymKey() + if err == nil { + ks.addSymmetricKeyToPool(keyid, topic, address, addToCache, false) + } + return keyid, err +} + +// Returns a symmetric key byte sequence stored in the whisper backend by its unique id. +// Passes on the error value from the whisper backend. +func (ks *KeyStore) GetSymmetricKey(symkeyid string) ([]byte, error) { + return ks.w.GetSymKey(symkeyid) +} + +// Links a peer symmetric key (arbitrary byte sequence) to a topic. +// +// This is required for symmetrically encrypted message exchange on the given topic. +// +// The key is stored in the whisper backend. +// +// If addtocache is set to true, the key will be added to the cache of keys +// used to attempt symmetric decryption of incoming messages. +// +// Returns a string id that can be used to retrieve the key bytes +// from the whisper backend (see pss.GetSymmetricKey()) +func (ks *KeyStore) SetSymmetricKey(key []byte, topic Topic, address PssAddress, addtocache bool) (string, error) { + if err := validateAddress(address); err != nil { + return "", err + } + return ks.setSymmetricKey(key, topic, address, addtocache, true) +} + +func (ks *KeyStore) setSymmetricKey(key []byte, topic Topic, address PssAddress, addtocache bool, protected bool) (string, error) { + keyid, err := ks.w.AddSymKeyDirect(key) + if err == nil { + ks.addSymmetricKeyToPool(keyid, topic, address, addtocache, protected) + } + return keyid, err +} diff --git a/swarm/pss/pss.go b/swarm/pss/pss.go index 9231fbd28f..0b8cc148c5 100644 --- a/swarm/pss/pss.go +++ b/swarm/pss/pss.go @@ -116,7 +116,6 @@ type Pss struct { *KeyStore privateKey *ecdsa.PrivateKey // pss can have it's own independent key - w *whisper.Whisper // key and encryption backend auxAPIs []rpc.API // builtins (handshake, test) can add APIs // sending and forwarding @@ -159,10 +158,9 @@ func NewPss(k *network.Kademlia, params *PssParams) (*Pss, error) { } ps := &Pss{ Kademlia: k, - KeyStore: newKeyStore(), + KeyStore: loadKeyStore(), privateKey: params.privateKey, - w: whisper.New(&whisper.DefaultConfig), quitC: make(chan struct{}), fwdPool: make(map[string]*protocols.Peer), @@ -529,61 +527,6 @@ func (p *Pss) isSelfPossibleRecipient(msg *PssMsg, prox bool) bool { return depth <= po } -///////////////////////////////////////////////////////////////////// -// SECTION: Encryption -///////////////////////////////////////////////////////////////////// - -// Automatically generate a new symkey for a topic and address hint -func (p *Pss) GenerateSymmetricKey(topic Topic, address PssAddress, addToCache bool) (string, error) { - keyid, err := p.w.GenerateSymKey() - if err == nil { - p.addSymmetricKeyToPool(keyid, topic, address, addToCache, false) - } - return keyid, err -} - -// Links a peer symmetric key (arbitrary byte sequence) to a topic. -// -// This is required for symmetrically encrypted message exchange on the given topic. -// -// The key is stored in the whisper backend. -// -// If addtocache is set to true, the key will be added to the cache of keys -// used to attempt symmetric decryption of incoming messages. -// -// Returns a string id that can be used to retrieve the key bytes -// from the whisper backend (see pss.GetSymmetricKey()) -func (p *Pss) SetSymmetricKey(key []byte, topic Topic, address PssAddress, addtocache bool) (string, error) { - if err := validateAddress(address); err != nil { - return "", err - } - return p.setSymmetricKey(key, topic, address, addtocache, true) -} - -func (p *Pss) setSymmetricKey(key []byte, topic Topic, address PssAddress, addtocache bool, protected bool) (string, error) { - keyid, err := p.w.AddSymKeyDirect(key) - if err == nil { - p.addSymmetricKeyToPool(keyid, topic, address, addtocache, protected) - } - return keyid, err -} - -// Returns a symmetric key byte sequence stored in the whisper backend by its unique id -// Passes on the error value from the whisper backend -func (p *Pss) GetSymmetricKey(symkeyid string) ([]byte, error) { - return p.w.GetSymKey(symkeyid) -} - -// Attempt to decrypt, validate and unpack a symmetrically encrypted message. -// If successful, returns the unpacked whisper ReceivedMessage struct -// encapsulating the decrypted message, and the whisper backend id -// of the symmetric key used to decrypt the message. -// It fails if decryption of the message fails or if the message is corrupted. -func (p *Pss) processSym(envelope *whisper.Envelope) (*whisper.ReceivedMessage, string, PssAddress, error) { - metrics.GetOrRegisterCounter("pss.process.sym", nil).Inc(1) - return p.processSymMsg(p.w, envelope) -} - ///////////////////////////////////////////////////////////////////// // SECTION: Message sending /////////////////////////////////////////////////////////////////////