diff --git a/cmd/wnode/main.go b/cmd/wnode/main.go index 3e7219e15a..f9a1296879 100644 --- a/cmd/wnode/main.go +++ b/cmd/wnode/main.go @@ -199,23 +199,23 @@ func initialize() { shh = whisper.New() } - asymKeyID, err = shh.NewIdentity() + asymKeyID, err = shh.NewKeyPair() if err != nil { utils.Fatalf("Failed to generate a new key pair: %s", err) } - asymKey, err = shh.GetIdentity(asymKeyID) + asymKey, err = shh.GetPrivateKey(asymKeyID) if err != nil { utils.Fatalf("Failed to retrieve a new key pair: %s", err) } if nodeid == nil { - tmpID, err := shh.NewIdentity() + tmpID, err := shh.NewKeyPair() if err != nil { utils.Fatalf("Failed to generate a new key pair: %s", err) } - nodeid, err = shh.GetIdentity(tmpID) + nodeid, err = shh.GetPrivateKey(tmpID) if err != nil { utils.Fatalf("Failed to retrieve a new key pair: %s", err) } @@ -325,10 +325,10 @@ func configureNode() { } filter := whisper.Filter{ - KeySym: symKey, - KeyAsym: asymKey, - Topics: []whisper.TopicType{topic}, - AcceptP2P: p2pAccept, + KeySym: symKey, + KeyAsym: asymKey, + Topics: []whisper.TopicType{topic}, + AllowP2P: p2pAccept, } filterID, err = shh.Watch(&filter) if err != nil { diff --git a/whisper/mailserver/server_test.go b/whisper/mailserver/server_test.go index e9ae6877a6..b0d3e06e49 100644 --- a/whisper/mailserver/server_test.go +++ b/whisper/mailserver/server_test.go @@ -102,11 +102,11 @@ func TestMailServer(t *testing.T) { } func deliverTest(t *testing.T, server *WMailServer, env *whisper.Envelope) { - id, err := shh.NewIdentity() + id, err := shh.NewKeyPair() if err != nil { t.Fatalf("failed to generate new key pair with seed %d: %s.", seed, err) } - testPeerID, err := shh.GetIdentity(id) + testPeerID, err := shh.GetPrivateKey(id) if err != nil { t.Fatalf("failed to retireve new key pair with seed %d: %s.", seed, err) } diff --git a/whisper/whisperv5/api.go b/whisper/whisperv5/api.go index 0c31eb3835..9de29a6fee 100644 --- a/whisper/whisperv5/api.go +++ b/whisper/whisperv5/api.go @@ -20,12 +20,12 @@ import ( "encoding/json" "errors" "fmt" - mathrand "math/rand" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/p2p/discover" ) var whisperOffLineErr = errors.New("whisper is offline") @@ -65,7 +65,7 @@ func (api *PublicWhisperAPI) Version() (hexutil.Uint, error) { } // Stats returns the Whisper statistics for diagnostics. -func (api *PublicWhisperAPI) Stats() (string, error) { +func (api *PublicWhisperAPI) Info() (string, error) { if api.whisper == nil { return "", whisperOffLineErr } @@ -108,29 +108,29 @@ func (api *PublicWhisperAPI) MarkPeerTrusted(peerID hexutil.Bytes) error { // HasIdentity checks if the whisper node is configured with the private key // of the specified public pair. -func (api *PublicWhisperAPI) HasIdentity(id string) (bool, error) { +func (api *PublicWhisperAPI) HasKeyPair(id string) (bool, error) { if api.whisper == nil { return false, whisperOffLineErr } - return api.whisper.HasIdentity(id), nil + return api.whisper.HasKeyPair(id), nil } // DeleteIdentity deletes the specifies key if it exists. -func (api *PublicWhisperAPI) DeleteIdentity(id string) (bool, error) { +func (api *PublicWhisperAPI) DeleteKeyPair(id string) (bool, error) { if api.whisper == nil { return false, whisperOffLineErr } - success := api.whisper.DeleteIdentity(id) + success := api.whisper.DeleteKeyPair(id) return success, nil } -// NewIdentity generates a new cryptographic identity for the client, and injects +// NewKeyPair generates a new cryptographic identity for the client, and injects // it into the known identities for message decryption. -func (api *PublicWhisperAPI) NewIdentity() (string, error) { +func (api *PublicWhisperAPI) NewKeyPair() (string, error) { if api.whisper == nil { return "", whisperOffLineErr } - return api.whisper.NewIdentity() + return api.whisper.NewKeyPair() } // GetPublicKey returns the public key for identity id @@ -138,7 +138,7 @@ func (api *PublicWhisperAPI) GetPublicKey(id string) (string, error) { if api.whisper == nil { return "", whisperOffLineErr } - key, err := api.whisper.GetIdentity(id) + key, err := api.whisper.GetPrivateKey(id) if err != nil { return "", err } @@ -150,7 +150,7 @@ func (api *PublicWhisperAPI) GetPrivateKey(id string) (string, error) { if api.whisper == nil { return "", whisperOffLineErr } - key, err := api.whisper.GetIdentity(id) + key, err := api.whisper.GetPrivateKey(id) if err != nil { return "", err } @@ -159,7 +159,7 @@ func (api *PublicWhisperAPI) GetPrivateKey(id string) (string, error) { // 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) { +func (api *PublicWhisperAPI) GenerateSymmetricKey() (string, error) { if api.whisper == nil { return "", whisperOffLineErr } @@ -167,7 +167,7 @@ func (api *PublicWhisperAPI) GenerateSymKey() (string, error) { } // AddSymKeyDirect stores the key, and returns its id. -func (api *PublicWhisperAPI) AddSymKeyDirect(key hexutil.Bytes) (string, error) { +func (api *PublicWhisperAPI) AddSymmetricKeyDirect(key hexutil.Bytes) (string, error) { if api.whisper == nil { return "", whisperOffLineErr } @@ -175,7 +175,7 @@ func (api *PublicWhisperAPI) AddSymKeyDirect(key hexutil.Bytes) (string, error) } // AddSymKeyFromPassword generates the key from password, stores it, and returns its id. -func (api *PublicWhisperAPI) AddSymKeyFromPassword(password string) (string, error) { +func (api *PublicWhisperAPI) AddSymmetricKeyFromPassword(password string) (string, error) { if api.whisper == nil { return "", whisperOffLineErr } @@ -184,7 +184,7 @@ func (api *PublicWhisperAPI) AddSymKeyFromPassword(password string) (string, err // HasSymKey returns true if there is a key associated with the given id. // Otherwise returns false. -func (api *PublicWhisperAPI) HasSymKey(id string) (bool, error) { +func (api *PublicWhisperAPI) HasSymmetricKey(id string) (bool, error) { if api.whisper == nil { return false, whisperOffLineErr } @@ -192,7 +192,7 @@ func (api *PublicWhisperAPI) HasSymKey(id string) (bool, error) { return res, nil } -func (api *PublicWhisperAPI) GetSymKey(name string) ([]byte, error) { +func (api *PublicWhisperAPI) GetSymmetricKey(name string) ([]byte, error) { if api.whisper == nil { return nil, whisperOffLineErr } @@ -200,7 +200,7 @@ func (api *PublicWhisperAPI) GetSymKey(name string) ([]byte, error) { } // DeleteSymKey deletes the key associated with the name string if it exists. -func (api *PublicWhisperAPI) DeleteSymKey(name string) (bool, error) { +func (api *PublicWhisperAPI) DeleteSymmetricKey(name string) (bool, error) { if api.whisper == nil { return false, whisperOffLineErr } @@ -208,77 +208,72 @@ func (api *PublicWhisperAPI) DeleteSymKey(name string) (bool, error) { return res, nil } -// NewWhisperFilter creates and registers a new message filter to watch for inbound whisper messages. -// Returns the ID of the newly created Filter. -func (api *PublicWhisperAPI) NewFilter(args WhisperFilterArgs) (string, error) { +// Subscribe creates and registers a new filter to watch for inbound whisper messages. +// Returns the ID of the newly created filter. +func (api *PublicWhisperAPI) Subscribe(args WhisperFilterArgs) (string, error) { if api.whisper == nil { 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: symKey, - PoW: args.PoW, - Messages: make(map[common.Hash]*ReceivedMessage), - AcceptP2P: args.AcceptP2P, - } - if len(filter.KeySym) > 0 { - filter.SymKeyHash = crypto.Keccak256Hash(filter.KeySym) + Src: crypto.ToECDSAPub(common.FromHex(args.SignedWith)), + PoW: args.MinPoW, + Messages: make(map[common.Hash]*ReceivedMessage), + AllowP2P: args.AllowP2P, } + filter.Topics = append(filter.Topics, args.Topics...) - if len(args.Topics) == 0 && len(args.KeyName) != 0 { - info := "NewFilter: at least one topic must be specified" - 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)) - return "", errors.New(info) - } - - if len(args.To) != 0 && len(filter.KeySym) != 0 { - info := "NewFilter: filter must not contain both symmetric and asymmetric key" - log.Error(fmt.Sprintf(info)) - return "", errors.New(info) - } - - if len(args.To) > 0 { - dst := crypto.ToECDSAPub(common.FromHex(args.To)) - if !ValidatePublicKey(dst) { - info := "NewFilter: Invalid 'To' address" - log.Error(fmt.Sprintf(info)) + if len(args.SignedWith) > 0 { + if !ValidatePublicKey(filter.Src) { + info := "NewFilter: Invalid 'From' address" + log.Error(info) return "", errors.New(info) } - filter.KeyAsym, err = api.whisper.GetIdentity(string(args.To)) + } + + err := ValidateKeyID(args.Key) + if err != nil { + return "", err + } + + if !ValidatePublicKey(filter.Src) { + info := "NewFilter: 'SignedWith' public key is invalid" + log.Error(info) + return "", errors.New(info) + } + + if args.Symmetric { + if len(args.Topics) == 0 { + info := "NewFilter: at least one topic must be specified with symmetric encryption" + log.Error(info) + return "", errors.New(info) + } + + symKey, err := api.whisper.GetSymKey(args.Key) if err != nil { - return "", err + info := "NewFilter: invalid key ID: " + args.Key + log.Error(info) + return "", errors.New(info) + } + if !validateSymmetricKey(symKey) { + info := "NewFilter: retrieved key is invalid" + log.Error(info) + return "", errors.New(info) + } + + filter.KeySym = symKey + filter.SymKeyHash = crypto.Keccak256Hash(filter.KeySym) + } else { + filter.KeyAsym, err = api.whisper.GetPrivateKey(args.Key) + if err != nil { + info := "NewFilter: invalid key ID: " + args.Key + log.Error(info) + return "", errors.New(info) } if filter.KeyAsym == nil { info := "NewFilter: non-existent identity provided" - log.Error(fmt.Sprintf(info)) - return "", errors.New(info) - } - } - - if len(args.From) > 0 { - if !ValidatePublicKey(filter.Src) { - info := "NewFilter: Invalid 'From' address" - log.Error(fmt.Sprintf(info)) + log.Error(info) return "", errors.New(info) } } @@ -286,9 +281,9 @@ func (api *PublicWhisperAPI) NewFilter(args WhisperFilterArgs) (string, error) { return api.whisper.Watch(&filter) } -// UninstallFilter disables and removes an existing filter. -func (api *PublicWhisperAPI) UninstallFilter(filterId string) { - api.whisper.Unwatch(filterId) +// Unsubscribe disables and removes an existing filter. +func (api *PublicWhisperAPI) Unsubscribe(id string) { + api.whisper.Unsubscribe(id) } // GetFilterChanges retrieves all the new messages matched by a filter since the last retrieval. @@ -323,144 +318,110 @@ func (api *PublicWhisperAPI) Post(args PostArgs) error { } 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: symKey, - Topic: args.Topic, + WorkTime: args.PowTime, + PoW: args.PowTarget, Payload: args.Payload, Padding: args.Padding, - WorkTime: args.WorkTime, - PoW: args.PoW, } - if len(args.From) > 0 { - pub := crypto.ToECDSAPub(common.FromHex(args.From)) - if !ValidatePublicKey(pub) { - info := "Post: Invalid 'From' address" - log.Error(fmt.Sprintf(info)) - return errors.New(info) - } - params.Src, err = api.whisper.GetIdentity(string(args.From)) + if len(args.SignWith) > 0 { + params.Src, err = api.whisper.GetPrivateKey(args.SignWith) if err != nil { + log.Error(err.Error()) return err } if params.Src == nil { - info := "Post: non-existent identity provided" - log.Error(fmt.Sprintf(info)) + info := "Post: empty identity" + log.Error(info) return errors.New(info) } } - filter := api.whisper.GetFilter(args.FilterID) - if filter == nil && len(args.FilterID) > 0 { - info := fmt.Sprintf("Post: wrong filter id %s", args.FilterID) - log.Error(fmt.Sprintf(info)) + if len(args.Topic) == TopicLength { + params.Topic = BytesToTopic(args.Topic) + } else if len(args.Topic) != 0 { + info := fmt.Sprintf("Post: wrong topic size %d", len(args.Topic)) + log.Error(info) return errors.New(info) } - if filter != nil { - // get the missing fields from the filter - if params.KeySym == nil && filter.KeySym != nil { - params.KeySym = filter.KeySym + if args.Type == "sym" { + err = ValidateKeyID(args.Key) + if err != nil { + log.Error(err.Error()) + return err } - if params.Src == nil && filter.Src != nil { - params.Src = filter.KeyAsym + params.KeySym, err = api.whisper.GetSymKey(args.Key) + if err != nil { + log.Error(err.Error()) + return err } - if (params.Topic == TopicType{}) { - sz := len(filter.Topics) - if sz < 1 { - info := fmt.Sprintf("Post: no topics in filter # %s", args.FilterID) - log.Error(fmt.Sprintf(info)) - return errors.New(info) - } else if sz == 1 { - params.Topic = filter.Topics[0] - } else { - // choose randomly - rnd := mathrand.Intn(sz) - params.Topic = filter.Topics[rnd] - } + if len(params.Topic) == 0 { + info := "Post: topic is missing for symmetric encryption" + log.Error(info) + return errors.New(info) } - } - - // validate - if len(args.To) == 0 && len(params.KeySym) == 0 { - info := "Post: message must be encrypted either symmetrically or asymmetrically" - log.Error(fmt.Sprintf(info)) - return errors.New(info) - } - - if len(args.To) != 0 && len(params.KeySym) != 0 { - info := "Post: ambigous encryption method requested" - log.Error(fmt.Sprintf(info)) - return errors.New(info) - } - - if len(args.To) > 0 { + } else if args.Type == "asym" { + params.Dst = crypto.ToECDSAPub(common.FromHex(args.Key)) if !ValidatePublicKey(params.Dst) { - info := "Post: Invalid 'To' address" - log.Error(fmt.Sprintf(info)) + info := "NewFilter: 'SignWith' public key is invalid" + log.Error(info) return errors.New(info) } + } else { + info := "Post: wrong type (sym/asym)" + log.Error(info) + return errors.New(info) } // encrypt and send message := NewSentMessage(¶ms) envelope, err := message.Wrap(¶ms) if err != nil { - log.Error(fmt.Sprintf(err.Error())) + log.Error(err.Error()) return err } if envelope.size() > api.whisper.maxMsgLength { info := "Post: message is too big" - log.Error(fmt.Sprintf(info)) - return errors.New(info) - } - if (envelope.Topic == TopicType{} && envelope.IsSymmetric()) { - info := "Post: topic is missing for symmetric encryption" - log.Error(fmt.Sprintf(info)) + log.Error(info) return errors.New(info) } - if args.PeerID != nil { - return api.whisper.SendP2PMessage(args.PeerID, envelope) + if len(args.TargetPeer) != 0 { + n, err := discover.ParseNode(args.TargetPeer) + if err != nil { + info := "Post: failed to parse enode of target peer: " + err.Error() + log.Error(info) + return errors.New(info) + } + return api.whisper.SendP2PMessage(n.ID[:], envelope) } return api.whisper.Send(envelope) } type PostArgs struct { - TTL uint32 `json:"ttl"` - From string `json:"from"` - To string `json:"to"` - KeyName string `json:"keyname"` - Topic TopicType `json:"topic"` - Padding hexutil.Bytes `json:"padding"` - Payload hexutil.Bytes `json:"payload"` - WorkTime uint32 `json:"worktime"` - PoW float64 `json:"pow"` - FilterID string `json:"filterID"` - PeerID hexutil.Bytes `json:"peerID"` + Type string `json:"type"` + TTL uint32 `json:"ttl"` + SignWith string `json:"signWith"` + Key string `json:"key"` + Topic hexutil.Bytes `json:"topic"` + Padding hexutil.Bytes `json:"padding"` + Payload hexutil.Bytes `json:"payload"` + PowTime uint32 `json:"powTime"` + PowTarget float64 `json:"powTarget"` + TargetPeer string `json:"targetPeer"` } type WhisperFilterArgs struct { - To string `json:"to"` - From string `json:"from"` - KeyName string `json:"keyname"` - PoW float64 `json:"pow"` - Topics []TopicType `json:"topics"` - AcceptP2P bool `json:"p2p"` + Symmetric bool + Key string + SignedWith string + MinPoW float64 + Topics []TopicType + AllowP2P bool } // UnmarshalJSON implements the json.Unmarshaler interface, invoked to convert a @@ -468,22 +429,29 @@ type WhisperFilterArgs struct { func (args *WhisperFilterArgs) UnmarshalJSON(b []byte) (err error) { // Unmarshal the JSON message and sanity check var obj struct { - To string `json:"to"` - From string `json:"from"` - KeyName string `json:"keyname"` - PoW float64 `json:"pow"` - Topics []interface{} `json:"topics"` - AcceptP2P bool `json:"p2p"` + Type string `json:"type"` + Key string `json:"key"` + SignedWith string `json:"signedWith"` + MinPoW float64 `json:"minPoW"` + Topics []interface{} `json:"topics"` + AllowP2P bool `json:"allowP2P"` } if err := json.Unmarshal(b, &obj); err != nil { return err } - args.To = obj.To - args.From = obj.From - args.KeyName = obj.KeyName - args.PoW = obj.PoW - args.AcceptP2P = obj.AcceptP2P + if obj.Type == "sym" { + args.Symmetric = true + } else if obj.Type == "asym" { + args.Symmetric = false + } else { + return fmt.Errorf("Wrong type (sym/asym") + } + + args.Key = obj.Key + args.SignedWith = obj.SignedWith + args.MinPoW = obj.MinPoW + args.AllowP2P = obj.AllowP2P // Construct the topic array if obj.Topics != nil { @@ -514,34 +482,34 @@ func (args *WhisperFilterArgs) UnmarshalJSON(b []byte) (err error) { // WhisperMessage is the RPC representation of a whisper message. type WhisperMessage struct { - Topic string `json:"topic"` - Payload string `json:"payload"` - Padding string `json:"padding"` - From string `json:"from"` - To string `json:"to"` - Sent uint32 `json:"sent"` - TTL uint32 `json:"ttl"` - PoW float64 `json:"pow"` - Hash string `json:"hash"` + Topic string `json:"topic"` + Payload string `json:"payload"` + Padding string `json:"padding"` + Src string `json:"signedWith"` + Dst string `json:"receipientPublicKey"` + Timestamp uint32 `json:"timestamp"` + TTL uint32 `json:"ttl"` + PoW float64 `json:"pow"` + Hash string `json:"hash"` } // NewWhisperMessage converts an internal message into an API version. func NewWhisperMessage(message *ReceivedMessage) *WhisperMessage { msg := WhisperMessage{ - Topic: common.ToHex(message.Topic[:]), - Payload: common.ToHex(message.Payload), - Padding: common.ToHex(message.Padding), - Sent: message.Sent, - TTL: message.TTL, - PoW: message.PoW, - Hash: common.ToHex(message.EnvelopeHash.Bytes()), + Topic: common.ToHex(message.Topic[:]), + Payload: common.ToHex(message.Payload), + Padding: common.ToHex(message.Padding), + Timestamp: message.Sent, + TTL: message.TTL, + PoW: message.PoW, + Hash: common.ToHex(message.EnvelopeHash.Bytes()), } if message.Dst != nil { - msg.To = common.ToHex(crypto.FromECDSAPub(message.Dst)) + msg.Dst = common.ToHex(crypto.FromECDSAPub(message.Dst)) } if isMessageSigned(message.Raw[0]) { - msg.From = common.ToHex(crypto.FromECDSAPub(message.SigToPubKey())) + msg.Src = common.ToHex(crypto.FromECDSAPub(message.SigToPubKey())) } return &msg } diff --git a/whisper/whisperv5/api_test.go b/whisper/whisperv5/api_test.go index a94909ecca..558f125446 100644 --- a/whisper/whisperv5/api_test.go +++ b/whisper/whisperv5/api_test.go @@ -23,6 +23,7 @@ import ( "time" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" ) func TestBasic(t *testing.T) { @@ -47,7 +48,7 @@ func TestBasic(t *testing.T) { t.Fatalf("failed GetFilterChanges: premature result") } - exist, err := api.HasIdentity(id) + exist, err := api.HasKeyPair(id) if err != nil { t.Fatalf("failed initial HasIdentity: %s.", err) } @@ -55,7 +56,7 @@ func TestBasic(t *testing.T) { t.Fatalf("failed initial HasIdentity: false positive.") } - success, err := api.DeleteIdentity(id) + success, err := api.DeleteKeyPair(id) if err != nil { t.Fatalf("failed DeleteIdentity: %s.", err) } @@ -63,7 +64,7 @@ func TestBasic(t *testing.T) { t.Fatalf("deleted non-existing identity: false positive.") } - pub, err := api.NewIdentity() + pub, err := api.NewKeyPair() if err != nil { t.Fatalf("failed NewIdentity: %s.", err) } @@ -71,7 +72,7 @@ func TestBasic(t *testing.T) { t.Fatalf("failed NewIdentity: empty") } - exist, err = api.HasIdentity(pub) + exist, err = api.HasKeyPair(pub) if err != nil { t.Fatalf("failed HasIdentity: %s.", err) } @@ -79,7 +80,7 @@ func TestBasic(t *testing.T) { t.Fatalf("failed HasIdentity: false negative.") } - success, err = api.DeleteIdentity(pub) + success, err = api.DeleteKeyPair(pub) if err != nil { t.Fatalf("failed to delete second identity: %s.", err) } @@ -87,7 +88,7 @@ func TestBasic(t *testing.T) { t.Fatalf("failed to delete second identity.") } - exist, err = api.HasIdentity(pub) + exist, err = api.HasKeyPair(pub) if err != nil { t.Fatalf("failed HasIdentity(): %s.", err) } @@ -98,7 +99,7 @@ func TestBasic(t *testing.T) { id = "arbitrary text" id2 := "another arbitrary string" - exist, err = api.HasSymKey(id) + exist, err = api.HasSymmetricKey(id) if err != nil { t.Fatalf("failed HasSymKey: %s.", err) } @@ -106,12 +107,12 @@ func TestBasic(t *testing.T) { t.Fatalf("failed HasSymKey: false positive.") } - id, err = api.GenerateSymKey() + id, err = api.GenerateSymmetricKey() if err != nil { t.Fatalf("failed GenerateSymKey: %s.", err) } - exist, err = api.HasSymKey(id) + exist, err = api.HasSymmetricKey(id) if err != nil { t.Fatalf("failed HasSymKey(): %s.", err) } @@ -120,17 +121,17 @@ func TestBasic(t *testing.T) { } const password = "some stuff here" - id, err = api.AddSymKeyFromPassword(password) + id, err = api.AddSymmetricKeyFromPassword(password) if err != nil { t.Fatalf("failed AddSymKey: %s.", err) } - id2, err = api.AddSymKeyFromPassword(password) + id2, err = api.AddSymmetricKeyFromPassword(password) if err != nil { t.Fatalf("failed AddSymKey: %s.", err) } - exist, err = api.HasSymKey(id2) + exist, err = api.HasSymmetricKey(id2) if err != nil { t.Fatalf("failed HasSymKey(id2): %s.", err) } @@ -138,11 +139,11 @@ func TestBasic(t *testing.T) { t.Fatalf("failed HasSymKey(id2): false negative.") } - k1, err := api.GetSymKey(id) + k1, err := api.GetSymmetricKey(id) if err != nil { t.Fatalf("failed GetSymKey(id): %s.", err) } - k2, err := api.GetSymKey(id2) + k2, err := api.GetSymmetricKey(id2) if err != nil { t.Fatalf("failed GetSymKey(id2): %s.", err) } @@ -151,7 +152,7 @@ func TestBasic(t *testing.T) { t.Fatalf("installed keys are not equal") } - exist, err = api.DeleteSymKey(id) + exist, err = api.DeleteSymmetricKey(id) if err != nil { t.Fatalf("failed DeleteSymKey(id): %s.", err) } @@ -159,7 +160,7 @@ func TestBasic(t *testing.T) { t.Fatalf("failed DeleteSymKey(id): false negative.") } - exist, err = api.HasSymKey(id) + exist, err = api.HasSymmetricKey(id) if err != nil { t.Fatalf("failed HasSymKey(id): %s.", err) } @@ -170,12 +171,12 @@ func TestBasic(t *testing.T) { func TestUnmarshalFilterArgs(t *testing.T) { s := []byte(`{ - "to":"0x70c87d191324e6712a591f304b4eedef6ad9bb9d", - "from":"0x9b2055d370f73ec7d8a03e965129118dc8f5bf83", - "keyname":"testname", - "pow":2.34, + "type":"asym", + "key":"0x70c87d191324e6712a591f304b4eedef6ad9bb9d", + "signedWith":"0x9b2055d370f73ec7d8a03e965129118dc8f5bf83", + "minPoW":2.34, "topics":["0x00000000", "0x007f80ff", "0xff807f00", "0xf26e7779"], - "p2p":true + "allowP2P":true }`) var f WhisperFilterArgs @@ -184,20 +185,20 @@ func TestUnmarshalFilterArgs(t *testing.T) { t.Fatalf("failed UnmarshalJSON: %s.", err) } - if f.To != "0x70c87d191324e6712a591f304b4eedef6ad9bb9d" { - t.Fatalf("wrong To: %x.", f.To) + if f.Symmetric { + t.Fatalf("wrong type.") } - if f.From != "0x9b2055d370f73ec7d8a03e965129118dc8f5bf83" { - t.Fatalf("wrong From: %x.", f.To) + if f.Key != "0x70c87d191324e6712a591f304b4eedef6ad9bb9d" { + t.Fatalf("wrong key: %s.", f.Key) } - if f.KeyName != "testname" { - t.Fatalf("wrong KeyName: %s.", f.KeyName) + if f.SignedWith != "0x9b2055d370f73ec7d8a03e965129118dc8f5bf83" { + t.Fatalf("wrong SignedWith: %s.", f.SignedWith) } - if f.PoW != 2.34 { - t.Fatalf("wrong pow: %f.", f.PoW) + if f.MinPoW != 2.34 { + t.Fatalf("wrong MinPoW: %f.", f.MinPoW) } - if !f.AcceptP2P { - t.Fatalf("wrong AcceptP2P: %v.", f.AcceptP2P) + if !f.AllowP2P { + t.Fatalf("wrong AllowP2P.") } if len(f.Topics) != 4 { t.Fatalf("wrong topics number: %d.", len(f.Topics)) @@ -226,17 +227,16 @@ func TestUnmarshalFilterArgs(t *testing.T) { func TestUnmarshalPostArgs(t *testing.T) { s := []byte(`{ + "type":"sym", "ttl":12345, - "from":"0x70c87d191324e6712a591f304b4eedef6ad9bb9d", - "to":"0x9b2055d370f73ec7d8a03e965129118dc8f5bf83", - "keyname":"shh_test", + "signWith":"0x70c87d191324e6712a591f304b4eedef6ad9bb9d", + "key":"0x9b2055d370f73ec7d8a03e965129118dc8f5bf83", "topic":"0xf26e7779", "padding":"0x74686973206973206D79207465737420737472696E67", "payload":"0x7061796C6F61642073686F756C642062652070736575646F72616E646F6D", - "worktime":777, - "pow":3.1416, - "filterid":"test-filter-id", - "peerid":"0xf26e7779" + "powTime":777, + "powTarget":3.1416, + "targetPeer":"enode://915533f667b1369793ebb9bda022416b1295235a1420799cd87a969467372546d808ebf59c5c9ce23f103d59b61b97df8af91f0908552485975397181b993461@127.0.0.1:12345" }`) var a PostArgs @@ -245,19 +245,20 @@ func TestUnmarshalPostArgs(t *testing.T) { t.Fatalf("failed UnmarshalJSON: %s.", err) } + if a.Type != "sym" { + t.Fatalf("wrong Type: %s.", a.Type) + } if a.TTL != 12345 { t.Fatalf("wrong ttl: %d.", a.TTL) } - if a.From != "0x70c87d191324e6712a591f304b4eedef6ad9bb9d" { - t.Fatalf("wrong From: %x.", a.To) + if a.SignWith != "0x70c87d191324e6712a591f304b4eedef6ad9bb9d" { + t.Fatalf("wrong From: %s.", a.SignWith) } - if a.To != "0x9b2055d370f73ec7d8a03e965129118dc8f5bf83" { - t.Fatalf("wrong To: %x.", a.To) + if a.Key != "0x9b2055d370f73ec7d8a03e965129118dc8f5bf83" { + t.Fatalf("wrong Key: %s.", a.Key) } - if a.KeyName != "shh_test" { - t.Fatalf("wrong KeyName: %s.", a.KeyName) - } - if a.Topic != (TopicType{0xf2, 0x6e, 0x77, 0x79}) { + + if BytesToTopic(a.Topic) != (TopicType{0xf2, 0x6e, 0x77, 0x79}) { t.Fatalf("wrong topic: %x.", a.Topic) } if string(a.Padding) != "this is my test string" { @@ -266,17 +267,14 @@ func TestUnmarshalPostArgs(t *testing.T) { if string(a.Payload) != "payload should be pseudorandom" { t.Fatalf("wrong Payload: %s.", string(a.Payload)) } - if a.WorkTime != 777 { - t.Fatalf("wrong WorkTime: %d.", a.WorkTime) + if a.PowTime != 777 { + t.Fatalf("wrong PowTime: %d.", a.PowTime) } - if a.PoW != 3.1416 { - t.Fatalf("wrong pow: %f.", a.PoW) + if a.PowTarget != 3.1416 { + t.Fatalf("wrong PowTarget: %f.", a.PowTarget) } - if a.FilterID != "test-filter-id" { - t.Fatalf("wrong FilterID: %s.", a.FilterID) - } - if !bytes.Equal(a.PeerID[:], a.Topic[:]) { - t.Fatalf("wrong PeerID: %x.", a.PeerID) + if a.TargetPeer != "enode://915533f667b1369793ebb9bda022416b1295235a1420799cd87a969467372546d808ebf59c5c9ce23f103d59b61b97df8af91f0908552485975397181b993461@127.0.0.1:12345" { + t.Fatalf("wrong PeerID: %s.", a.TargetPeer) } } @@ -309,7 +307,7 @@ func TestIntegrationAsym(t *testing.T) { api.Start() defer api.Stop() - sig, err := api.NewIdentity() + sig, err := api.NewKeyPair() if err != nil { t.Fatalf("failed NewIdentity: %s.", err) } @@ -317,7 +315,7 @@ func TestIntegrationAsym(t *testing.T) { t.Fatalf("wrong signature") } - exist, err := api.HasIdentity(sig) + exist, err := api.HasKeyPair(sig) if err != nil { t.Fatalf("failed HasIdentity: %s.", err) } @@ -325,7 +323,7 @@ func TestIntegrationAsym(t *testing.T) { t.Fatalf("failed HasIdentity: false negative.") } - key, err := api.NewIdentity() + key, err := api.NewKeyPair() if err != nil { t.Fatalf("failed NewIdentity(): %s.", err) } @@ -337,26 +335,27 @@ func TestIntegrationAsym(t *testing.T) { topics[0] = TopicType{0x00, 0x64, 0x00, 0xff} topics[1] = TopicType{0xf2, 0x6e, 0x77, 0x79} var f WhisperFilterArgs - f.To = key - f.From = sig + f.Symmetric = false + f.Key = key + f.SignedWith = sig f.Topics = topics[:] - f.PoW = DefaultMinimumPoW / 2 - f.AcceptP2P = true + f.MinPoW = DefaultMinimumPoW / 2 + f.AllowP2P = true - id, err := api.NewFilter(f) + id, err := api.Subscribe(f) if err != nil { t.Fatalf("failed to create new filter: %s.", err) } var p PostArgs p.TTL = 2 - p.From = f.From - p.To = f.To + p.SignWith = f.SignedWith + p.Key = f.Key p.Padding = []byte("test string") p.Payload = []byte("extended test string") - p.PoW = DefaultMinimumPoW - p.Topic = TopicType{0xf2, 0x6e, 0x77, 0x79} - p.WorkTime = 2 + p.PowTarget = DefaultMinimumPoW + p.PowTime = 2 + p.Topic = hexutil.Bytes{0xf2, 0x6e, 0x77, 0x79} // topics[1] err = api.Post(p) if err != nil { @@ -401,12 +400,12 @@ func TestIntegrationSym(t *testing.T) { api.Start() defer api.Stop() - keyID, err := api.GenerateSymKey() + symKeyID, err := api.GenerateSymmetricKey() if err != nil { t.Fatalf("failed GenerateSymKey: %s.", err) } - sig, err := api.NewIdentity() + sig, err := api.NewKeyPair() if err != nil { t.Fatalf("failed NewIdentity: %s.", err) } @@ -414,7 +413,7 @@ func TestIntegrationSym(t *testing.T) { t.Fatalf("wrong signature") } - exist, err := api.HasIdentity(sig) + exist, err := api.HasKeyPair(sig) if err != nil { t.Fatalf("failed HasIdentity: %s.", err) } @@ -426,26 +425,28 @@ func TestIntegrationSym(t *testing.T) { topics[0] = TopicType{0x00, 0x7f, 0x80, 0xff} topics[1] = TopicType{0xf2, 0x6e, 0x77, 0x79} var f WhisperFilterArgs - f.KeyName = keyID + f.Symmetric = true + f.Key = symKeyID f.Topics = topics[:] - f.PoW = 0.324 - f.From = sig - f.AcceptP2P = false + f.MinPoW = 0.324 + f.SignedWith = sig + f.AllowP2P = false - id, err := api.NewFilter(f) + id, err := api.Subscribe(f) if err != nil { t.Fatalf("failed to create new filter: %s.", err) } var p PostArgs + p.Type = "sym" p.TTL = 1 - p.KeyName = keyID - p.From = f.From + p.Key = symKeyID + p.SignWith = f.SignedWith p.Padding = []byte("test string") p.Payload = []byte("extended test string") - p.PoW = DefaultMinimumPoW - p.Topic = TopicType{0xf2, 0x6e, 0x77, 0x79} - p.WorkTime = 2 + p.PowTarget = DefaultMinimumPoW + p.PowTime = 2 + p.Topic = hexutil.Bytes{0xf2, 0x6e, 0x77, 0x79} err = api.Post(p) if err != nil { @@ -490,20 +491,20 @@ func TestIntegrationSymWithFilter(t *testing.T) { api.Start() defer api.Stop() - keyID, err := api.GenerateSymKey() + symKeyID, err := api.GenerateSymmetricKey() if err != nil { t.Fatalf("failed to GenerateSymKey: %s.", err) } - sig, err := api.NewIdentity() + sigKeyID, err := api.NewKeyPair() if err != nil { t.Fatalf("failed NewIdentity: %s.", err) } - if len(sig) == 0 { + if len(sigKeyID) == 0 { t.Fatalf("wrong signature.") } - exist, err := api.HasIdentity(sig) + exist, err := api.HasKeyPair(sigKeyID) if err != nil { t.Fatalf("failed HasIdentity: %s.", err) } @@ -511,30 +512,36 @@ func TestIntegrationSymWithFilter(t *testing.T) { t.Fatalf("failed HasIdentity: does not exist.") } + sigPubKey, err := api.GetPublicKey(sigKeyID) + if err != nil { + t.Fatalf("failed GetPublicKey: %s.", err) + } + var topics [2]TopicType topics[0] = TopicType{0x00, 0x7f, 0x80, 0xff} topics[1] = TopicType{0xf2, 0x6e, 0x77, 0x79} var f WhisperFilterArgs - f.KeyName = keyID + f.Symmetric = true + f.Key = symKeyID f.Topics = topics[:] - f.PoW = 0.324 - f.From = sig - f.AcceptP2P = false + f.MinPoW = 0.324 + f.SignedWith = sigPubKey + f.AllowP2P = false - id, err := api.NewFilter(f) + id, err := api.Subscribe(f) if err != nil { t.Fatalf("failed to create new filter: %s.", err) } var p PostArgs + p.Type = "sym" p.TTL = 1 - p.FilterID = id - p.From = sig + p.SignWith = sigKeyID p.Padding = []byte("test string") p.Payload = []byte("extended test string") - p.PoW = DefaultMinimumPoW - p.Topic = TopicType{0xf2, 0x6e, 0x77, 0x79} - p.WorkTime = 2 + p.PowTarget = DefaultMinimumPoW + p.PowTime = 2 + p.Topic = hexutil.Bytes{0xf2, 0x6e, 0x77, 0x79} err = api.Post(p) if err != nil { diff --git a/whisper/whisperv5/filter.go b/whisper/whisperv5/filter.go index cfb8f0f4b0..f18b4ee292 100644 --- a/whisper/whisperv5/filter.go +++ b/whisper/whisperv5/filter.go @@ -31,11 +31,11 @@ type Filter struct { KeySym []byte // Key associated with the Topic Topics []TopicType // Topics to filter messages with PoW float64 // Proof of work as described in the Whisper spec - AcceptP2P bool // Indicates whether this filter is interested in direct peer-to-peer messages + AllowP2P bool // Indicates whether this filter is interested in direct peer-to-peer messages SymKeyHash common.Hash // The Keccak256Hash of the symmetric key, needed for optimization - Messages map[common.Hash]*ReceivedMessage - mutex sync.RWMutex + Messages map[common.Hash]*ReceivedMessage + mutex sync.RWMutex } type Filters struct { @@ -72,10 +72,14 @@ func (fs *Filters) Install(watcher *Filter) (string, error) { return id, err } -func (fs *Filters) Uninstall(id string) { +func (fs *Filters) Uninstall(id string) bool { fs.mutex.Lock() defer fs.mutex.Unlock() - delete(fs.watchers, id) + if fs.watchers[id] != nil { + delete(fs.watchers, id) + return true + } + return false } func (fs *Filters) Get(id string) *Filter { @@ -93,7 +97,7 @@ func (fs *Filters) NotifyWatchers(env *Envelope, p2pMessage bool) { for _, watcher := range fs.watchers { j++ - if p2pMessage && !watcher.AcceptP2P { + if p2pMessage && !watcher.AllowP2P { log.Trace(fmt.Sprintf("msg [%x], filter [%d]: p2p messages are not allowed", env.Hash(), j)) continue } diff --git a/whisper/whisperv5/filter_test.go b/whisper/whisperv5/filter_test.go index b4f52a8185..bdd2e6d6c6 100644 --- a/whisper/whisperv5/filter_test.go +++ b/whisper/whisperv5/filter_test.go @@ -491,7 +491,7 @@ func cloneFilter(orig *Filter) *Filter { clone.KeySym = orig.KeySym clone.Topics = orig.Topics clone.PoW = orig.PoW - clone.AcceptP2P = orig.AcceptP2P + clone.AllowP2P = orig.AllowP2P clone.SymKeyHash = orig.SymKeyHash return &clone } @@ -655,7 +655,7 @@ func TestWatchers(t *testing.T) { if f == nil { t.Fatalf("failed to get the filter with seed %d.", seed) } - f.AcceptP2P = true + f.AllowP2P = true total = 0 filters.NotifyWatchers(envelopes[0], true) diff --git a/whisper/whisperv5/message.go b/whisper/whisperv5/message.go index c5103578c8..afbce7d890 100644 --- a/whisper/whisperv5/message.go +++ b/whisper/whisperv5/message.go @@ -264,7 +264,7 @@ func (msg *ReceivedMessage) decryptSymmetric(key []byte, salt []byte, nonce []by } if len(nonce) != aesgcm.NonceSize() { info := fmt.Sprintf("Wrong AES nonce size - want: %d, got: %d", len(nonce), aesgcm.NonceSize()) - log.Error(fmt.Sprintf(info)) + log.Error(info) return errors.New(info) } decrypted, err := aesgcm.Open(nil, nonce, msg.Raw, nil) diff --git a/whisper/whisperv5/peer_test.go b/whisper/whisperv5/peer_test.go index 110c3af531..9df2a060e8 100644 --- a/whisper/whisperv5/peer_test.go +++ b/whisper/whisperv5/peer_test.go @@ -166,7 +166,7 @@ func stopServers() { for i := 0; i < NumNodes; i++ { n := nodes[i] if n != nil { - n.shh.Unwatch(n.filerId) + n.shh.Unsubscribe(n.filerId) n.shh.Stop() n.server.Stop() } diff --git a/whisper/whisperv5/whisper.go b/whisper/whisperv5/whisper.go index cad7f2e425..42cca2ee12 100644 --- a/whisper/whisperv5/whisper.go +++ b/whisper/whisperv5/whisper.go @@ -36,9 +36,11 @@ import ( ) type Statistics struct { - messagesCleared int - memoryCleared int - totalMemoryUsed int + messagesCleared int + memoryCleared int + memoryUsed int + cycles int + totalMessagesCleared int } // Whisper represents a dark communication interface through the Ethereum @@ -189,7 +191,7 @@ func (w *Whisper) SendP2PDirect(peer *Peer, envelope *Envelope) error { // NewIdentity generates a new cryptographic identity for the client, and injects // it into the known identities for message decryption. Returns ID of the new key pair. -func (w *Whisper) NewIdentity() (string, error) { +func (w *Whisper) NewKeyPair() (string, error) { key, err := crypto.GenerateKey() if err != nil || !validatePrivateKey(key) { key, err = crypto.GenerateKey() // retry once @@ -217,7 +219,7 @@ func (w *Whisper) NewIdentity() (string, error) { } // DeleteIdentity deletes the specified key if it exists. -func (w *Whisper) DeleteIdentity(key string) bool { +func (w *Whisper) DeleteKeyPair(key string) bool { w.keyMu.Lock() defer w.keyMu.Unlock() @@ -230,14 +232,14 @@ func (w *Whisper) DeleteIdentity(key string) bool { // HasIdentity checks if the the whisper node is configured with the private key // of the specified public pair. -func (w *Whisper) HasIdentity(id string) bool { +func (w *Whisper) HasKeyPair(id string) bool { w.keyMu.RLock() defer w.keyMu.RUnlock() return w.privateKeys[id] != nil } // GetIdentity retrieves the private key of the specified public identity. -func (w *Whisper) GetIdentity(pubKey string) (*ecdsa.PrivateKey, error) { +func (w *Whisper) GetPrivateKey(pubKey string) (*ecdsa.PrivateKey, error) { w.keyMu.RLock() defer w.keyMu.RUnlock() key := w.privateKeys[pubKey] @@ -361,9 +363,13 @@ func (w *Whisper) GetFilter(id string) *Filter { return w.filters.Get(id) } -// Unwatch removes an installed message handler. -func (w *Whisper) Unwatch(id string) { - w.filters.Uninstall(id) +// Unsubscribe removes an installed message handler. +func (w *Whisper) Unsubscribe(id string) error { + ok := w.filters.Uninstall(id) + if !ok { + return fmt.Errorf("Invalid ID") + } + return nil } // Send injects a message into the whisper send queue, to be distributed in the @@ -557,7 +563,7 @@ func (wh *Whisper) add(envelope *Envelope) (bool, error) { log.Trace(fmt.Sprintf("whisper envelope already cached [%x]\n", envelope.Hash())) } else { log.Trace(fmt.Sprintf("cached whisper envelope [%x]: %v\n", envelope.Hash(), envelope)) - wh.stats.totalMemoryUsed += envelope.size() + wh.stats.memoryUsed += envelope.size() wh.postEvent(envelope, false) // notify the local node about the new message if wh.mailServer != nil { wh.mailServer.Archive(envelope) @@ -649,7 +655,7 @@ func (w *Whisper) expire() { hashSet.Each(func(v interface{}) bool { sz := w.envelopes[v.(common.Hash)].size() w.stats.memoryCleared += sz - w.stats.totalMemoryUsed -= sz + w.stats.memoryUsed -= sz delete(w.envelopes, v.(common.Hash)) return true }) @@ -660,8 +666,13 @@ func (w *Whisper) expire() { } func (w *Whisper) Stats() string { - return fmt.Sprintf("Latest expiry cycle cleared %d messages (%d bytes). Memory usage: %d bytes.", - w.stats.messagesCleared, w.stats.memoryCleared, w.stats.totalMemoryUsed) + result := fmt.Sprintf("Memory usage: %d bytes.\nAverage messages cleared per expiry cycle: %d.", + w.stats.memoryUsed, w.stats.totalMessagesCleared/w.stats.cycles) + if w.stats.messagesCleared > 0 { + result += fmt.Sprintf("\nLatest expiry cycle cleared %d messages (%d bytes).", + w.stats.messagesCleared, w.stats.memoryCleared) + } + return result } // envelopes retrieves all the messages currently pooled by the node. @@ -703,10 +714,20 @@ func (w *Whisper) isEnvelopeCached(hash common.Hash) bool { } func (s *Statistics) reset() { + s.cycles++ + s.totalMessagesCleared += s.messagesCleared + s.memoryCleared = 0 s.messagesCleared = 0 } +func ValidateKeyID(id string) error { + if len(id) != keyIdSize*2 { + return fmt.Errorf("Wrong size of key ID") + } + return nil +} + func ValidatePublicKey(k *ecdsa.PublicKey) bool { return k != nil && k.X != nil && k.Y != nil && k.X.Sign() != 0 && k.Y.Sign() != 0 } diff --git a/whisper/whisperv5/whisper_test.go b/whisper/whisperv5/whisper_test.go index c712fa6eb1..de86ff4ad7 100644 --- a/whisper/whisperv5/whisper_test.go +++ b/whisper/whisperv5/whisper_test.go @@ -100,11 +100,11 @@ func TestWhisperBasic(t *testing.T) { t.Fatalf("failed BytesToIntBigEndian: %d.", be) } - id, err := w.NewIdentity() + id, err := w.NewKeyPair() if err != nil { t.Fatalf("failed to generate new key pair: %s.", err) } - pk, err := w.GetIdentity(id) + pk, err := w.GetPrivateKey(id) if err != nil { t.Fatalf("failed to retrieve new key pair: %s.", err) } @@ -118,58 +118,60 @@ func TestWhisperBasic(t *testing.T) { func TestWhisperIdentityManagement(t *testing.T) { w := New() - id1, err := w.NewIdentity() + id1, err := w.NewKeyPair() if err != nil { t.Fatalf("failed to generate new key pair: %s.", err) } - id2, err := w.NewIdentity() + id2, err := w.NewKeyPair() if err != nil { t.Fatalf("failed to generate new key pair: %s.", err) } - pk1, err := w.GetIdentity(id1) + pk1, err := w.GetPrivateKey(id1) if err != nil { t.Fatalf("failed to retrieve the key pair: %s.", err) } - pk2, err := w.GetIdentity(id2) + pk2, err := w.GetPrivateKey(id2) if err != nil { t.Fatalf("failed to retrieve the key pair: %s.", err) } - // todo: delete - //pub1 := common.ToHex(crypto.FromECDSAPub(&id1.PublicKey)) - //pub2 := common.ToHex(crypto.FromECDSAPub(&id2.PublicKey)) - //pub1 := pk1.PublicKey - //pub2 := pk2.PublicKey - if !w.HasIdentity(id1) { - t.Fatalf("failed HasIdentity(pub1).") + if !w.HasKeyPair(id1) { + t.Fatalf("failed HasIdentity(pk1).") } - if !w.HasIdentity(id2) { - t.Fatalf("failed HasIdentity(pub2).") + if !w.HasKeyPair(id2) { + t.Fatalf("failed HasIdentity(pk2).") } if pk1 == nil { - t.Fatalf("failed GetIdentity(pub1).") + t.Fatalf("failed GetIdentity(pk1).") } if pk2 == nil { - t.Fatalf("failed GetIdentity(pub2).") + t.Fatalf("failed GetIdentity(pk2).") + } + + if !validatePrivateKey(pk1) { + t.Fatalf("pk1 is invalid.") + } + if !validatePrivateKey(pk2) { + t.Fatalf("pk2 is invalid.") } // Delete one identity - done := w.DeleteIdentity(id1) + done := w.DeleteKeyPair(id1) if !done { t.Fatalf("failed to delete id1.") } - pk1, err = w.GetIdentity(id1) + pk1, err = w.GetPrivateKey(id1) if err == nil { t.Fatalf("retrieve the key pair: false positive.") } - pk2, err = w.GetIdentity(id2) + pk2, err = w.GetPrivateKey(id2) if err != nil { t.Fatalf("failed to retrieve the key pair: %s.", err) } - if w.HasIdentity(id1) { + if w.HasKeyPair(id1) { t.Fatalf("failed DeleteIdentity(pub1): still exist.") } - if !w.HasIdentity(id2) { + if !w.HasKeyPair(id2) { t.Fatalf("failed DeleteIdentity(pub1): pub2 does not exist.") } if pk1 != nil { @@ -180,22 +182,22 @@ func TestWhisperIdentityManagement(t *testing.T) { } // Delete again non-existing identity - done = w.DeleteIdentity(id1) + done = w.DeleteKeyPair(id1) if done { t.Fatalf("delete id1: false positive.") } - pk1, err = w.GetIdentity(id1) + pk1, err = w.GetPrivateKey(id1) if err == nil { t.Fatalf("retrieve the key pair: false positive.") } - pk2, err = w.GetIdentity(id2) + pk2, err = w.GetPrivateKey(id2) if err != nil { t.Fatalf("failed to retrieve the key pair: %s.", err) } - if w.HasIdentity(id1) { + if w.HasKeyPair(id1) { t.Fatalf("failed delete non-existing identity: exist.") } - if !w.HasIdentity(id2) { + if !w.HasKeyPair(id2) { t.Fatalf("failed delete non-existing identity: pub2 does not exist.") } if pk1 != nil { @@ -206,22 +208,22 @@ func TestWhisperIdentityManagement(t *testing.T) { } // Delete second identity - done = w.DeleteIdentity(id2) + done = w.DeleteKeyPair(id2) if !done { t.Fatalf("failed to delete id2.") } - pk1, err = w.GetIdentity(id1) + pk1, err = w.GetPrivateKey(id1) if err == nil { t.Fatalf("retrieve the key pair: false positive.") } - pk2, err = w.GetIdentity(id2) + pk2, err = w.GetPrivateKey(id2) if err == nil { t.Fatalf("retrieve the key pair: false positive.") } - if w.HasIdentity(id1) { + if w.HasKeyPair(id1) { t.Fatalf("failed delete second identity: first identity exist.") } - if w.HasIdentity(id2) { + if w.HasKeyPair(id2) { t.Fatalf("failed delete second identity: still exist.") } if pk1 != nil {