]> nmode's Git Repositories - signal-cli/blobdiff - src/main/java/org/asamk/signal/JsonIdentityKeyStore.java
Add command to update account attributes
[signal-cli] / src / main / java / org / asamk / signal / JsonIdentityKeyStore.java
index 332d871212a395f51b51db3d4d54ec48dc5a81c6..d71e3581d6dc18e1f4f6dbd9d77a2d6701aed423 100644 (file)
@@ -7,13 +7,11 @@ import com.fasterxml.jackson.databind.*;
 import org.whispersystems.libsignal.IdentityKey;
 import org.whispersystems.libsignal.IdentityKeyPair;
 import org.whispersystems.libsignal.InvalidKeyException;
+import org.whispersystems.libsignal.SignalProtocolAddress;
 import org.whispersystems.libsignal.state.IdentityKeyStore;
 
 import java.io.IOException;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
 
 class JsonIdentityKeyStore implements IdentityKeyStore {
 
@@ -39,11 +37,19 @@ class JsonIdentityKeyStore implements IdentityKeyStore {
     }
 
     @Override
-    public void saveIdentity(String name, IdentityKey identityKey) {
-        saveIdentity(name, identityKey, TrustLevel.TRUSTED_UNVERIFIED);
+    public void saveIdentity(SignalProtocolAddress address, IdentityKey identityKey) {
+        saveIdentity(address.getName(), identityKey, TrustLevel.TRUSTED_UNVERIFIED, null);
     }
 
-    public void saveIdentity(String name, IdentityKey identityKey, TrustLevel trustLevel) {
+    /**
+     * Adds or updates the given identityKey for the user name and sets the trustLevel and added timestamp.
+     *
+     * @param name        User name, i.e. phone number
+     * @param identityKey The user's public key
+     * @param trustLevel
+     * @param added       Added timestamp, if null and the key is newly added, the current time is used.
+     */
+    public void saveIdentity(String name, IdentityKey identityKey, TrustLevel trustLevel, Date added) {
         List<Identity> identities = trustedKeys.get(name);
         if (identities == null) {
             identities = new ArrayList<>();
@@ -53,16 +59,21 @@ class JsonIdentityKeyStore implements IdentityKeyStore {
                 if (!id.identityKey.equals(identityKey))
                     continue;
 
-                id.trustLevel = trustLevel;
+                if (id.trustLevel.compareTo(trustLevel) < 0) {
+                    id.trustLevel = trustLevel;
+                }
+                if (added != null) {
+                    id.added = added;
+                }
                 return;
             }
         }
-        identities.add(new Identity(identityKey, trustLevel));
+        identities.add(new Identity(identityKey, trustLevel, added != null ? added : new Date()));
     }
 
     @Override
-    public boolean isTrustedIdentity(String name, IdentityKey identityKey) {
-        List<Identity> identities = trustedKeys.get(name);
+    public boolean isTrustedIdentity(SignalProtocolAddress address, IdentityKey identityKey) {
+        List<Identity> identities = trustedKeys.get(address.getName());
         if (identities == null) {
             // Trust on first use
             return true;
@@ -77,6 +88,16 @@ class JsonIdentityKeyStore implements IdentityKeyStore {
         return false;
     }
 
+    public Map<String, List<Identity>> getIdentities() {
+        // TODO deep copy
+        return trustedKeys;
+    }
+
+    public List<Identity> getIdentities(String name) {
+        // TODO deep copy
+        return trustedKeys.get(name);
+    }
+
     public static class JsonIdentityKeyStoreDeserializer extends JsonDeserializer<JsonIdentityKeyStore> {
 
         @Override
@@ -97,7 +118,8 @@ class JsonIdentityKeyStore implements IdentityKeyStore {
                         try {
                             IdentityKey id = new IdentityKey(Base64.decode(trustedKey.get("identityKey").asText()), 0);
                             TrustLevel trustLevel = trustedKey.has("trustLevel") ? TrustLevel.fromInt(trustedKey.get("trustLevel").asInt()) : TrustLevel.TRUSTED_UNVERIFIED;
-                            keyStore.saveIdentity(trustedKeyName, id, trustLevel);
+                            Date added = trustedKey.has("addedTimestamp") ? new Date(trustedKey.get("addedTimestamp").asLong()) : new Date();
+                            keyStore.saveIdentity(trustedKeyName, id, trustLevel, added);
                         } catch (InvalidKeyException | IOException e) {
                             System.out.println(String.format("Error while decoding key for: %s", trustedKeyName));
                         }
@@ -125,6 +147,7 @@ class JsonIdentityKeyStore implements IdentityKeyStore {
                     json.writeStringField("name", trustedKey.getKey());
                     json.writeStringField("identityKey", Base64.encodeBytes(id.identityKey.serialize()));
                     json.writeNumberField("trustLevel", id.trustLevel.ordinal());
+                    json.writeNumberField("addedTimestamp", id.added.getTime());
                     json.writeEndObject();
                 }
             }
@@ -133,33 +156,30 @@ class JsonIdentityKeyStore implements IdentityKeyStore {
         }
     }
 
-    private enum TrustLevel {
-        UNTRUSTED,
-        TRUSTED_UNVERIFIED,
-        TRUSTED_VERIFIED;
-
-        private static TrustLevel[] cachedValues = null;
-
-        public static TrustLevel fromInt(int i) {
-            if (TrustLevel.cachedValues == null) {
-                TrustLevel.cachedValues = TrustLevel.values();
-            }
-            return TrustLevel.cachedValues[i];
-        }
-    }
-
-    private class Identity {
+    public class Identity {
         IdentityKey identityKey;
         TrustLevel trustLevel;
+        Date added;
 
         public Identity(IdentityKey identityKey, TrustLevel trustLevel) {
             this.identityKey = identityKey;
             this.trustLevel = trustLevel;
+            this.added = new Date();
+        }
+
+        public Identity(IdentityKey identityKey, TrustLevel trustLevel, Date added) {
+            this.identityKey = identityKey;
+            this.trustLevel = trustLevel;
+            this.added = added;
         }
 
         public boolean isTrusted() {
             return trustLevel == TrustLevel.TRUSTED_UNVERIFIED ||
                     trustLevel == TrustLevel.TRUSTED_VERIFIED;
         }
+
+        public byte[] getFingerprint() {
+            return identityKey.getPublicKey().serialize();
+        }
     }
 }