From 01f5ff7c865213405774325cc085d2736374b52b Mon Sep 17 00:00:00 2001
From: Mikunj <mikunj@live.com.au>
Date: Tue, 28 Jan 2020 12:27:12 +1100
Subject: [PATCH 1/3] Fix up build gradle.

---
 .../crypto/UnidentifiedAccessUtil.java        | 19 +++++++++++++++--
 .../securesms/jobs/PushSendJob.java           | 21 +------------------
 2 files changed, 18 insertions(+), 22 deletions(-)

diff --git a/src/org/thoughtcrime/securesms/crypto/UnidentifiedAccessUtil.java b/src/org/thoughtcrime/securesms/crypto/UnidentifiedAccessUtil.java
index 141ec67de5..6f8f5e9e65 100644
--- a/src/org/thoughtcrime/securesms/crypto/UnidentifiedAccessUtil.java
+++ b/src/org/thoughtcrime/securesms/crypto/UnidentifiedAccessUtil.java
@@ -6,6 +6,7 @@ import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
 import android.support.annotation.WorkerThread;
 
+import org.signal.libsignal.metadata.SignalProtos;
 import org.signal.libsignal.metadata.certificate.CertificateValidator;
 import org.signal.libsignal.metadata.certificate.InvalidCertificateException;
 import network.loki.messenger.BuildConfig;
@@ -20,6 +21,7 @@ import org.whispersystems.libsignal.ecc.ECPublicKey;
 import org.whispersystems.libsignal.util.guava.Optional;
 import org.whispersystems.signalservice.api.crypto.UnidentifiedAccess;
 import org.whispersystems.signalservice.api.crypto.UnidentifiedAccessPair;
+import org.whispersystems.signalservice.api.push.SignalServiceAddress;
 
 import java.io.IOException;
 
@@ -48,7 +50,7 @@ public class UnidentifiedAccessUtil {
     try {
       byte[] theirUnidentifiedAccessKey       = getTargetUnidentifiedAccessKey(recipient);
       byte[] ourUnidentifiedAccessKey         = getSelfUnidentifiedAccessKey(context);
-      byte[] ourUnidentifiedAccessCertificate = TextSecurePreferences.getUnidentifiedAccessCertificate(context);
+      byte[] ourUnidentifiedAccessCertificate = getUnidentifiedAccessCertificate(context);
 
       if (TextSecurePreferences.isUniversalUnidentifiedAccess(context)) {
         ourUnidentifiedAccessKey = Util.getSecretBytes(16);
@@ -83,7 +85,7 @@ public class UnidentifiedAccessUtil {
 
     try {
       byte[] ourUnidentifiedAccessKey         = getSelfUnidentifiedAccessKey(context);
-      byte[] ourUnidentifiedAccessCertificate = TextSecurePreferences.getUnidentifiedAccessCertificate(context);
+      byte[] ourUnidentifiedAccessCertificate = getUnidentifiedAccessCertificate(context);
 
       if (TextSecurePreferences.isUniversalUnidentifiedAccess(context)) {
         ourUnidentifiedAccessKey = Util.getSecretBytes(16);
@@ -125,4 +127,17 @@ public class UnidentifiedAccessUtil {
         throw new AssertionError("Unknown mode: " + recipient.getUnidentifiedAccessMode().getMode());
     }
   }
+
+  private static @Nullable byte[] getUnidentifiedAccessCertificate(Context context) {
+    String ourNumber = TextSecurePreferences.getLocalNumber(context);
+    if (ourNumber != null) {
+      SignalProtos.SenderCertificate certificate = SignalProtos.SenderCertificate.newBuilder()
+              .setSender(ourNumber)
+              .setSenderDevice(SignalServiceAddress.DEFAULT_DEVICE_ID)
+              .build();
+      return certificate.toByteArray();
+    }
+
+    return null;
+  }
 }
diff --git a/src/org/thoughtcrime/securesms/jobs/PushSendJob.java b/src/org/thoughtcrime/securesms/jobs/PushSendJob.java
index 526264ef67..591e3f43f8 100644
--- a/src/org/thoughtcrime/securesms/jobs/PushSendJob.java
+++ b/src/org/thoughtcrime/securesms/jobs/PushSendJob.java
@@ -280,26 +280,7 @@ public abstract class PushSendJob extends SendJob {
   }
 
   protected void rotateSenderCertificateIfNecessary() throws IOException {
-    try {
-      byte[] certificateBytes = TextSecurePreferences.getUnidentifiedAccessCertificate(context);
-
-      if (certificateBytes == null) {
-        throw new InvalidCertificateException("No certificate was present.");
-      }
-
-      SenderCertificate certificate = new SenderCertificate(certificateBytes);
-
-      if (System.currentTimeMillis() > (certificate.getExpiration() - CERTIFICATE_EXPIRATION_BUFFER)) {
-        throw new InvalidCertificateException("Certificate is expired, or close to it. Expires on: " + certificate.getExpiration() + ", currently: " + System.currentTimeMillis());
-      }
-
-      Log.d(TAG, "Certificate is valid.");
-    } catch (InvalidCertificateException e) {
-      Log.w(TAG, "Certificate was invalid at send time. Fetching a new one.", e);
-      RotateCertificateJob certificateJob = new RotateCertificateJob(context);
-      ApplicationContext.getInstance(context).injectDependencies(certificateJob);
-      certificateJob.onRun();
-    }
+    // Loki - We don't need verification on sender certificates
   }
 
   protected SignalServiceSyncMessage buildSelfSendSyncMessage(@NonNull Context context, @NonNull SignalServiceDataMessage message, Optional<UnidentifiedAccessPair> syncAccess) {

From 62d391085b7bf8dd4fb6748cc82106d5c77b5953 Mon Sep 17 00:00:00 2001
From: Mikunj <mikunj@live.com.au>
Date: Wed, 29 Jan 2020 13:49:39 +1100
Subject: [PATCH 2/3] Stop relying on SignalServiceEnvelope and instead use
 SignalServiceContent to determine message sender and friend request

---
 .../crypto/UnidentifiedAccessUtil.java        |  7 +--
 .../securesms/jobs/PushDecryptJob.java        | 52 +++++++++----------
 .../securesms/loki/LokiPublicChatPoller.kt    |  2 +-
 .../securesms/loki/LokiRSSFeedPoller.kt       |  2 +-
 .../securesms/loki/MultiDeviceUtilities.kt    |  4 +-
 .../loki/PushBackgroundMessageSendJob.kt      |  6 ++-
 6 files changed, 35 insertions(+), 38 deletions(-)

diff --git a/src/org/thoughtcrime/securesms/crypto/UnidentifiedAccessUtil.java b/src/org/thoughtcrime/securesms/crypto/UnidentifiedAccessUtil.java
index 6f8f5e9e65..b54d81b11f 100644
--- a/src/org/thoughtcrime/securesms/crypto/UnidentifiedAccessUtil.java
+++ b/src/org/thoughtcrime/securesms/crypto/UnidentifiedAccessUtil.java
@@ -30,12 +30,7 @@ public class UnidentifiedAccessUtil {
   private static final String TAG = UnidentifiedAccessUtil.class.getSimpleName();
 
   public static CertificateValidator getCertificateValidator() {
-    try {
-      ECPublicKey unidentifiedSenderTrustRoot = Curve.decodePoint(Base64.decode(BuildConfig.UNIDENTIFIED_SENDER_TRUST_ROOT), 0);
-      return new CertificateValidator(unidentifiedSenderTrustRoot);
-    } catch (InvalidKeyException | IOException e) {
-      throw new AssertionError(e);
-    }
+    return new CertificateValidator();
   }
 
   @WorkerThread
diff --git a/src/org/thoughtcrime/securesms/jobs/PushDecryptJob.java b/src/org/thoughtcrime/securesms/jobs/PushDecryptJob.java
index 9ec5d229a1..d4c9423c7c 100644
--- a/src/org/thoughtcrime/securesms/jobs/PushDecryptJob.java
+++ b/src/org/thoughtcrime/securesms/jobs/PushDecryptJob.java
@@ -274,18 +274,14 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
       SignalServiceAddress     localAddress             = new SignalServiceAddress(TextSecurePreferences.getLocalNumber(context));
       LokiServiceCipher        cipher                   = new LokiServiceCipher(localAddress, axolotlStore, lokiThreadDatabase, lokiPreKeyRecordDatabase, UnidentifiedAccessUtil.getCertificateValidator());
 
-      // Loki - Handle session reset logic
-      if (!envelope.isFriendRequest() && cipher.getSessionStatus(envelope) == null && envelope.isPreKeySignalMessage()) {
-        cipher.validateBackgroundMessage(envelope, envelope.getContent());
-      }
+      SignalServiceContent content = cipher.decrypt(envelope);
 
       // Loki - Ignore any friend requests that we got before restoration
-      if (envelope.isFriendRequest() && envelope.getTimestamp() < TextSecurePreferences.getRestorationTime(context)) {
+      if (content.isFriendRequest() && content.getTimestamp() < TextSecurePreferences.getRestorationTime(context)) {
         Log.d("Loki", "Ignoring friend request received before restoration.");
         return;
       }
 
-      SignalServiceContent content = cipher.decrypt(envelope);
 
       if (shouldIgnore(content)) {
         Log.i(TAG, "Ignoring message.");
@@ -293,12 +289,12 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
       }
 
       // Loki - Handle friend request acceptance if needed
-      acceptFriendRequestIfNeeded(envelope, content);
+      acceptFriendRequestIfNeeded(content);
 
       // Loki - Store pre key bundle
       // We shouldn't store it if it's a pairing message
       if (!content.getPairingAuthorisation().isPresent()) {
-        storePreKeyBundleIfNeeded(envelope, content);
+        storePreKeyBundleIfNeeded(content);
       }
 
       if (content.lokiServiceMessage.isPresent()) {
@@ -313,24 +309,24 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
       if (rawSenderDisplayName.isPresent() && rawSenderDisplayName.get().length() > 0) {
         // If we got a name from our primary device then we set our profile name to match it
         String ourPrimaryDevice = TextSecurePreferences.getMasterHexEncodedPublicKey(context);
-        if (ourPrimaryDevice != null && envelope.getSource().equals(ourPrimaryDevice)) {
+        if (ourPrimaryDevice != null && content.getSender().equals(ourPrimaryDevice)) {
           TextSecurePreferences.setProfileName(context, rawSenderDisplayName.get());
         }
 
         // If we receive a message from our device then don't set the display name in the database (as we probably have a alias set for them)
         MultiDeviceUtilities.isOneOfOurDevices(context, Address.fromSerialized(content.getSender())).success(isOneOfOurDevice -> {
-          if (!isOneOfOurDevice) { setDisplayName(envelope.getSource(), rawSenderDisplayName.get()); }
+          if (!isOneOfOurDevice) { setDisplayName(content.getSender(), rawSenderDisplayName.get()); }
           return Unit.INSTANCE;
         });
       }
 
       if (content.getPairingAuthorisation().isPresent()) {
-        handlePairingMessage(content.getPairingAuthorisation().get(), envelope, content);
+        handlePairingMessage(content.getPairingAuthorisation().get(), content);
       } else if (content.getDataMessage().isPresent()) {
         SignalServiceDataMessage message        = content.getDataMessage().get();
         boolean                  isMediaMessage = message.getAttachments().isPresent() || message.getQuote().isPresent() || message.getSharedContacts().isPresent() || message.getPreviews().isPresent() || message.getSticker().isPresent();
 
-        if (!envelope.isFriendRequest() && message.isUnpairingRequest()) {
+        if (!content.isFriendRequest() && message.isUnpairingRequest()) {
           // Make sure we got the request from our primary device
           String ourPrimaryDevice = TextSecurePreferences.getMasterHexEncodedPublicKey(context);
           if (ourPrimaryDevice != null && ourPrimaryDevice.equals(content.getSender())) {
@@ -363,7 +359,7 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
           }
 
           // Loki - Handle friend request logic if needed
-          updateFriendRequestStatusIfNeeded(envelope, content, message);
+          updateFriendRequestStatusIfNeeded(content, message);
         }
       } else if (content.getSyncMessage().isPresent()) {
         TextSecurePreferences.setMultiDevice(context, true);
@@ -404,8 +400,8 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
       }
 
       // Loki - Handle session reset logic
-      if (!envelope.isFriendRequest()) {
-        cipher.handleSessionResetRequestIfNeeded(envelope, cipher.getSessionStatus(envelope));
+      if (!content.isFriendRequest()) {
+        cipher.handleSessionResetRequestIfNeeded(content, cipher.getSessionStatus(content));
       }
     } catch (ProtocolInvalidVersionException e) {
       Log.w(TAG, e);
@@ -1109,26 +1105,26 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
     ApplicationContext.getInstance(context).getJobManager().add(new RetrieveProfileAvatarJob(primaryDevice, url));
   }
 
-  private void handlePairingMessage(@NonNull PairingAuthorisation authorisation, @NonNull SignalServiceEnvelope envelope, @NonNull SignalServiceContent content) {
+  private void handlePairingMessage(@NonNull PairingAuthorisation authorisation, @NonNull SignalServiceContent content) {
     String userHexEncodedPublicKey = TextSecurePreferences.getLocalNumber(context);
     if (authorisation.getType() == PairingAuthorisation.Type.REQUEST) {
-      handlePairingRequestMessage(authorisation, envelope, content);
+      handlePairingRequestMessage(authorisation, content);
     } else if (authorisation.getSecondaryDevicePublicKey().equals(userHexEncodedPublicKey)) {
-      handlePairingAuthorisationMessage(authorisation, envelope, content);
+      handlePairingAuthorisationMessage(authorisation, content);
     }
   }
 
-  private void handlePairingRequestMessage(@NonNull PairingAuthorisation authorisation, @NonNull SignalServiceEnvelope envelope, @NonNull SignalServiceContent content) {
+  private void handlePairingRequestMessage(@NonNull PairingAuthorisation authorisation, @NonNull SignalServiceContent content) {
     boolean isValid = isValidPairingMessage(authorisation);
     DeviceLinkingSession linkingSession = DeviceLinkingSession.Companion.getShared();
     if (isValid && linkingSession.isListeningForLinkingRequests()) {
       // Loki - If we successfully received a request then we should store the PreKeyBundle
-      storePreKeyBundleIfNeeded(envelope, content);
+      storePreKeyBundleIfNeeded(content);
       linkingSession.processLinkingRequest(authorisation);
     }
   }
 
-  private void handlePairingAuthorisationMessage(@NonNull PairingAuthorisation authorisation, @NonNull SignalServiceEnvelope envelope, @NonNull SignalServiceContent content) {
+  private void handlePairingAuthorisationMessage(@NonNull PairingAuthorisation authorisation, @NonNull SignalServiceContent content) {
     // Prepare
     boolean isSecondaryDevice = TextSecurePreferences.getMasterHexEncodedPublicKey(context) != null;
     if (isSecondaryDevice) {
@@ -1147,7 +1143,7 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
     if (authorisation.getType() != PairingAuthorisation.Type.GRANT) { return; }
     Log.d("Loki", "Received pairing authorisation message from: " + authorisation.getPrimaryDevicePublicKey() + ".");
     // Save PreKeyBundle if for whatever reason we got one
-    storePreKeyBundleIfNeeded(envelope, content);
+    storePreKeyBundleIfNeeded(content);
     // Process
     DeviceLinkingSession.Companion.getShared().processLinkingAuthorization(authorisation);
     // Store the primary device's public key
@@ -1188,7 +1184,7 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
     }
   }
 
-  private void storePreKeyBundleIfNeeded(@NonNull SignalServiceEnvelope envelope, @NonNull SignalServiceContent content) {
+  private void storePreKeyBundleIfNeeded(@NonNull SignalServiceContent content) {
     Recipient sender = Recipient.from(context, Address.fromSerialized(content.getSender()), false);
     if (!sender.isGroupRecipient() && content.lokiServiceMessage.isPresent()) {
       LokiServiceMessage lokiMessage = content.lokiServiceMessage.get();
@@ -1205,7 +1201,7 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
           lokiPreKeyBundleDatabase.setPreKeyBundle(content.getSender(), preKeyBundle);
 
           // Loki - If we received a friend request, but we were already friends with this user, then reset the session
-          if (envelope.isFriendRequest()) {
+          if (content.isFriendRequest()) {
             long threadID = threadDatabase.getThreadIdIfExistsFor(sender);
             if (lokiThreadDatabase.getFriendRequestStatus(threadID) == LokiThreadFriendRequestStatus.FRIENDS) {
               resetSession(content.getSender(), threadID);
@@ -1218,9 +1214,9 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
     }
   }
 
-  private void acceptFriendRequestIfNeeded(@NonNull SignalServiceEnvelope envelope, @NonNull SignalServiceContent content) {
+  private void acceptFriendRequestIfNeeded(@NonNull SignalServiceContent content) {
     // If we get anything other than a friend request, we can assume that we have a session with the other user
-    if (envelope.isFriendRequest() || isGroupChatMessage(content)) { return; }
+    if (content.isFriendRequest() || isGroupChatMessage(content)) { return; }
     becomeFriendsWithContact(content.getSender(), true);
   }
 
@@ -1251,8 +1247,8 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
     });
   }
 
-  private void updateFriendRequestStatusIfNeeded(@NonNull SignalServiceEnvelope envelope, @NonNull SignalServiceContent content, @NonNull SignalServiceDataMessage message) {
-    if (!envelope.isFriendRequest() || message.isGroupUpdate()) { return; }
+  private void updateFriendRequestStatusIfNeeded(@NonNull SignalServiceContent content, @NonNull SignalServiceDataMessage message) {
+    if (!content.isFriendRequest() || message.isGroupUpdate()) { return; }
     // This handles the case where another user sends us a regular message without authorisation
     Promise<Boolean, Exception> promise = PromiseUtil.timeout(MultiDeviceUtilities.shouldAutomaticallyBecomeFriendsWithDevice(content.getSender(), context), 8000);
     boolean shouldBecomeFriends = PromiseUtil.get(promise, false);
diff --git a/src/org/thoughtcrime/securesms/loki/LokiPublicChatPoller.kt b/src/org/thoughtcrime/securesms/loki/LokiPublicChatPoller.kt
index d423bcac56..954d8d3e06 100644
--- a/src/org/thoughtcrime/securesms/loki/LokiPublicChatPoller.kt
+++ b/src/org/thoughtcrime/securesms/loki/LokiPublicChatPoller.kt
@@ -164,7 +164,7 @@ class LokiPublicChatPoller(private val context: Context, private val group: Loki
 
             val senderPublicKey = primaryDevice ?: message.hexEncodedPublicKey
             val serviceDataMessage = getDataMessage(message)
-            val serviceContent = SignalServiceContent(serviceDataMessage, senderPublicKey, SignalServiceAddress.DEFAULT_DEVICE_ID, message.timestamp, false)
+            val serviceContent = SignalServiceContent(serviceDataMessage, senderPublicKey, SignalServiceAddress.DEFAULT_DEVICE_ID, message.timestamp, false, false)
             if (serviceDataMessage.quote.isPresent || (serviceDataMessage.attachments.isPresent && serviceDataMessage.attachments.get().size > 0) || serviceDataMessage.previews.isPresent) {
                 PushDecryptJob(context).handleMediaMessage(serviceContent, serviceDataMessage, Optional.absent(), Optional.of(message.serverID))
             } else {
diff --git a/src/org/thoughtcrime/securesms/loki/LokiRSSFeedPoller.kt b/src/org/thoughtcrime/securesms/loki/LokiRSSFeedPoller.kt
index d695c7de26..f2944d5319 100644
--- a/src/org/thoughtcrime/securesms/loki/LokiRSSFeedPoller.kt
+++ b/src/org/thoughtcrime/securesms/loki/LokiRSSFeedPoller.kt
@@ -66,7 +66,7 @@ class LokiRSSFeedPoller(private val context: Context, private val feed: LokiRSSF
                     val id = feed.id.toByteArray()
                     val x1 = SignalServiceGroup(SignalServiceGroup.Type.UPDATE, id, null, null, null)
                     val x2 = SignalServiceDataMessage(timestamp, x1, null, body)
-                    val x3 = SignalServiceContent(x2, "Loki", SignalServiceAddress.DEFAULT_DEVICE_ID, timestamp, false)
+                    val x3 = SignalServiceContent(x2, "Loki", SignalServiceAddress.DEFAULT_DEVICE_ID, timestamp, false, false)
                     PushDecryptJob(context).handleTextMessage(x3, x2, Optional.absent(), Optional.absent())
                 }
             } catch (exception: Exception) {
diff --git a/src/org/thoughtcrime/securesms/loki/MultiDeviceUtilities.kt b/src/org/thoughtcrime/securesms/loki/MultiDeviceUtilities.kt
index d3abb182dd..89f54bddee 100644
--- a/src/org/thoughtcrime/securesms/loki/MultiDeviceUtilities.kt
+++ b/src/org/thoughtcrime/securesms/loki/MultiDeviceUtilities.kt
@@ -13,6 +13,7 @@ import org.thoughtcrime.securesms.ApplicationContext
 import org.thoughtcrime.securesms.crypto.IdentityKeyUtil
 import org.thoughtcrime.securesms.crypto.PreKeyUtil
 import org.thoughtcrime.securesms.crypto.ProfileKeyUtil
+import org.thoughtcrime.securesms.crypto.UnidentifiedAccessUtil
 import org.thoughtcrime.securesms.database.Address
 import org.thoughtcrime.securesms.database.DatabaseFactory
 import org.thoughtcrime.securesms.logging.Log
@@ -128,7 +129,8 @@ fun sendPairingAuthorisationMessage(context: Context, contactHexEncodedPublicKey
 
   return try {
     Log.d("Loki", "Sending authorisation message to: $contactHexEncodedPublicKey.")
-    val result = messageSender.sendMessage(0, address, Optional.absent<UnidentifiedAccessPair>(), message.build())
+    val udAccess = UnidentifiedAccessUtil.getAccessFor(context, Recipient.from(context, Address.fromSerialized(contactHexEncodedPublicKey), false))
+    val result = messageSender.sendMessage(0, address, udAccess, message.build())
     if (result.success == null) {
       val exception = when {
         result.isNetworkFailure -> "Failed to send authorisation message due to a network error."
diff --git a/src/org/thoughtcrime/securesms/loki/PushBackgroundMessageSendJob.kt b/src/org/thoughtcrime/securesms/loki/PushBackgroundMessageSendJob.kt
index a7b1d081ad..347711abdc 100644
--- a/src/org/thoughtcrime/securesms/loki/PushBackgroundMessageSendJob.kt
+++ b/src/org/thoughtcrime/securesms/loki/PushBackgroundMessageSendJob.kt
@@ -1,12 +1,15 @@
 package org.thoughtcrime.securesms.loki
 
 import org.thoughtcrime.securesms.ApplicationContext
+import org.thoughtcrime.securesms.crypto.UnidentifiedAccessUtil
+import org.thoughtcrime.securesms.database.Address
 import org.thoughtcrime.securesms.database.DatabaseFactory
 import org.thoughtcrime.securesms.jobmanager.Data
 import org.thoughtcrime.securesms.jobmanager.Job
 import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint
 import org.thoughtcrime.securesms.jobs.BaseJob
 import org.thoughtcrime.securesms.logging.Log
+import org.thoughtcrime.securesms.recipients.Recipient
 import org.whispersystems.libsignal.util.guava.Optional
 import org.whispersystems.signalservice.api.crypto.UnidentifiedAccessPair
 import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage
@@ -99,7 +102,8 @@ class PushBackgroundMessageSendJob private constructor(
     val messageSender = ApplicationContext.getInstance(context).communicationModule.provideSignalMessageSender()
     val address = SignalServiceAddress(recipient)
     try {
-      messageSender.sendMessage(-1, address, Optional.absent<UnidentifiedAccessPair>(), dataMessage.build()) // The message ID doesn't matter
+      val udAccess = UnidentifiedAccessUtil.getAccessFor(context, Recipient.from(context, Address.fromSerialized(recipient), false))
+      messageSender.sendMessage(-1, address, udAccess, dataMessage.build()) // The message ID doesn't matter
     } catch (e: Exception) {
       Log.d("Loki", "Failed to send background message to: ${recipient}.")
       throw e

From 5fa6e5a75cf322efc30325b7047cc95f71cff739 Mon Sep 17 00:00:00 2001
From: Mikunj <mikunj@live.com.au>
Date: Wed, 29 Jan 2020 16:17:53 +1100
Subject: [PATCH 3/3] Enable sealed sender by default

---
 .../securesms/jobs/MultiDeviceContactUpdateJob.java        | 7 ++++++-
 .../thoughtcrime/securesms/loki/PushMessageSyncSendJob.kt  | 5 ++++-
 src/org/thoughtcrime/securesms/recipients/Recipient.java   | 2 +-
 .../thoughtcrime/securesms/util/TextSecurePreferences.java | 4 +++-
 4 files changed, 14 insertions(+), 4 deletions(-)

diff --git a/src/org/thoughtcrime/securesms/jobs/MultiDeviceContactUpdateJob.java b/src/org/thoughtcrime/securesms/jobs/MultiDeviceContactUpdateJob.java
index 6479ef0b64..aa22fa51e5 100644
--- a/src/org/thoughtcrime/securesms/jobs/MultiDeviceContactUpdateJob.java
+++ b/src/org/thoughtcrime/securesms/jobs/MultiDeviceContactUpdateJob.java
@@ -29,6 +29,8 @@ import org.thoughtcrime.securesms.util.TextSecurePreferences;
 import org.whispersystems.libsignal.IdentityKey;
 import org.whispersystems.libsignal.util.guava.Optional;
 import org.whispersystems.signalservice.api.SignalServiceMessageSender;
+import org.whispersystems.signalservice.api.crypto.UnidentifiedAccess;
+import org.whispersystems.signalservice.api.crypto.UnidentifiedAccessPair;
 import org.whispersystems.signalservice.api.crypto.UntrustedIdentityException;
 import org.whispersystems.signalservice.api.messages.SignalServiceAttachment;
 import org.whispersystems.signalservice.api.messages.SignalServiceAttachmentStream;
@@ -285,9 +287,12 @@ public class MultiDeviceContactUpdateJob extends BaseJob implements InjectableTy
                                                                                 .build();
 
       SignalServiceAddress messageRecipient = recipient != null ? new SignalServiceAddress(recipient) : null;
+      Address address = recipient != null ? Address.fromSerialized(recipient) : null;
+
+      Optional<UnidentifiedAccessPair> unidentifiedAccess = address != null ? UnidentifiedAccessUtil.getAccessFor(context, Recipient.from(context, address, false)) : Optional.absent();
 
       try {
-        messageSender.sendMessage(0, SignalServiceSyncMessage.forContacts(new ContactsMessage(attachmentStream, complete)), messageRecipient);
+        messageSender.sendMessage(0, SignalServiceSyncMessage.forContacts(new ContactsMessage(attachmentStream, complete)), unidentifiedAccess, Optional.fromNullable(messageRecipient));
       } catch (IOException ioe) {
         throw new NetworkException(ioe);
       }
diff --git a/src/org/thoughtcrime/securesms/loki/PushMessageSyncSendJob.kt b/src/org/thoughtcrime/securesms/loki/PushMessageSyncSendJob.kt
index f18e941fda..87d19cf9c2 100644
--- a/src/org/thoughtcrime/securesms/loki/PushMessageSyncSendJob.kt
+++ b/src/org/thoughtcrime/securesms/loki/PushMessageSyncSendJob.kt
@@ -1,11 +1,13 @@
 package org.thoughtcrime.securesms.loki
 
+import org.thoughtcrime.securesms.crypto.UnidentifiedAccessUtil
 import org.thoughtcrime.securesms.database.Address
 import org.thoughtcrime.securesms.dependencies.InjectableType
 import org.thoughtcrime.securesms.jobmanager.Data
 import org.thoughtcrime.securesms.jobmanager.Job
 import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint
 import org.thoughtcrime.securesms.jobs.BaseJob
+import org.thoughtcrime.securesms.recipients.Recipient
 import org.whispersystems.signalservice.api.SignalServiceMessageSender
 import org.whispersystems.signalservice.api.crypto.UntrustedIdentityException
 import org.whispersystems.signalservice.api.push.SignalServiceAddress
@@ -63,7 +65,8 @@ class PushMessageSyncSendJob private constructor(
   public override fun onRun() {
     // Don't send sync messages to a group
     if (recipient.isGroup || recipient.isEmail) { return }
-    messageSender.lokiSendSyncMessage(messageID, SignalServiceAddress(recipient.toPhoneString()), timestamp, message, ttl)
+    val unidentifiedAccess = UnidentifiedAccessUtil.getAccessFor(context, Recipient.from(context, recipient, false))
+    messageSender.lokiSendSyncMessage(messageID, SignalServiceAddress(recipient.toPhoneString()), unidentifiedAccess, timestamp, message, ttl)
   }
 
   public override fun onShouldRetry(e: Exception): Boolean {
diff --git a/src/org/thoughtcrime/securesms/recipients/Recipient.java b/src/org/thoughtcrime/securesms/recipients/Recipient.java
index ec0b3a8410..8e61e4900c 100644
--- a/src/org/thoughtcrime/securesms/recipients/Recipient.java
+++ b/src/org/thoughtcrime/securesms/recipients/Recipient.java
@@ -101,7 +101,7 @@ public class Recipient implements RecipientModifiedListener {
   private           String         notificationChannel;
   private           boolean        forceSmsSelection;
 
-  private @NonNull  UnidentifiedAccessMode unidentifiedAccessMode = UnidentifiedAccessMode.DISABLED;
+  private @NonNull  UnidentifiedAccessMode unidentifiedAccessMode = UnidentifiedAccessMode.ENABLED;
 
   @SuppressWarnings("ConstantConditions")
   public static @NonNull Recipient from(@NonNull Context context, @NonNull Address address, boolean asynchronous) {
diff --git a/src/org/thoughtcrime/securesms/util/TextSecurePreferences.java b/src/org/thoughtcrime/securesms/util/TextSecurePreferences.java
index e6729ff233..d2a9ae3364 100644
--- a/src/org/thoughtcrime/securesms/util/TextSecurePreferences.java
+++ b/src/org/thoughtcrime/securesms/util/TextSecurePreferences.java
@@ -601,7 +601,9 @@ public class TextSecurePreferences {
   }
 
   public static boolean isUnidentifiedDeliveryEnabled(Context context) {
-    return getBooleanPreference(context, UNIDENTIFIED_DELIVERY_ENABLED, true);
+    // Loki - Always enable unidentified sender
+    return true;
+    // return getBooleanPreference(context, UNIDENTIFIED_DELIVERY_ENABLED, true);
   }
 
   public static long getSignedPreKeyRotationTime(Context context) {