1 /*
2  * Copyright (C) 2020 Finn Herzfeld
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 package io.finn.signald.util;
19 
20 import io.finn.signald.db.Recipient;
21 import org.whispersystems.libsignal.IdentityKey;
22 import org.whispersystems.libsignal.fingerprint.Fingerprint;
23 import org.whispersystems.libsignal.fingerprint.NumericFingerprintGenerator;
24 import org.whispersystems.signalservice.api.util.UuidUtil;
25 
26 public class SafetyNumberHelper {
27   // It seems like the official Signal apps don't use v2 safety numbers yet, so this is disabled for now.
28   public static boolean UseV2SafetyNumbers = false;
29 
30   // computeSafetyNumber derived from signal-cli (computeSafetyNumber in src/main/java/org/asamk/signal/manager/Common.java)
computeFingerprint(Recipient self, IdentityKey ownIdentityKey, Recipient recipient, IdentityKey theirIdentityKey)31   public static Fingerprint computeFingerprint(Recipient self, IdentityKey ownIdentityKey, Recipient recipient, IdentityKey theirIdentityKey) {
32     int version;
33     byte[] ownId;
34     byte[] theirId;
35 
36     if (UseV2SafetyNumbers && self.getUUID() != null && recipient.getUUID() != null) {
37       // Version 2: UUID user
38       version = 2;
39       ownId = UuidUtil.toByteArray(self.getUUID());
40       theirId = UuidUtil.toByteArray(recipient.getUUID());
41     } else {
42       // Version 1: E164 user
43       version = 1;
44       if (!self.getAddress().getNumber().isPresent() || !recipient.getAddress().getNumber().isPresent()) {
45         return null;
46       }
47       ownId = self.getAddress().getNumber().get().getBytes();
48       theirId = recipient.getAddress().getNumber().get().getBytes();
49     }
50 
51     return new NumericFingerprintGenerator(5200).createFor(version, ownId, ownIdentityKey, theirId, theirIdentityKey);
52   }
53 
computeSafetyNumber(Recipient self, IdentityKey ownIdentityKey, Recipient recipient, IdentityKey theirIdentityKey)54   public static String computeSafetyNumber(Recipient self, IdentityKey ownIdentityKey, Recipient recipient, IdentityKey theirIdentityKey) {
55     Fingerprint fingerprint = computeFingerprint(self, ownIdentityKey, recipient, theirIdentityKey);
56     if (fingerprint == null) {
57       return "INVALID ID";
58     }
59     return fingerprint.getDisplayableFingerprint().getDisplayText();
60   }
61 }
62