221 lines
6.8 KiB
Diff
221 lines
6.8 KiB
Diff
diff --git a/whisper/whisperv2/whisper.go b/whisper/whisperv2/whisper.go
|
|
index 61c36918d..908346999 100644
|
|
--- a/whisper/whisperv2/whisper.go
|
|
+++ b/whisper/whisperv2/whisper.go
|
|
@@ -134,6 +134,13 @@ func (self *Whisper) NewIdentity() *ecdsa.PrivateKey {
|
|
return key
|
|
}
|
|
|
|
+// AddIdentity adds identity into the known identities list (for message decryption).
|
|
+func (self *Whisper) AddIdentity(key *ecdsa.PrivateKey) {
|
|
+ self.keysMu.Lock()
|
|
+ self.keys[string(crypto.FromECDSAPub(&key.PublicKey))] = key
|
|
+ self.keysMu.Unlock()
|
|
+}
|
|
+
|
|
// HasIdentity checks if the the whisper node is configured with the private key
|
|
// of the specified public pair.
|
|
func (self *Whisper) HasIdentity(key *ecdsa.PublicKey) bool {
|
|
diff --git a/whisper/whisperv5/api.go b/whisper/whisperv5/api.go
|
|
index 96c4b0e6c..e3c2f4a97 100644
|
|
--- a/whisper/whisperv5/api.go
|
|
+++ b/whisper/whisperv5/api.go
|
|
@@ -313,6 +313,16 @@ func (api *PublicWhisperAPI) Post(ctx context.Context, req NewMessage) (bool, er
|
|
return true, api.w.Send(env)
|
|
}
|
|
|
|
+// UninstallFilter is alias for Unsubscribe
|
|
+func (api *PublicWhisperAPI) UninstallFilter(id string) {
|
|
+ api.w.Unsubscribe(id)
|
|
+}
|
|
+
|
|
+// Unsubscribe disables and removes an existing filter.
|
|
+func (api *PublicWhisperAPI) Unsubscribe(id string) {
|
|
+ api.w.Unsubscribe(id)
|
|
+}
|
|
+
|
|
//go:generate gencodec -type Criteria -field-override criteriaOverride -out gen_criteria_json.go
|
|
|
|
// Criteria holds various filter options for inbound messages.
|
|
diff --git a/whisper/whisperv5/whisper.go b/whisper/whisperv5/whisper.go
|
|
index 85849ccce..c39e8b3e0 100644
|
|
--- a/whisper/whisperv5/whisper.go
|
|
+++ b/whisper/whisperv5/whisper.go
|
|
@@ -250,9 +256,9 @@ func (w *Whisper) NewKeyPair() (string, error) {
|
|
return "", fmt.Errorf("failed to generate valid key")
|
|
}
|
|
|
|
- id, err := GenerateRandomID()
|
|
+ id, err := toDeterministicID(common.ToHex(crypto.FromECDSAPub(&key.PublicKey)), keyIdSize)
|
|
if err != nil {
|
|
- return "", fmt.Errorf("failed to generate ID: %s", err)
|
|
+ return "", err
|
|
}
|
|
|
|
w.keyMu.Lock()
|
|
@@ -265,45 +271,94 @@ func (w *Whisper) NewKeyPair() (string, error) {
|
|
return id, nil
|
|
}
|
|
|
|
-// DeleteKeyPair deletes the specified key if it exists.
|
|
-func (w *Whisper) DeleteKeyPair(key string) bool {
|
|
+// AddIdentity adds cryptographic identity into the known
|
|
+// identities list (for message decryption).
|
|
+func (w *Whisper) AddKeyPair(key *ecdsa.PrivateKey) (string, error) {
|
|
+ id, err := makeDeterministicID(common.ToHex(crypto.FromECDSAPub(&key.PublicKey)), keyIdSize)
|
|
+ if err != nil {
|
|
+ return "", err
|
|
+ }
|
|
+ if w.HasKeyPair(id) {
|
|
+ return id, nil // no need to re-inject
|
|
+ }
|
|
+
|
|
w.keyMu.Lock()
|
|
defer w.keyMu.Unlock()
|
|
|
|
- if w.privateKeys[key] != nil {
|
|
- delete(w.privateKeys, key)
|
|
- return true
|
|
- }
|
|
- return false
|
|
+ w.privateKeys[id] = key
|
|
+ log.Info("Whisper identity added", "id", id, "pubkey", common.ToHex(crypto.FromECDSAPub(&key.PublicKey)))
|
|
+
|
|
+ return id, nil
|
|
}
|
|
|
|
-// AddKeyPair imports a asymmetric private key and returns it identifier.
|
|
-func (w *Whisper) AddKeyPair(key *ecdsa.PrivateKey) (string, error) {
|
|
- id, err := GenerateRandomID()
|
|
+// SelectKeyPair adds cryptographic identity, and makes sure
|
|
+// that it is the only private key known to the node.
|
|
+func (w *Whisper) SelectKeyPair(key *ecdsa.PrivateKey) error {
|
|
+ id, err := makeDeterministicID(common.ToHex(crypto.FromECDSAPub(&key.PublicKey)), keyIdSize)
|
|
if err != nil {
|
|
- return "", fmt.Errorf("failed to generate ID: %s", err)
|
|
+ return err
|
|
}
|
|
|
|
w.keyMu.Lock()
|
|
+ defer w.keyMu.Unlock()
|
|
+
|
|
+ w.privateKeys = make(map[string]*ecdsa.PrivateKey) // reset key store
|
|
w.privateKeys[id] = key
|
|
- w.keyMu.Unlock()
|
|
|
|
- return id, nil
|
|
+ log.Info("Whisper identity selected", "id", id, "key", common.ToHex(crypto.FromECDSAPub(&key.PublicKey)))
|
|
+ return nil
|
|
+}
|
|
+
|
|
+// DeleteKeyPairs removes all cryptographic identities known to the node
|
|
+func (w *Whisper) DeleteKeyPairs() error {
|
|
+ w.keyMu.Lock()
|
|
+ defer w.keyMu.Unlock()
|
|
+
|
|
+ w.privateKeys = make(map[string]*ecdsa.PrivateKey)
|
|
+
|
|
+ return nil
|
|
+}
|
|
+
|
|
+// DeleteKeyPair deletes the specified key if it exists.
|
|
+func (w *Whisper) DeleteKeyPair(id string) bool {
|
|
+ deterministicID, err := toDeterministicID(id, keyIdSize)
|
|
+ if err != nil {
|
|
+ return false
|
|
+ }
|
|
+
|
|
+ w.keyMu.Lock()
|
|
+ defer w.keyMu.Unlock()
|
|
+
|
|
+ if w.privateKeys[deterministicID] != nil {
|
|
+ delete(w.privateKeys, deterministicID)
|
|
+ return true
|
|
+ }
|
|
+ return false
|
|
}
|
|
|
|
// HasKeyPair checks if the the whisper node is configured with the private key
|
|
// of the specified public pair.
|
|
func (w *Whisper) HasKeyPair(id string) bool {
|
|
+ deterministicID, err := toDeterministicID(id, keyIdSize)
|
|
+ if err != nil {
|
|
+ return false
|
|
+ }
|
|
+
|
|
w.keyMu.RLock()
|
|
defer w.keyMu.RUnlock()
|
|
- return w.privateKeys[id] != nil
|
|
+ return w.privateKeys[deterministicID] != nil
|
|
}
|
|
|
|
// GetPrivateKey retrieves the private key of the specified identity.
|
|
func (w *Whisper) GetPrivateKey(id string) (*ecdsa.PrivateKey, error) {
|
|
+ deterministicID, err := toDeterministicID(id, keyIdSize)
|
|
+ if err != nil {
|
|
+ return nil, err
|
|
+ }
|
|
+
|
|
w.keyMu.RLock()
|
|
defer w.keyMu.RUnlock()
|
|
- key := w.privateKeys[id]
|
|
+ key := w.privateKeys[deterministicID]
|
|
if key == nil {
|
|
return nil, fmt.Errorf("invalid id")
|
|
}
|
|
@@ -336,6 +391,23 @@ func (w *Whisper) GenerateSymKey() (string, error) {
|
|
return id, nil
|
|
}
|
|
|
|
+// AddSymKey stores the key with a given id.
|
|
+func (w *Whisper) AddSymKey(id string, key []byte) (string, error) {
|
|
+ deterministicID, err := toDeterministicID(id, keyIdSize)
|
|
+ if err != nil {
|
|
+ return "", err
|
|
+ }
|
|
+
|
|
+ w.keyMu.Lock()
|
|
+ defer w.keyMu.Unlock()
|
|
+
|
|
+ if w.symKeys[deterministicID] != nil {
|
|
+ return "", fmt.Errorf("key already exists: %v", id)
|
|
+ }
|
|
+ w.symKeys[deterministicID] = key
|
|
+ return deterministicID, nil
|
|
+}
|
|
+
|
|
// AddSymKeyDirect stores the key, and returns its id.
|
|
func (w *Whisper) AddSymKeyDirect(key []byte) (string, error) {
|
|
if len(key) != aesKeyLength {
|
|
@@ -856,3 +941,30 @@ func GenerateRandomID() (id string, err error) {
|
|
id = common.Bytes2Hex(buf)
|
|
return id, err
|
|
}
|
|
+
|
|
+// makeDeterministicID generates a deterministic ID, based on a given input
|
|
+func makeDeterministicID(input string, keyLen int) (id string, err error) {
|
|
+ buf := pbkdf2.Key([]byte(input), nil, 4096, keyLen, sha256.New)
|
|
+ if !validateSymmetricKey(buf) {
|
|
+ return "", fmt.Errorf("error in GenerateDeterministicID: failed to generate key")
|
|
+ }
|
|
+ id = common.Bytes2Hex(buf)
|
|
+ return id, err
|
|
+}
|
|
+
|
|
+// toDeterministicID reviews incoming id, and transforms it to format
|
|
+// expected internally be private key store. Originally, public keys
|
|
+// were used as keys, now random keys are being used. And in order to
|
|
+// make it easier to consume, we now allow both random IDs and public
|
|
+// keys to be passed.
|
|
+func toDeterministicID(id string, expectedLen int) (string, error) {
|
|
+ if len(id) != (expectedLen * 2) { // we received hex key, so number of chars in id is doubled
|
|
+ var err error
|
|
+ id, err = makeDeterministicID(id, expectedLen)
|
|
+ if err != nil {
|
|
+ return "", err
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return id, nil
|
|
+}
|