]> nmode's Git Repositories - signal-cli/commitdiff
Add support for new safety numbers, that replace the hex fingerprint
authorAsamK <asamk@gmx.de>
Thu, 27 Oct 2016 12:09:22 +0000 (14:09 +0200)
committerAsamK <asamk@gmx.de>
Thu, 27 Oct 2016 12:09:22 +0000 (14:09 +0200)
src/main/java/org/asamk/signal/Main.java
src/main/java/org/asamk/signal/Manager.java

index d70b00cbd6bea18b8a40ce6175639ad88b3b964b..fbdc0ce120410d0857f2d86d4fe4b3948c0cb21a 100644 (file)
@@ -458,13 +458,13 @@ public class Main {
                     if (ns.get("number") == null) {
                         for (Map.Entry<String, List<JsonIdentityKeyStore.Identity>> keys : m.getIdentities().entrySet()) {
                             for (JsonIdentityKeyStore.Identity id : keys.getValue()) {
-                                System.out.println(String.format("%s: %s Added: %s Fingerprint: %s", keys.getKey(), id.trustLevel, id.added, Hex.toStringCondensed(id.getFingerprint())));
+                                printIdentityFingerprint(m, keys.getKey(), id);
                             }
                         }
                     } else {
                         String number = ns.getString("number");
                         for (JsonIdentityKeyStore.Identity id : m.getIdentities(number)) {
-                            System.out.println(String.format("%s: %s Added: %s Fingerprint: %s", number, id.trustLevel, id.added, Hex.toStringCondensed(id.getFingerprint())));
+                            printIdentityFingerprint(m, number, id);
                         }
                     }
                     break;
@@ -487,16 +487,28 @@ public class Main {
                     } else {
                         String fingerprint = ns.getString("verified_fingerprint");
                         if (fingerprint != null) {
-                            byte[] fingerprintBytes;
-                            try {
-                                fingerprintBytes = Hex.toByteArray(fingerprint.replaceAll(" ", "").toLowerCase(Locale.ROOT));
-                            } catch (Exception e) {
-                                System.err.println("Failed to parse the fingerprint, make sure the fingerprint is a correctly encoded hex string without additional characters.");
-                                return 1;
-                            }
-                            boolean res = m.trustIdentityVerified(number, fingerprintBytes);
-                            if (!res) {
-                                System.err.println("Failed to set the trust for the fingerprint of this number, make sure the number and the fingerprint are correct.");
+                            fingerprint = fingerprint.replaceAll(" ", "");
+                            if (fingerprint.length() == 66) {
+                                byte[] fingerprintBytes;
+                                try {
+                                    fingerprintBytes = Hex.toByteArray(fingerprint.toLowerCase(Locale.ROOT));
+                                } catch (Exception e) {
+                                    System.err.println("Failed to parse the fingerprint, make sure the fingerprint is a correctly encoded hex string without additional characters.");
+                                    return 1;
+                                }
+                                boolean res = m.trustIdentityVerified(number, fingerprintBytes);
+                                if (!res) {
+                                    System.err.println("Failed to set the trust for the fingerprint of this number, make sure the number and the fingerprint are correct.");
+                                    return 1;
+                                }
+                            } else if (fingerprint.length() == 60) {
+                                boolean res = m.trustIdentityVerifiedSafetyNumber(number, fingerprint);
+                                if (!res) {
+                                    System.err.println("Failed to set the trust for the safety number of this phone number, make sure the phone number and the safety number are correct.");
+                                    return 1;
+                                }
+                            } else {
+                                System.err.println("Fingerprint has invalid format, either specify the old hex fingerprint or the new safety number");
                                 return 1;
                             }
                         } else {
@@ -555,6 +567,22 @@ public class Main {
         }
     }
 
+    private static void printIdentityFingerprint(Manager m, String theirUsername, JsonIdentityKeyStore.Identity theirId) {
+        String digits = formatSafetyNumber(m.computeSafetyNumber(theirUsername, theirId.identityKey));
+        System.out.println(String.format("%s: %s Added: %s Fingerprint: %s Safety Number: %s", theirUsername,
+                theirId.trustLevel, theirId.added, Hex.toStringCondensed(theirId.getFingerprint()), digits));
+    }
+
+    private static String formatSafetyNumber(String digits) {
+        final int partCount = 12;
+        int partSize = digits.length() / partCount;
+        StringBuilder f = new StringBuilder(digits.length() + partCount);
+        for (int i = 0; i < partCount; i++) {
+            f.append(digits.substring(i * partSize, (i * partSize) + partSize)).append(" ");
+        }
+        return f.toString();
+    }
+
     private static void handleGroupNotFoundException(GroupNotFoundException e) {
         System.err.println("Failed to send to group: " + e.getMessage());
         System.err.println("Aborting sending.");
index 6ed8b04517b8f556d8424ae9b575eacd1516535f..e02258f19918967c9e9f3afeec3454c8c1a8cf63 100644 (file)
@@ -31,6 +31,8 @@ import org.whispersystems.libsignal.*;
 import org.whispersystems.libsignal.ecc.Curve;
 import org.whispersystems.libsignal.ecc.ECKeyPair;
 import org.whispersystems.libsignal.ecc.ECPublicKey;
+import org.whispersystems.libsignal.fingerprint.Fingerprint;
+import org.whispersystems.libsignal.fingerprint.NumericFingerprintGenerator;
 import org.whispersystems.libsignal.state.PreKeyRecord;
 import org.whispersystems.libsignal.state.SignedPreKeyRecord;
 import org.whispersystems.libsignal.util.KeyHelper;
@@ -125,6 +127,10 @@ class Manager implements Signal {
         return username;
     }
 
+    private IdentityKey getIdentity() {
+        return signalProtocolStore.getIdentityKeyPair().getPublicKey();
+    }
+
     public int getDeviceId() {
         return deviceId;
     }
@@ -1330,6 +1336,29 @@ class Manager implements Signal {
         return false;
     }
 
+    /**
+     * Trust this the identity with this safety number
+     *
+     * @param name         username of the identity
+     * @param safetyNumber Safety number
+     */
+    public boolean trustIdentityVerifiedSafetyNumber(String name, String safetyNumber) {
+        List<JsonIdentityKeyStore.Identity> ids = signalProtocolStore.getIdentities(name);
+        if (ids == null) {
+            return false;
+        }
+        for (JsonIdentityKeyStore.Identity id : ids) {
+            if (!safetyNumber.equals(computeSafetyNumber(name, id.identityKey))) {
+                continue;
+            }
+
+            signalProtocolStore.saveIdentity(name, id.identityKey, TrustLevel.TRUSTED_VERIFIED);
+            save();
+            return true;
+        }
+        return false;
+    }
+
     /**
      * Trust all keys of this identity without verification
      *
@@ -1348,4 +1377,9 @@ class Manager implements Signal {
         save();
         return true;
     }
+
+    public String computeSafetyNumber(String theirUsername, IdentityKey theirIdentityKey) {
+        Fingerprint fingerprint = new NumericFingerprintGenerator(5200).createFor(username, getIdentity(), theirUsername, theirIdentityKey);
+        return fingerprint.getDisplayableFingerprint().getDisplayText();
+    }
 }