]> nmode's Git Repositories - signal-cli/commitdiff
Trust an identity with its scannable safety numbers from the other device
authorAsamK <asamk@gmx.de>
Sun, 22 Aug 2021 17:23:49 +0000 (19:23 +0200)
committerAsamK <asamk@gmx.de>
Sun, 22 Aug 2021 17:23:49 +0000 (19:23 +0200)
Attention, the scannable fingerprints are asymetric, so the scannable
fingerprints from the local listIdentities command can't be used to trust
an identity. The scannable fingerprint must come from the other device.

lib/src/main/java/org/asamk/signal/manager/Manager.java
src/main/java/org/asamk/signal/commands/TrustCommand.java

index cde2714f25012ad39634b39a0bea5163283436bd..cc57e0614b27451a0864e19e19b70cc8b66d8f51 100644 (file)
@@ -81,6 +81,9 @@ import org.whispersystems.libsignal.IdentityKeyPair;
 import org.whispersystems.libsignal.InvalidKeyException;
 import org.whispersystems.libsignal.InvalidMessageException;
 import org.whispersystems.libsignal.ecc.ECPublicKey;
+import org.whispersystems.libsignal.fingerprint.Fingerprint;
+import org.whispersystems.libsignal.fingerprint.FingerprintParsingException;
+import org.whispersystems.libsignal.fingerprint.FingerprintVersionMismatchException;
 import org.whispersystems.libsignal.state.PreKeyRecord;
 import org.whispersystems.libsignal.state.SignedPreKeyRecord;
 import org.whispersystems.libsignal.util.Pair;
@@ -2668,6 +2671,25 @@ public class Manager implements Closeable {
                 TrustLevel.TRUSTED_VERIFIED);
     }
 
+    /**
+     * Trust this the identity with this scannable safety number
+     *
+     * @param name         username of the identity
+     * @param safetyNumber Scannable safety number
+     */
+    public boolean trustIdentityVerifiedSafetyNumber(String name, byte[] safetyNumber) throws InvalidNumberException {
+        var recipientId = canonicalizeAndResolveRecipient(name);
+        var address = account.getRecipientStore().resolveServiceAddress(recipientId);
+        return trustIdentity(recipientId, identityKey -> {
+            final var fingerprint = computeSafetyNumberFingerprint(address, identityKey);
+            try {
+                return fingerprint != null && fingerprint.getScannableFingerprint().compareTo(safetyNumber);
+            } catch (FingerprintVersionMismatchException | FingerprintParsingException e) {
+                return false;
+            }
+        }, TrustLevel.TRUSTED_VERIFIED);
+    }
+
     /**
      * Trust all keys of this identity without verification
      *
@@ -2717,21 +2739,23 @@ public class Manager implements Closeable {
     }
 
     public String computeSafetyNumber(SignalServiceAddress theirAddress, IdentityKey theirIdentityKey) {
-        final var fingerprint = Utils.computeSafetyNumber(capabilities.isUuid(),
-                account.getSelfAddress(),
-                getIdentityKeyPair().getPublicKey(),
-                theirAddress,
-                theirIdentityKey);
+        final Fingerprint fingerprint = computeSafetyNumberFingerprint(theirAddress, theirIdentityKey);
         return fingerprint == null ? null : fingerprint.getDisplayableFingerprint().getDisplayText();
     }
 
     public byte[] computeSafetyNumberForScanning(SignalServiceAddress theirAddress, IdentityKey theirIdentityKey) {
-        final var fingerprint = Utils.computeSafetyNumber(capabilities.isUuid(),
+        final Fingerprint fingerprint = computeSafetyNumberFingerprint(theirAddress, theirIdentityKey);
+        return fingerprint == null ? null : fingerprint.getScannableFingerprint().getSerialized();
+    }
+
+    private Fingerprint computeSafetyNumberFingerprint(
+            final SignalServiceAddress theirAddress, final IdentityKey theirIdentityKey
+    ) {
+        return Utils.computeSafetyNumber(capabilities.isUuid(),
                 account.getSelfAddress(),
                 getIdentityKeyPair().getPublicKey(),
                 theirAddress,
                 theirIdentityKey);
-        return fingerprint == null ? null : fingerprint.getScannableFingerprint().getSerialized();
     }
 
     @Deprecated
index 78f22c190d2f0b731e4928469cd8d92256f2d981..65487ba7fd77a5fa07d5c376597d4ca1077856cc 100644 (file)
@@ -11,6 +11,7 @@ import org.asamk.signal.manager.Manager;
 import org.asamk.signal.util.Hex;
 import org.whispersystems.signalservice.api.util.InvalidNumberException;
 
+import java.util.Base64;
 import java.util.Locale;
 
 public class TrustCommand implements JsonRpcLocalCommand {
@@ -49,44 +50,59 @@ public class TrustCommand implements JsonRpcLocalCommand {
             }
         } else {
             var safetyNumber = ns.getString("verified-safety-number");
-            if (safetyNumber != null) {
-                safetyNumber = safetyNumber.replaceAll(" ", "");
-                if (safetyNumber.length() == 66) {
-                    byte[] fingerprintBytes;
-                    try {
-                        fingerprintBytes = Hex.toByteArray(safetyNumber.toLowerCase(Locale.ROOT));
-                    } catch (Exception e) {
-                        throw new UserErrorException(
-                                "Failed to parse the fingerprint, make sure the fingerprint is a correctly encoded hex string without additional characters.");
-                    }
-                    boolean res;
-                    try {
-                        res = m.trustIdentityVerified(number, fingerprintBytes);
-                    } catch (InvalidNumberException e) {
-                        throw new UserErrorException("Failed to parse recipient: " + e.getMessage());
-                    }
-                    if (!res) {
-                        throw new UserErrorException(
-                                "Failed to set the trust for the fingerprint of this number, make sure the number and the fingerprint are correct.");
-                    }
-                } else if (safetyNumber.length() == 60) {
-                    boolean res;
-                    try {
-                        res = m.trustIdentityVerifiedSafetyNumber(number, safetyNumber);
-                    } catch (InvalidNumberException e) {
-                        throw new UserErrorException("Failed to parse recipient: " + e.getMessage());
-                    }
-                    if (!res) {
-                        throw new UserErrorException(
-                                "Failed to set the trust for the safety number of this phone number, make sure the phone number and the safety number are correct.");
-                    }
-                } else {
+            if (safetyNumber == null) {
+                throw new UserErrorException(
+                        "You need to specify the fingerprint/safety number you have verified with -v SAFETY_NUMBER");
+            }
+
+            safetyNumber = safetyNumber.replaceAll(" ", "");
+            if (safetyNumber.length() == 66) {
+                byte[] fingerprintBytes;
+                try {
+                    fingerprintBytes = Hex.toByteArray(safetyNumber.toLowerCase(Locale.ROOT));
+                } catch (Exception e) {
                     throw new UserErrorException(
-                            "Safety number has invalid format, either specify the old hex fingerprint or the new safety number");
+                            "Failed to parse the fingerprint, make sure the fingerprint is a correctly encoded hex string without additional characters.");
+                }
+                boolean res;
+                try {
+                    res = m.trustIdentityVerified(number, fingerprintBytes);
+                } catch (InvalidNumberException e) {
+                    throw new UserErrorException("Failed to parse recipient: " + e.getMessage());
+                }
+                if (!res) {
+                    throw new UserErrorException(
+                            "Failed to set the trust for the fingerprint of this number, make sure the number and the fingerprint are correct.");
+                }
+            } else if (safetyNumber.length() == 60) {
+                boolean res;
+                try {
+                    res = m.trustIdentityVerifiedSafetyNumber(number, safetyNumber);
+                } catch (InvalidNumberException e) {
+                    throw new UserErrorException("Failed to parse recipient: " + e.getMessage());
+                }
+                if (!res) {
+                    throw new UserErrorException(
+                            "Failed to set the trust for the safety number of this phone number, make sure the phone number and the safety number are correct.");
                 }
             } else {
-                throw new UserErrorException(
-                        "You need to specify the fingerprint/safety number you have verified with -v SAFETY_NUMBER");
+                final byte[] scannableSafetyNumber;
+                try {
+                    scannableSafetyNumber = Base64.getDecoder().decode(safetyNumber);
+                } catch (IllegalArgumentException e) {
+                    throw new UserErrorException(
+                            "Safety number has invalid format, either specify the old hex fingerprint or the new safety number");
+                }
+                boolean res;
+                try {
+                    res = m.trustIdentityVerifiedSafetyNumber(number, scannableSafetyNumber);
+                } catch (InvalidNumberException e) {
+                    throw new UserErrorException("Failed to parse recipient: " + e.getMessage());
+                }
+                if (!res) {
+                    throw new UserErrorException(
+                            "Failed to set the trust for the safety number of this phone number, make sure the phone number and the safety number are correct.");
+                }
             }
         }
     }