From c49b05cd75dd8cee795859b6045fbec0040d4144 Mon Sep 17 00:00:00 2001 From: AsamK Date: Mon, 21 Dec 2020 14:56:37 +0100 Subject: [PATCH] Get UUIDs for unknown numbers from server --- .../asamk/signal/manager/IasTrustStore.java | 18 +++++++++ .../org/asamk/signal/manager/Manager.java | 38 +++++++++++++++++- .../asamk/signal/manager/ServiceConfig.java | 25 +++++++++++- .../org/asamk/signal/manager/ias.store | Bin 0 -> 1441 bytes 4 files changed, 79 insertions(+), 2 deletions(-) create mode 100644 src/main/java/org/asamk/signal/manager/IasTrustStore.java create mode 100644 src/main/resources/org/asamk/signal/manager/ias.store diff --git a/src/main/java/org/asamk/signal/manager/IasTrustStore.java b/src/main/java/org/asamk/signal/manager/IasTrustStore.java new file mode 100644 index 00000000..f9bbb0b3 --- /dev/null +++ b/src/main/java/org/asamk/signal/manager/IasTrustStore.java @@ -0,0 +1,18 @@ +package org.asamk.signal.manager; + +import org.whispersystems.signalservice.api.push.TrustStore; + +import java.io.InputStream; + +class IasTrustStore implements TrustStore { + + @Override + public InputStream getKeyStoreInputStream() { + return IasTrustStore.class.getResourceAsStream("ias.store"); + } + + @Override + public String getKeyStorePassword() { + return "whisper"; + } +} diff --git a/src/main/java/org/asamk/signal/manager/Manager.java b/src/main/java/org/asamk/signal/manager/Manager.java index d15d164b..26f5abbc 100644 --- a/src/main/java/org/asamk/signal/manager/Manager.java +++ b/src/main/java/org/asamk/signal/manager/Manager.java @@ -120,6 +120,9 @@ import org.whispersystems.signalservice.api.util.StreamDetails; import org.whispersystems.signalservice.api.util.UptimeSleepTimer; import org.whispersystems.signalservice.api.util.UuidUtil; import org.whispersystems.signalservice.internal.configuration.SignalServiceConfiguration; +import org.whispersystems.signalservice.internal.contacts.crypto.Quote; +import org.whispersystems.signalservice.internal.contacts.crypto.UnauthenticatedQuoteException; +import org.whispersystems.signalservice.internal.contacts.crypto.UnauthenticatedResponseException; import org.whispersystems.signalservice.internal.push.SignalServiceProtos; import org.whispersystems.signalservice.internal.push.UnsupportedDataMessageException; import org.whispersystems.signalservice.internal.push.VerifyAccountResponse; @@ -142,6 +145,7 @@ import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Paths; import java.nio.file.StandardCopyOption; +import java.security.SignatureException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -151,6 +155,7 @@ import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Locale; +import java.util.Map; import java.util.Objects; import java.util.Set; import java.util.UUID; @@ -161,7 +166,9 @@ import java.util.stream.Collectors; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; +import static org.asamk.signal.manager.ServiceConfig.CDS_MRENCLAVE; import static org.asamk.signal.manager.ServiceConfig.capabilities; +import static org.asamk.signal.manager.ServiceConfig.getIasKeyStore; public class Manager implements Closeable { @@ -1279,10 +1286,39 @@ public class Manager implements Closeable { private Collection getSignalServiceAddresses(Collection numbers) throws InvalidNumberException { final Set signalServiceAddresses = new HashSet<>(numbers.size()); + final Set missingUuids = new HashSet<>(); for (String number : numbers) { - signalServiceAddresses.add(canonicalizeAndResolveSignalServiceAddress(number)); + final SignalServiceAddress resolvedAddress = canonicalizeAndResolveSignalServiceAddress(number); + if (resolvedAddress.getUuid().isPresent()) { + signalServiceAddresses.add(resolvedAddress); + } else { + missingUuids.add(resolvedAddress); + } + } + + Map registeredUsers; + try { + registeredUsers = accountManager.getRegisteredUsers(getIasKeyStore(), + missingUuids.stream().map(a -> a.getNumber().get()).collect(Collectors.toSet()), + CDS_MRENCLAVE); + } catch (IOException | Quote.InvalidQuoteFormatException | UnauthenticatedQuoteException | SignatureException | UnauthenticatedResponseException e) { + System.err.println("Failed to resolve uuids from server: " + e.getMessage()); + registeredUsers = new HashMap<>(); + } + + for (SignalServiceAddress address : missingUuids) { + final String number = address.getNumber().get(); + if (registeredUsers.containsKey(number)) { + final SignalServiceAddress newAddress = resolveSignalServiceAddress(new SignalServiceAddress( + registeredUsers.get(number), + number)); + signalServiceAddresses.add(newAddress); + } else { + signalServiceAddresses.add(address); + } } + return signalServiceAddresses; } diff --git a/src/main/java/org/asamk/signal/manager/ServiceConfig.java b/src/main/java/org/asamk/signal/manager/ServiceConfig.java index 7f7d5570..5721b166 100644 --- a/src/main/java/org/asamk/signal/manager/ServiceConfig.java +++ b/src/main/java/org/asamk/signal/manager/ServiceConfig.java @@ -13,6 +13,10 @@ import org.whispersystems.signalservice.internal.configuration.SignalStorageUrl; import org.whispersystems.util.Base64; import java.io.IOException; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.cert.CertificateException; import java.util.Collections; import java.util.List; import java.util.Map; @@ -29,12 +33,16 @@ public class ServiceConfig { final static int MAX_ENVELOPE_SIZE = 0; final static long AVATAR_DOWNLOAD_FAILSAFE_MAX_SIZE = 10 * 1024 * 1024; + final static String CDS_MRENCLAVE = "c98e00a4e3ff977a56afefe7362a27e4961e4f19e211febfbb19b897e6b80b15"; + private final static String URL = "https://textsecure-service.whispersystems.org"; private final static String CDN_URL = "https://cdn.signal.org"; private final static String CDN2_URL = "https://cdn2.signal.org"; + private final static String SIGNAL_CONTACT_DISCOVERY_URL = "https://api.directory.signal.org"; private final static String SIGNAL_KEY_BACKUP_URL = "https://api.backup.signal.org"; private final static String STORAGE_URL = "https://storage.signal.org"; private final static TrustStore TRUST_STORE = new WhisperTrustStore(); + private final static TrustStore IAS_TRUST_STORE = new IasTrustStore(); private final static Optional dns = Optional.absent(); @@ -71,7 +79,8 @@ public class ServiceConfig { return new SignalServiceConfiguration(new SignalServiceUrl[]{new SignalServiceUrl(URL, TRUST_STORE)}, makeSignalCdnUrlMapFor(new SignalCdnUrl[]{new SignalCdnUrl(CDN_URL, TRUST_STORE)}, new SignalCdnUrl[]{new SignalCdnUrl(CDN2_URL, TRUST_STORE)}), - new SignalContactDiscoveryUrl[0], + new SignalContactDiscoveryUrl[]{new SignalContactDiscoveryUrl(SIGNAL_CONTACT_DISCOVERY_URL, + TRUST_STORE)}, new SignalKeyBackupServiceUrl[]{new SignalKeyBackupServiceUrl(SIGNAL_KEY_BACKUP_URL, TRUST_STORE)}, new SignalStorageUrl[]{new SignalStorageUrl(STORAGE_URL, TRUST_STORE)}, interceptors, @@ -79,6 +88,20 @@ public class ServiceConfig { zkGroupServerPublicParams); } + static KeyStore getIasKeyStore() { + try { + TrustStore contactTrustStore = IAS_TRUST_STORE; + + KeyStore keyStore = KeyStore.getInstance("BKS"); + keyStore.load(contactTrustStore.getKeyStoreInputStream(), + contactTrustStore.getKeyStorePassword().toCharArray()); + + return keyStore; + } catch (KeyStoreException | CertificateException | IOException | NoSuchAlgorithmException e) { + throw new AssertionError(e); + } + } + private static Map makeSignalCdnUrlMapFor( SignalCdnUrl[] cdn0Urls, SignalCdnUrl[] cdn2Urls ) { diff --git a/src/main/resources/org/asamk/signal/manager/ias.store b/src/main/resources/org/asamk/signal/manager/ias.store new file mode 100644 index 0000000000000000000000000000000000000000..e0b8ec8ccacc48459adb2384402b887682cf45da GIT binary patch literal 1441 zcmZQzU|?ckU=WcLo>6|#P&tUfG}q(0mN9?; zYlNPufh7Y2tG_`LtG7WD^X3K2OpHuSoD3J)%VLcdZqvrKx4qfV;4XaS?K$F|sl+H!=1z z7&I|a`cv# z+H3zEwy`}EXPUw|w_v z`!R=OKJT)#+yA_Kak5FOFXU4Ui`c~;x8_;#4MM-~+8*~+O{!db=)l#e|M_f6PO;KV z%!~|-iyKcGG#)cZU}FxIm1l`G2sa2_5WFC;%|D~0q`*pFzoe+NxFj{DIJKxOGdZ^^)^*^^^1SN>cMm^qqrz^n=|a^pTP)B(*{ltFxnCa#4n0pM!SzL}vP?kHQuJ2S$xZV*A573vU3NTLj8i6KwSw2W zLWxdKojN%qPC?hG{(~k?hI-}8ET`O@KJ~;a*Rm#?S6vq$PCUON>DP{xMwf4H2##WB zx)2&)@>Jn5v%zPRhUaTfUOyqHP+;h^pW&#+3T`*!#=i+#O~;vo8dp7?nsjEXvEPab zcB$NqY>i*f^=;EzGsn@hL&fUNq)*WwZSH@6eMYnIsr0TWQ;TicYNwAx1>R$@S!6wErjW$R c>kO@;PruI8IpZ#GEq!p+8#{Bb06B*xuK)l5 literal 0 HcmV?d00001 -- 2.50.1