mirror of
https://github.com/status-im/status-go.git
synced 2025-01-10 22:56:40 +00:00
f4cd8d27b5
This function returns only the new messages from the filter, never returns the same message for the same user twice.
209 lines
6.5 KiB
Diff
209 lines
6.5 KiB
Diff
diff --git i/whisper/whisperv6/api.go w/whisper/whisperv6/api.go
|
|
index c60bc46a1..2de99f293 100644
|
|
--- i/whisper/whisperv6/api.go
|
|
+++ w/whisper/whisperv6/api.go
|
|
@@ -317,6 +317,16 @@ func (api *PublicWhisperAPI) Post(ctx context.Context, req NewMessage) (hexutil.
|
|
return result, err
|
|
}
|
|
|
|
+// 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 i/whisper/whisperv6/whisper.go w/whisper/whisperv6/whisper.go
|
|
index 880cced09..702556079 100644
|
|
--- i/whisper/whisperv6/whisper.go
|
|
+++ w/whisper/whisperv6/whisper.go
|
|
@@ -382,9 +382,9 @@ func (whisper *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
|
|
}
|
|
|
|
whisper.keyMu.Lock()
|
|
@@ -399,11 +399,16 @@ func (whisper *Whisper) NewKeyPair() (string, error) {
|
|
|
|
// DeleteKeyPair deletes the specified key if it exists.
|
|
func (whisper *Whisper) DeleteKeyPair(key string) bool {
|
|
+ deterministicID, err := toDeterministicID(key, keyIDSize)
|
|
+ if err != nil {
|
|
+ return false
|
|
+ }
|
|
+
|
|
whisper.keyMu.Lock()
|
|
defer whisper.keyMu.Unlock()
|
|
|
|
- if whisper.privateKeys[key] != nil {
|
|
- delete(whisper.privateKeys, key)
|
|
+ if whisper.privateKeys[deterministicID] != nil {
|
|
+ delete(whisper.privateKeys, deterministicID)
|
|
return true
|
|
}
|
|
return false
|
|
@@ -411,31 +416,73 @@ func (whisper *Whisper) DeleteKeyPair(key string) bool {
|
|
|
|
// AddKeyPair imports a asymmetric private key and returns it identifier.
|
|
func (whisper *Whisper) AddKeyPair(key *ecdsa.PrivateKey) (string, error) {
|
|
- id, err := GenerateRandomID()
|
|
+ id, err := makeDeterministicID(common.ToHex(crypto.FromECDSAPub(&key.PublicKey)), keyIDSize)
|
|
if err != nil {
|
|
- return "", fmt.Errorf("failed to generate ID: %s", err)
|
|
+ return "", err
|
|
+ }
|
|
+ if whisper.HasKeyPair(id) {
|
|
+ return id, nil // no need to re-inject
|
|
}
|
|
|
|
whisper.keyMu.Lock()
|
|
whisper.privateKeys[id] = key
|
|
whisper.keyMu.Unlock()
|
|
+ log.Info("Whisper identity added", "id", id, "pubkey", common.ToHex(crypto.FromECDSAPub(&key.PublicKey)))
|
|
|
|
return id, nil
|
|
}
|
|
|
|
+// SelectKeyPair adds cryptographic identity, and makes sure
|
|
+// that it is the only private key known to the node.
|
|
+func (whisper *Whisper) SelectKeyPair(key *ecdsa.PrivateKey) error {
|
|
+ id, err := makeDeterministicID(common.ToHex(crypto.FromECDSAPub(&key.PublicKey)), keyIDSize)
|
|
+ if err != nil {
|
|
+ return err
|
|
+ }
|
|
+
|
|
+ whisper.keyMu.Lock()
|
|
+ defer whisper.keyMu.Unlock()
|
|
+
|
|
+ whisper.privateKeys = make(map[string]*ecdsa.PrivateKey) // reset key store
|
|
+ whisper.privateKeys[id] = key
|
|
+
|
|
+ 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 (whisper *Whisper) DeleteKeyPairs() error {
|
|
+ whisper.keyMu.Lock()
|
|
+ defer whisper.keyMu.Unlock()
|
|
+
|
|
+ whisper.privateKeys = make(map[string]*ecdsa.PrivateKey)
|
|
+
|
|
+ return nil
|
|
+}
|
|
+
|
|
// HasKeyPair checks if the the whisper node is configured with the private key
|
|
// of the specified public pair.
|
|
func (whisper *Whisper) HasKeyPair(id string) bool {
|
|
+ deterministicID, err := toDeterministicID(id, keyIDSize)
|
|
+ if err != nil {
|
|
+ return false
|
|
+ }
|
|
+
|
|
whisper.keyMu.RLock()
|
|
defer whisper.keyMu.RUnlock()
|
|
- return whisper.privateKeys[id] != nil
|
|
+ return whisper.privateKeys[deterministicID] != nil
|
|
}
|
|
|
|
// GetPrivateKey retrieves the private key of the specified identity.
|
|
func (whisper *Whisper) GetPrivateKey(id string) (*ecdsa.PrivateKey, error) {
|
|
+ deterministicID, err := toDeterministicID(id, keyIDSize)
|
|
+ if err != nil {
|
|
+ return nil, err
|
|
+ }
|
|
+
|
|
whisper.keyMu.RLock()
|
|
defer whisper.keyMu.RUnlock()
|
|
- key := whisper.privateKeys[id]
|
|
+ key := whisper.privateKeys[deterministicID]
|
|
if key == nil {
|
|
return nil, fmt.Errorf("invalid id")
|
|
}
|
|
@@ -467,6 +514,23 @@ func (whisper *Whisper) GenerateSymKey() (string, error) {
|
|
return id, nil
|
|
}
|
|
|
|
+// AddSymKey stores the key with a given id.
|
|
+func (whisper *Whisper) AddSymKey(id string, key []byte) (string, error) {
|
|
+ deterministicID, err := toDeterministicID(id, keyIDSize)
|
|
+ if err != nil {
|
|
+ return "", err
|
|
+ }
|
|
+
|
|
+ whisper.keyMu.Lock()
|
|
+ defer whisper.keyMu.Unlock()
|
|
+
|
|
+ if whisper.symKeys[deterministicID] != nil {
|
|
+ return "", fmt.Errorf("key already exists: %v", id)
|
|
+ }
|
|
+ whisper.symKeys[deterministicID] = key
|
|
+ return deterministicID, nil
|
|
+}
|
|
+
|
|
// AddSymKeyDirect stores the key, and returns its id.
|
|
func (whisper *Whisper) AddSymKeyDirect(key []byte) (string, error) {
|
|
if len(key) != aesKeyLength {
|
|
@@ -1013,6 +1077,33 @@ func GenerateRandomID() (id string, err error) {
|
|
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 !validateDataIntegrity(buf, keyIDSize) {
|
|
+ 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
|
|
+}
|
|
+
|
|
func isFullNode(bloom []byte) bool {
|
|
if bloom == nil {
|
|
return true
|
|
@@ -1048,3 +1139,15 @@ func addBloom(a, b []byte) []byte {
|
|
}
|
|
return c
|
|
}
|
|
+
|
|
+// SelectedKeyPairID returns the id of currently selected key pair.
|
|
+// It helps distinguish between different users w/o exposing the user identity itself.
|
|
+func (whisper *Whisper) SelectedKeyPairID() string {
|
|
+ whisper.keyMu.RLock()
|
|
+ defer whisper.keyMu.RUnlock()
|
|
+
|
|
+ for id := range whisper.privateKeys {
|
|
+ return id
|
|
+ }
|
|
+ return ""
|
|
+}
|