From 8ac71045670dbd15de9d9af8b0d0b8db641f1e49 Mon Sep 17 00:00:00 2001 From: Vlad Date: Thu, 2 Mar 2017 13:38:38 +0100 Subject: [PATCH] whisper: sym key management changed --- cmd/wnode/main.go | 18 ++-- whisper/mailserver/mailserver.go | 9 +- whisper/mailserver/server_test.go | 11 ++- whisper/whisperv5/api.go | 97 +++++++++++++------- whisper/whisperv5/api_test.go | 39 +++++--- whisper/whisperv5/doc.go | 1 + whisper/whisperv5/filter.go | 35 ++------ whisper/whisperv5/filter_test.go | 2 +- whisper/whisperv5/whisper.go | 129 ++++++++++++++++++-------- whisper/whisperv5/whisper_test.go | 144 ++++++++++++++++++++++++------ 10 files changed, 336 insertions(+), 149 deletions(-) diff --git a/cmd/wnode/main.go b/cmd/wnode/main.go index f631c03bad..1746247f01 100644 --- a/cmd/wnode/main.go +++ b/cmd/wnode/main.go @@ -46,7 +46,6 @@ import ( ) const quitCommand = "~Q" -const symKeyName = "da919ea33001b04dfc630522e33078ec0df11" // singletons var ( @@ -288,8 +287,14 @@ func configureNode() { } } - shh.AddSymKey(symKeyName, []byte(symPass)) - symKey = shh.GetSymKey(symKeyName) + symKeyID, err := shh.AddSymKeyFromPassword(symPass) + if err != nil { + utils.Fatalf("Failed to create symmetric key: %s", err) + } + symKey, err = shh.GetSymKey(symKeyID) + if err != nil { + utils.Fatalf("Failed to save symmetric key: %s", err) + } if len(*argTopic) == 0 { generateTopic([]byte(symPass)) } @@ -470,11 +475,14 @@ func requestExpiredMessagesLoop() { var t string var xt, empty whisper.TopicType - err := shh.AddSymKey(mailserver.MailServerKeyName, []byte(msPassword)) + keyID, err := shh.AddSymKeyFromPassword(msPassword) if err != nil { utils.Fatalf("Failed to create symmetric key for mail request: %s", err) } - key = shh.GetSymKey(mailserver.MailServerKeyName) + key, err = shh.GetSymKey(keyID) + if err != nil { + utils.Fatalf("Failed to save symmetric key for mail request: %s", err) + } peerID = extractIdFromEnode(*argEnode) shh.MarkPeerTrusted(peerID) diff --git a/whisper/mailserver/mailserver.go b/whisper/mailserver/mailserver.go index 6533c56c2f..d705c622f4 100644 --- a/whisper/mailserver/mailserver.go +++ b/whisper/mailserver/mailserver.go @@ -31,8 +31,6 @@ import ( "github.com/syndtr/goleveldb/leveldb/util" ) -const MailServerKeyName = "958e04ab302fb36ad2616a352cbac79d" - type WMailServer struct { db *leveldb.DB w *whisper.Whisper @@ -75,11 +73,14 @@ func (s *WMailServer) Init(shh *whisper.Whisper, path string, password string, p s.w = shh s.pow = pow - err = s.w.AddSymKey(MailServerKeyName, []byte(password)) + MailServerKeyID, err := s.w.AddSymKeyFromPassword(password) if err != nil { utils.Fatalf("Failed to create symmetric key for MailServer: %s", err) } - s.key = s.w.GetSymKey(MailServerKeyName) + s.key, err = s.w.GetSymKey(MailServerKeyID) + if err != nil { + utils.Fatalf("Failed to save symmetric key for MailServer") + } } func (s *WMailServer) Close() { diff --git a/whisper/mailserver/server_test.go b/whisper/mailserver/server_test.go index 8b58a826fd..9304d81774 100644 --- a/whisper/mailserver/server_test.go +++ b/whisper/mailserver/server_test.go @@ -30,8 +30,8 @@ import ( ) const powRequirement = 0.00001 -const keyName = "6d604bac5401ce9a6b995f1b45a4ab" +var keyID string var shh *whisper.Whisper var seed = time.Now().Unix() @@ -90,7 +90,7 @@ func TestMailServer(t *testing.T) { server.Init(shh, dir, password, powRequirement) defer server.Close() - err = shh.AddSymKey(keyName, []byte(password)) + keyID, err = shh.AddSymKeyFromPassword(password) if err != nil { t.Fatalf("Failed to create symmetric key for mail request: %s", err) } @@ -167,8 +167,13 @@ func createRequest(t *testing.T, p *ServerTestParams) *whisper.Envelope { binary.BigEndian.PutUint32(data[4:], p.upp) copy(data[8:], p.topic[:]) + key, err := shh.GetSymKey(keyID) + if err != nil { + t.Fatalf("failed to retrieve sym key with seed %d: %s.", seed, err) + } + params := &whisper.MessageParams{ - KeySym: shh.GetSymKey(keyName), + KeySym: key, Topic: p.topic, Payload: data, PoW: powRequirement * 2, diff --git a/whisper/whisperv5/api.go b/whisper/whisperv5/api.go index ba99350189..456e16fa21 100644 --- a/whisper/whisperv5/api.go +++ b/whisper/whisperv5/api.go @@ -134,40 +134,63 @@ func (api *PublicWhisperAPI) NewIdentity() (string, error) { return common.ToHex(crypto.FromECDSAPub(&identity.PublicKey)), nil } -// GenerateSymKey generates a random symmetric key and stores it under -// the 'name' id. Will be used in the future for session key exchange. -func (api *PublicWhisperAPI) GenerateSymKey(name string) error { +// todo: implement +//func (api *PublicWhisperAPI) GetPublicKey(id string) (bool, error) { +// if api.whisper == nil { +// return false, whisperOffLineErr +// } +// return api.whisper.HasIdentity(identity), nil +//} + +// GenerateSymKey generates a random symmetric key and stores it under id, +// which is then returned. Will be used in the future for session key exchange. +func (api *PublicWhisperAPI) GenerateSymKey() (string, error) { if api.whisper == nil { - return whisperOffLineErr + return "", whisperOffLineErr } - return api.whisper.GenerateSymKey(name) + return api.whisper.GenerateSymKey() } -// AddSymKey stores the key under the 'name' id. -func (api *PublicWhisperAPI) AddSymKey(name string, key hexutil.Bytes) error { +// AddSymKeyDirect stores the key, and returns its id. +func (api *PublicWhisperAPI) AddSymKeyDirect(key hexutil.Bytes) (string, error) { if api.whisper == nil { - return whisperOffLineErr + return "", whisperOffLineErr } - return api.whisper.AddSymKey(name, key) + return api.whisper.AddSymKeyDirect(key) } -// HasSymKey returns true if there is a key associated with the name string. +// AddSymKeyFromPassword generates the key from password, stores it, and returns its id. +func (api *PublicWhisperAPI) AddSymKeyFromPassword(password string) (string, error) { + if api.whisper == nil { + return "", whisperOffLineErr + } + return api.whisper.AddSymKeyFromPassword(password) +} + +// HasSymKey returns true if there is a key associated with the given id. // Otherwise returns false. -func (api *PublicWhisperAPI) HasSymKey(name string) (bool, error) { +func (api *PublicWhisperAPI) HasSymKey(id string) (bool, error) { if api.whisper == nil { return false, whisperOffLineErr } - res := api.whisper.HasSymKey(name) + res := api.whisper.HasSymKey(id) return res, nil } -// DeleteSymKey deletes the key associated with the name string if it exists. -func (api *PublicWhisperAPI) DeleteSymKey(name string) error { +func (api *PublicWhisperAPI) GetSymKey(name string) ([]byte, error) { if api.whisper == nil { - return whisperOffLineErr + return nil, whisperOffLineErr } - api.whisper.DeleteSymKey(name) - return nil + return api.whisper.GetSymKey(name) +} + +// DeleteSymKey deletes the key associated with the name string if it exists. +func (api *PublicWhisperAPI) DeleteSymKey(name string) (bool, error) { + if api.whisper == nil { + return false, whisperOffLineErr + } + res := api.whisper.DeleteSymKey(name) + return res, nil } // NewWhisperFilter creates and registers a new message filter to watch for inbound whisper messages. @@ -177,9 +200,21 @@ func (api *PublicWhisperAPI) NewFilter(args WhisperFilterArgs) (string, error) { return "", whisperOffLineErr } + var err error + var symKey []byte + + if len(args.KeyName) > 0 { + symKey, err = api.whisper.GetSymKey(args.KeyName) + if err != nil { + info := "NewFilter: symmetric key ID does not exist: " + args.KeyName + log.Error(fmt.Sprintf(info)) + return "", errors.New(info) + } + } + filter := Filter{ Src: crypto.ToECDSAPub(common.FromHex(args.From)), - KeySym: api.whisper.GetSymKey(args.KeyName), + KeySym: symKey, PoW: args.PoW, Messages: make(map[common.Hash]*ReceivedMessage), AcceptP2P: args.AcceptP2P, @@ -195,12 +230,6 @@ func (api *PublicWhisperAPI) NewFilter(args WhisperFilterArgs) (string, error) { return "", errors.New(info) } - if len(args.KeyName) != 0 && len(filter.KeySym) == 0 { - info := "NewFilter: key was not found by name: " + args.KeyName - log.Error(fmt.Sprintf(info)) - return "", errors.New(info) - } - if len(args.To) == 0 && len(filter.KeySym) == 0 { info := "NewFilter: filter must contain either symmetric or asymmetric key" log.Error(fmt.Sprintf(info)) @@ -275,10 +304,22 @@ func (api *PublicWhisperAPI) Post(args PostArgs) error { return whisperOffLineErr } + var err error + var symKey []byte + + if len(args.KeyName) > 0 { + symKey, err = api.whisper.GetSymKey(args.KeyName) + if err != nil { + info := "NewFilter: symmetric key ID does not exist: " + args.KeyName + log.Error(fmt.Sprintf(info)) + return errors.New(info) + } + } + params := MessageParams{ TTL: args.TTL, Dst: crypto.ToECDSAPub(common.FromHex(args.To)), - KeySym: api.whisper.GetSymKey(args.KeyName), + KeySym: symKey, Topic: args.Topic, Payload: args.Payload, Padding: args.Padding, @@ -333,12 +374,6 @@ func (api *PublicWhisperAPI) Post(args PostArgs) error { } // validate - if len(args.KeyName) != 0 && len(params.KeySym) == 0 { - info := "Post: key was not found by name: " + args.KeyName - log.Error(fmt.Sprintf(info)) - return errors.New(info) - } - if len(args.To) == 0 && len(params.KeySym) == 0 { info := "Post: message must be encrypted either symmetrically or asymmetrically" log.Error(fmt.Sprintf(info)) diff --git a/whisper/whisperv5/api_test.go b/whisper/whisperv5/api_test.go index 9c8fb2841b..a94909ecca 100644 --- a/whisper/whisperv5/api_test.go +++ b/whisper/whisperv5/api_test.go @@ -106,7 +106,7 @@ func TestBasic(t *testing.T) { t.Fatalf("failed HasSymKey: false positive.") } - err = api.GenerateSymKey(id) + id, err = api.GenerateSymKey() if err != nil { t.Fatalf("failed GenerateSymKey: %s.", err) } @@ -119,12 +119,13 @@ func TestBasic(t *testing.T) { t.Fatalf("failed HasSymKey(): false negative.") } - err = api.AddSymKey(id, []byte("some stuff here")) - if err == nil { + const password = "some stuff here" + id, err = api.AddSymKeyFromPassword(password) + if err != nil { t.Fatalf("failed AddSymKey: %s.", err) } - err = api.AddSymKey(id2, []byte("some stuff here")) + id2, err = api.AddSymKeyFromPassword(password) if err != nil { t.Fatalf("failed AddSymKey: %s.", err) } @@ -137,10 +138,26 @@ func TestBasic(t *testing.T) { t.Fatalf("failed HasSymKey(id2): false negative.") } - err = api.DeleteSymKey(id) + k1, err := api.GetSymKey(id) + if err != nil { + t.Fatalf("failed GetSymKey(id): %s.", err) + } + k2, err := api.GetSymKey(id2) + if err != nil { + t.Fatalf("failed GetSymKey(id2): %s.", err) + } + + if !bytes.Equal(k1, k2) { + t.Fatalf("installed keys are not equal") + } + + exist, err = api.DeleteSymKey(id) if err != nil { t.Fatalf("failed DeleteSymKey(id): %s.", err) } + if !exist { + t.Fatalf("failed DeleteSymKey(id): false negative.") + } exist, err = api.HasSymKey(id) if err != nil { @@ -384,8 +401,7 @@ func TestIntegrationSym(t *testing.T) { api.Start() defer api.Stop() - keyname := "schluessel" - err := api.GenerateSymKey(keyname) + keyID, err := api.GenerateSymKey() if err != nil { t.Fatalf("failed GenerateSymKey: %s.", err) } @@ -410,7 +426,7 @@ func TestIntegrationSym(t *testing.T) { topics[0] = TopicType{0x00, 0x7f, 0x80, 0xff} topics[1] = TopicType{0xf2, 0x6e, 0x77, 0x79} var f WhisperFilterArgs - f.KeyName = keyname + f.KeyName = keyID f.Topics = topics[:] f.PoW = 0.324 f.From = sig @@ -423,7 +439,7 @@ func TestIntegrationSym(t *testing.T) { var p PostArgs p.TTL = 1 - p.KeyName = keyname + p.KeyName = keyID p.From = f.From p.Padding = []byte("test string") p.Payload = []byte("extended test string") @@ -474,8 +490,7 @@ func TestIntegrationSymWithFilter(t *testing.T) { api.Start() defer api.Stop() - keyname := "schluessel" - err := api.GenerateSymKey(keyname) + keyID, err := api.GenerateSymKey() if err != nil { t.Fatalf("failed to GenerateSymKey: %s.", err) } @@ -500,7 +515,7 @@ func TestIntegrationSymWithFilter(t *testing.T) { topics[0] = TopicType{0x00, 0x7f, 0x80, 0xff} topics[1] = TopicType{0xf2, 0x6e, 0x77, 0x79} var f WhisperFilterArgs - f.KeyName = keyname + f.KeyName = keyID f.Topics = topics[:] f.PoW = 0.324 f.From = sig diff --git a/whisper/whisperv5/doc.go b/whisper/whisperv5/doc.go index 69756eacee..4b735cbc6c 100644 --- a/whisper/whisperv5/doc.go +++ b/whisper/whisperv5/doc.go @@ -54,6 +54,7 @@ const ( aesKeyLength = 32 saltLength = 12 AESNonceMaxLength = 12 + keyIdSize = 32 DefaultMaxMessageLength = 1024 * 1024 DefaultMinimumPoW = 10.0 // todo: review after testing. diff --git a/whisper/whisperv5/filter.go b/whisper/whisperv5/filter.go index 40c2ebbc1e..cfb8f0f4b0 100644 --- a/whisper/whisperv5/filter.go +++ b/whisper/whisperv5/filter.go @@ -18,7 +18,6 @@ package whisperv5 import ( "crypto/ecdsa" - crand "crypto/rand" "fmt" "sync" @@ -52,40 +51,24 @@ func NewFilters(w *Whisper) *Filters { } } -func (fs *Filters) generateRandomID() (id string, err error) { - buf := make([]byte, 20) - for i := 0; i < 3; i++ { - _, err = crand.Read(buf) - if err != nil { - continue - } - if !validateSymmetricKey(buf) { - err = fmt.Errorf("error in generateRandomID: crypto/rand failed to generate random data") - continue - } - id = common.Bytes2Hex(buf) - if fs.watchers[id] != nil { - err = fmt.Errorf("error in generateRandomID: generated same ID twice") - continue - } - return id, err - } - - return "", err -} - func (fs *Filters) Install(watcher *Filter) (string, error) { if watcher.Messages == nil { watcher.Messages = make(map[common.Hash]*ReceivedMessage) } + id, err := GenerateRandomID() + if err != nil { + return "", err + } + fs.mutex.Lock() defer fs.mutex.Unlock() - id, err := fs.generateRandomID() - if err == nil { - fs.watchers[id] = watcher + if fs.watchers[id] != nil { + return "", fmt.Errorf("failed to generate unique ID") } + + fs.watchers[id] = watcher return id, err } diff --git a/whisper/whisperv5/filter_test.go b/whisper/whisperv5/filter_test.go index d69fb40dbf..b4f52a8185 100644 --- a/whisper/whisperv5/filter_test.go +++ b/whisper/whisperv5/filter_test.go @@ -108,7 +108,7 @@ func TestInstallFilters(t *testing.T) { t.Fatalf("seed %d: failed to install filter: %s", seed, err) } tst[i].id = j - if len(j) != 40 { + if len(j) != keyIdSize*2 { t.Fatalf("seed %d: wrong filter id size [%d]", seed, len(j)) } } diff --git a/whisper/whisperv5/whisper.go b/whisper/whisperv5/whisper.go index 2f416cae19..fd9f544817 100644 --- a/whisper/whisperv5/whisper.go +++ b/whisper/whisperv5/whisper.go @@ -48,8 +48,9 @@ type Whisper struct { filters *Filters privateKeys map[string]*ecdsa.PrivateKey - symKeys map[string][]byte - keyMu sync.RWMutex + //identities map[string]*ecdsa.PrivateKey + symKeys map[string][]byte + keyMu sync.RWMutex envelopes map[common.Hash]*Envelope // Pool of envelopes currently tracked by this node expirations map[uint32]*set.SetNonTS // Message expiration pool @@ -75,7 +76,8 @@ type Whisper struct { // Param s should be passed if you want to implement mail server, otherwise nil. func New() *Whisper { whisper := &Whisper{ - privateKeys: make(map[string]*ecdsa.PrivateKey), + privateKeys: make(map[string]*ecdsa.PrivateKey), + //identities: make(map[string]*ecdsa.PrivateKey), symKeys: make(map[string][]byte), envelopes: make(map[common.Hash]*Envelope), expirations: make(map[uint32]*set.SetNonTS), @@ -231,72 +233,108 @@ func (w *Whisper) GetIdentity(pubKey string) *ecdsa.PrivateKey { return w.privateKeys[pubKey] } -func (w *Whisper) GenerateSymKey(name string) error { +func (w *Whisper) GenerateSymKey() (string, error) { const size = aesKeyLength * 2 buf := make([]byte, size) _, err := crand.Read(buf) if err != nil { - return err + return "", err } else if !validateSymmetricKey(buf) { - return fmt.Errorf("error in GenerateSymKey: crypto/rand failed to generate random data") + return "", fmt.Errorf("error in GenerateSymKey: crypto/rand failed to generate random data") } key := buf[:aesKeyLength] salt := buf[aesKeyLength:] derived, err := DeriveOneTimeKey(key, salt, EnvelopeVersion) if err != nil { - return err + return "", err } else if !validateSymmetricKey(derived) { - return fmt.Errorf("failed to derive valid key") + return "", fmt.Errorf("failed to derive valid key") } - w.keyMu.Lock() - defer w.keyMu.Unlock() - - if w.symKeys[name] != nil { - return fmt.Errorf("Key with name [%s] already exists", name) - } - w.symKeys[name] = derived - return nil -} - -func (w *Whisper) AddSymKey(name string, key []byte) error { - if w.HasSymKey(name) { - return fmt.Errorf("Key with name [%s] already exists", name) - } - - derived, err := deriveKeyMaterial(key, EnvelopeVersion) + id, err := GenerateRandomID() if err != nil { - return err + return "", fmt.Errorf("Failed to generate ID: %s", err) } w.keyMu.Lock() defer w.keyMu.Unlock() - // double check is necessary, because deriveKeyMaterial() is slow - if w.symKeys[name] != nil { - return fmt.Errorf("Key with name [%s] already exists", name) + if w.symKeys[id] != nil { + return "", fmt.Errorf("Failed to generate unique ID") } - w.symKeys[name] = derived - return nil + w.symKeys[id] = derived + return id, nil } -func (w *Whisper) HasSymKey(name string) bool { - w.keyMu.RLock() - defer w.keyMu.RUnlock() - return w.symKeys[name] != nil -} +func (w *Whisper) AddSymKeyDirect(key []byte) (string, error) { + if len(key) != aesKeyLength { + return "", fmt.Errorf("Wrong key size: %d", len(key)) + } + + id, err := GenerateRandomID() + if err != nil { + return "", fmt.Errorf("Failed to generate ID: %s", err) + } -func (w *Whisper) DeleteSymKey(name string) { w.keyMu.Lock() defer w.keyMu.Unlock() - delete(w.symKeys, name) + + if w.symKeys[id] != nil { + return "", fmt.Errorf("Failed to generate unique ID") + } + w.symKeys[id] = key + return id, nil } -func (w *Whisper) GetSymKey(name string) []byte { +func (w *Whisper) AddSymKeyFromPassword(password string) (string, error) { + id, err := GenerateRandomID() + if err != nil { + return "", fmt.Errorf("Failed to generate ID: %s", err) + } + if w.HasSymKey(id) { + return "", fmt.Errorf("Failed to generate unique ID") + } + + derived, err := deriveKeyMaterial([]byte(password), EnvelopeVersion) + if err != nil { + return "", err + } + + w.keyMu.Lock() + defer w.keyMu.Unlock() + + // double check is necessary, because deriveKeyMaterial() is very slow + if w.symKeys[id] != nil { + return "", fmt.Errorf("Severe error: failed to generate unique ID") + } + w.symKeys[id] = derived + return id, nil +} + +func (w *Whisper) HasSymKey(id string) bool { w.keyMu.RLock() defer w.keyMu.RUnlock() - return w.symKeys[name] + return w.symKeys[id] != nil +} + +func (w *Whisper) DeleteSymKey(id string) bool { + w.keyMu.Lock() + defer w.keyMu.Unlock() + if w.symKeys[id] != nil { + delete(w.symKeys, id) + return true + } + return false +} + +func (w *Whisper) GetSymKey(id string) ([]byte, error) { + w.keyMu.RLock() + defer w.keyMu.RUnlock() + if w.symKeys[id] != nil { + return w.symKeys[id], nil + } + return nil, fmt.Errorf("non-existent ID") } // Watch installs a new message handler to run in case a matching packet arrives @@ -709,3 +747,16 @@ func deriveKeyMaterial(key []byte, version uint64) (derivedKey []byte, err error return nil, unknownVersionError(version) } } + +func GenerateRandomID() (id string, err error) { + buf := make([]byte, keyIdSize) + _, err = crand.Read(buf) + if err != nil { + return "", err + } + if !validateSymmetricKey(buf) { + return "", fmt.Errorf("error in generateRandomID: crypto/rand failed to generate random data") + } + id = common.Bytes2Hex(buf) + return id, err +} diff --git a/whisper/whisperv5/whisper_test.go b/whisper/whisperv5/whisper_test.go index fbaebe8306..9a9142c0ca 100644 --- a/whisper/whisperv5/whisper_test.go +++ b/whisper/whisperv5/whisper_test.go @@ -61,9 +61,12 @@ func TestWhisperBasic(t *testing.T) { if exist { t.Fatalf("failed HasSymKey.") } - key := w.GetSymKey("non-existing") + key, err := w.GetSymKey("non-existing") + if err == nil { + t.Fatalf("failed GetSymKey(non-existing): false positive.") + } if key != nil { - t.Fatalf("failed GetSymKey.") + t.Fatalf("failed GetSymKey: false positive.") } mail := w.Envelopes() if len(mail) != 0 { @@ -79,7 +82,7 @@ func TestWhisperBasic(t *testing.T) { if _, err := deriveKeyMaterial(peerID, ver); err != unknownVersionError(ver) { t.Fatalf("failed deriveKeyMaterial with param = %v: %s.", peerID, err) } - derived, err := deriveKeyMaterial(peerID, 0) + derived, err = deriveKeyMaterial(peerID, 0) if err != nil { t.Fatalf("failed second deriveKeyMaterial with param = %v: %s.", peerID, err) } @@ -185,23 +188,30 @@ func TestWhisperIdentityManagement(t *testing.T) { func TestWhisperSymKeyManagement(t *testing.T) { InitSingleTest() + var err error var k1, k2 []byte w := New() id1 := string("arbitrary-string-1") id2 := string("arbitrary-string-2") - err := w.GenerateSymKey(id1) + id1, err = w.GenerateSymKey() if err != nil { t.Fatalf("failed GenerateSymKey with seed %d: %s.", seed, err) } - k1 = w.GetSymKey(id1) - k2 = w.GetSymKey(id2) + k1, err = w.GetSymKey(id1) + if err != nil { + t.Fatalf("failed GetSymKey(id1).") + } + k2, err = w.GetSymKey(id2) + if err == nil { + t.Fatalf("failed GetSymKey(id2): false positive.") + } if !w.HasSymKey(id1) { t.Fatalf("failed HasSymKey(id1).") } if w.HasSymKey(id2) { - t.Fatalf("failed HasSymKey(id2).") + t.Fatalf("failed HasSymKey(id2): false positive.") } if k1 == nil { t.Fatalf("first key does not exist.") @@ -210,38 +220,49 @@ func TestWhisperSymKeyManagement(t *testing.T) { t.Fatalf("second key still exist.") } - // add existing id, nothing should change - randomKey := make([]byte, 16) + randomKey := make([]byte, aesKeyLength) randomize(randomKey) - err = w.AddSymKey(id1, randomKey) - if err == nil { - t.Fatalf("failed AddSymKey with seed %d.", seed) + id1, err = w.AddSymKeyDirect(randomKey) + if err != nil { + t.Fatalf("failed AddSymKey with seed %d: %s.", seed, err) } - k1 = w.GetSymKey(id1) - k2 = w.GetSymKey(id2) + k1, err = w.GetSymKey(id1) + if err != nil { + t.Fatalf("failed w.GetSymKey(id1).") + } + k2, err = w.GetSymKey(id2) + if err == nil { + t.Fatalf("failed w.GetSymKey(id2): false positive.") + } if !w.HasSymKey(id1) { t.Fatalf("failed w.HasSymKey(id1).") } if w.HasSymKey(id2) { - t.Fatalf("failed w.HasSymKey(id2).") + t.Fatalf("failed w.HasSymKey(id2): false positive.") } if k1 == nil { t.Fatalf("first key does not exist.") } - if bytes.Equal(k1, randomKey) { - t.Fatalf("k1 == randomKey.") + if !bytes.Equal(k1, randomKey) { + t.Fatalf("k1 != randomKey.") } if k2 != nil { t.Fatalf("second key already exist.") } - err = w.AddSymKey(id2, randomKey) // add non-existing (yet) + id2, err = w.AddSymKeyDirect(randomKey) if err != nil { t.Fatalf("failed AddSymKey(id2) with seed %d: %s.", seed, err) } - k1 = w.GetSymKey(id1) - k2 = w.GetSymKey(id2) + k1, err = w.GetSymKey(id1) + if err != nil { + t.Fatalf("failed w.GetSymKey(id1).") + } + k2, err = w.GetSymKey(id2) + if err != nil { + t.Fatalf("failed w.GetSymKey(id2).") + } if !w.HasSymKey(id1) { t.Fatalf("HasSymKey(id1) failed.") } @@ -254,11 +275,11 @@ func TestWhisperSymKeyManagement(t *testing.T) { if k2 == nil { t.Fatalf("k2 does not exist.") } - if bytes.Equal(k1, k2) { - t.Fatalf("k1 == k2.") + if !bytes.Equal(k1, k2) { + t.Fatalf("k1 != k2.") } - if bytes.Equal(k1, randomKey) { - t.Fatalf("k1 == randomKey.") + if !bytes.Equal(k1, randomKey) { + t.Fatalf("k1 != randomKey.") } if len(k1) != aesKeyLength { t.Fatalf("wrong length of k1.") @@ -268,8 +289,17 @@ func TestWhisperSymKeyManagement(t *testing.T) { } w.DeleteSymKey(id1) - k1 = w.GetSymKey(id1) - k2 = w.GetSymKey(id2) + k1, err = w.GetSymKey(id1) + if err == nil { + t.Fatalf("failed w.GetSymKey(id1): false positive.") + } + if k1 != nil { + t.Fatalf("failed GetSymKey(id1): false positive.") + } + k2, err = w.GetSymKey(id2) + if err != nil { + t.Fatalf("failed w.GetSymKey(id2).") + } if w.HasSymKey(id1) { t.Fatalf("failed to delete first key: still exist.") } @@ -285,8 +315,17 @@ func TestWhisperSymKeyManagement(t *testing.T) { w.DeleteSymKey(id1) w.DeleteSymKey(id2) - k1 = w.GetSymKey(id1) - k2 = w.GetSymKey(id2) + k1, err = w.GetSymKey(id1) + if err == nil { + t.Fatalf("failed w.GetSymKey(id1): false positive.") + } + k2, err = w.GetSymKey(id2) + if err == nil { + t.Fatalf("failed w.GetSymKey(id2): false positive.") + } + if k1 != nil || k2 != nil { + t.Fatalf("k1 or k2 is not nil") + } if w.HasSymKey(id1) { t.Fatalf("failed to delete second key: first key exist.") } @@ -299,6 +338,55 @@ func TestWhisperSymKeyManagement(t *testing.T) { if k2 != nil { t.Fatalf("failed to delete second key: second key is not nil.") } + + randomKey = make([]byte, aesKeyLength+1) + randomize(randomKey) + id1, err = w.AddSymKeyDirect(randomKey) + if err == nil { + t.Fatalf("added the key with wrong size, seed %d.", seed) + } + + const password = "arbitrary data here" + id1, err = w.AddSymKeyFromPassword(password) + if err != nil { + t.Fatalf("failed AddSymKeyFromPassword(id1) with seed %d: %s.", seed, err) + } + id2, err = w.AddSymKeyFromPassword(password) + if err != nil { + t.Fatalf("failed AddSymKeyFromPassword(id2) with seed %d: %s.", seed, err) + } + k1, err = w.GetSymKey(id1) + if err != nil { + t.Fatalf("failed w.GetSymKey(id1).") + } + k2, err = w.GetSymKey(id2) + if err != nil { + t.Fatalf("failed w.GetSymKey(id2).") + } + if !w.HasSymKey(id1) { + t.Fatalf("HasSymKey(id1) failed.") + } + if !w.HasSymKey(id2) { + t.Fatalf("HasSymKey(id2) failed.") + } + if k1 == nil { + t.Fatalf("k1 does not exist.") + } + if k2 == nil { + t.Fatalf("k2 does not exist.") + } + if !bytes.Equal(k1, k2) { + t.Fatalf("k1 != k2.") + } + if len(k1) != aesKeyLength { + t.Fatalf("wrong length of k1.") + } + if len(k2) != aesKeyLength { + t.Fatalf("wrong length of k2.") + } + if !validateSymmetricKey(k2) { + t.Fatalf("key validation failed.") + } } func TestExpiry(t *testing.T) {