WIP: clean up signal protocol

This commit is contained in:
Ryan ZHAO 2021-02-19 16:06:10 +11:00
parent 8cc78e8f4c
commit b34809f4d5
20 changed files with 93 additions and 462 deletions

View File

@ -7,90 +7,57 @@ import androidx.annotation.Nullable;
import androidx.annotation.WorkerThread; import androidx.annotation.WorkerThread;
import org.session.libsignal.metadata.SignalProtos; import org.session.libsignal.metadata.SignalProtos;
import org.session.libsignal.metadata.certificate.CertificateValidator;
import org.session.libsignal.metadata.certificate.InvalidCertificateException;
import org.session.libsignal.utilities.logging.Log; import org.session.libsignal.utilities.logging.Log;
import org.session.libsession.messaging.threads.recipients.Recipient; import org.session.libsession.messaging.threads.recipients.Recipient;
import org.session.libsession.utilities.TextSecurePreferences; import org.session.libsession.utilities.TextSecurePreferences;
import org.session.libsession.utilities.Util; import org.session.libsession.utilities.Util;
import org.session.libsignal.libsignal.util.guava.Optional; import org.session.libsignal.libsignal.util.guava.Optional;
import org.session.libsignal.service.api.crypto.UnidentifiedAccess; import org.session.libsignal.service.api.crypto.UnidentifiedAccess;
import org.session.libsignal.service.api.crypto.UnidentifiedAccessPair;
import org.session.libsignal.service.api.push.SignalServiceAddress; import org.session.libsignal.service.api.push.SignalServiceAddress;
public class UnidentifiedAccessUtil { public class UnidentifiedAccessUtil {
private static final String TAG = UnidentifiedAccessUtil.class.getSimpleName(); private static final String TAG = UnidentifiedAccessUtil.class.getSimpleName();
public static CertificateValidator getCertificateValidator() {
return new CertificateValidator();
}
@WorkerThread @WorkerThread
public static Optional<UnidentifiedAccessPair> getAccessFor(@NonNull Context context, public static Optional<UnidentifiedAccess> getAccessFor(@NonNull Context context,
@NonNull Recipient recipient) @NonNull Recipient recipient)
{ {
if (!TextSecurePreferences.isUnidentifiedDeliveryEnabled(context)) { byte[] theirUnidentifiedAccessKey = getTargetUnidentifiedAccessKey(recipient);
Log.i(TAG, "Unidentified delivery is disabled. [other]"); byte[] ourUnidentifiedAccessKey = getSelfUnidentifiedAccessKey(context);
return Optional.absent(); byte[] ourUnidentifiedAccessCertificate = getUnidentifiedAccessCertificate(context);
if (TextSecurePreferences.isUniversalUnidentifiedAccess(context)) {
ourUnidentifiedAccessKey = Util.getSecretBytes(16);
} }
try { Log.i(TAG, "Their access key present? " + (theirUnidentifiedAccessKey != null) +
byte[] theirUnidentifiedAccessKey = getTargetUnidentifiedAccessKey(recipient); " | Our access key present? " + (ourUnidentifiedAccessKey != null) +
byte[] ourUnidentifiedAccessKey = getSelfUnidentifiedAccessKey(context); " | Our certificate present? " + (ourUnidentifiedAccessCertificate != null));
byte[] ourUnidentifiedAccessCertificate = getUnidentifiedAccessCertificate(context);
if (TextSecurePreferences.isUniversalUnidentifiedAccess(context)) { if (theirUnidentifiedAccessKey != null &&
ourUnidentifiedAccessKey = Util.getSecretBytes(16); ourUnidentifiedAccessKey != null &&
} ourUnidentifiedAccessCertificate != null)
{
Log.i(TAG, "Their access key present? " + (theirUnidentifiedAccessKey != null) + return Optional.of(new UnidentifiedAccess(theirUnidentifiedAccessKey));
" | Our access key present? " + (ourUnidentifiedAccessKey != null) +
" | Our certificate present? " + (ourUnidentifiedAccessCertificate != null));
if (theirUnidentifiedAccessKey != null &&
ourUnidentifiedAccessKey != null &&
ourUnidentifiedAccessCertificate != null)
{
return Optional.of(new UnidentifiedAccessPair(new UnidentifiedAccess(theirUnidentifiedAccessKey,
ourUnidentifiedAccessCertificate),
new UnidentifiedAccess(ourUnidentifiedAccessKey,
ourUnidentifiedAccessCertificate)));
}
return Optional.absent();
} catch (InvalidCertificateException e) {
Log.w(TAG, e);
return Optional.absent();
} }
return Optional.absent();
} }
public static Optional<UnidentifiedAccessPair> getAccessForSync(@NonNull Context context) { public static Optional<UnidentifiedAccess> getAccessForSync(@NonNull Context context) {
if (!TextSecurePreferences.isUnidentifiedDeliveryEnabled(context)) { byte[] ourUnidentifiedAccessKey = getSelfUnidentifiedAccessKey(context);
Log.i(TAG, "Unidentified delivery is disabled. [self]"); byte[] ourUnidentifiedAccessCertificate = getUnidentifiedAccessCertificate(context);
return Optional.absent();
if (TextSecurePreferences.isUniversalUnidentifiedAccess(context)) {
ourUnidentifiedAccessKey = Util.getSecretBytes(16);
} }
try { if (ourUnidentifiedAccessKey != null && ourUnidentifiedAccessCertificate != null) {
byte[] ourUnidentifiedAccessKey = getSelfUnidentifiedAccessKey(context); return Optional.of(new UnidentifiedAccess(ourUnidentifiedAccessKey));
byte[] ourUnidentifiedAccessCertificate = getUnidentifiedAccessCertificate(context);
if (TextSecurePreferences.isUniversalUnidentifiedAccess(context)) {
ourUnidentifiedAccessKey = Util.getSecretBytes(16);
}
if (ourUnidentifiedAccessKey != null && ourUnidentifiedAccessCertificate != null) {
return Optional.of(new UnidentifiedAccessPair(new UnidentifiedAccess(ourUnidentifiedAccessKey,
ourUnidentifiedAccessCertificate),
new UnidentifiedAccess(ourUnidentifiedAccessKey,
ourUnidentifiedAccessCertificate)));
}
return Optional.absent();
} catch (InvalidCertificateException e) {
Log.w(TAG, e);
return Optional.absent();
} }
return Optional.absent();
} }
public static @NonNull byte[] getSelfUnidentifiedAccessKey(@NonNull Context context) { public static @NonNull byte[] getSelfUnidentifiedAccessKey(@NonNull Context context) {

View File

@ -16,6 +16,7 @@ import org.session.libsession.messaging.threads.Address;
import org.session.libsession.utilities.GroupUtil; import org.session.libsession.utilities.GroupUtil;
import org.session.libsession.utilities.TextSecurePreferences; import org.session.libsession.utilities.TextSecurePreferences;
import org.session.libsignal.service.api.crypto.UnidentifiedAccess;
import org.session.libsignal.service.internal.push.SignalServiceProtos; import org.session.libsignal.service.internal.push.SignalServiceProtos;
import org.thoughtcrime.securesms.ApplicationContext; import org.thoughtcrime.securesms.ApplicationContext;
import org.thoughtcrime.securesms.crypto.UnidentifiedAccessUtil; import org.thoughtcrime.securesms.crypto.UnidentifiedAccessUtil;
@ -37,7 +38,6 @@ import org.thoughtcrime.securesms.transport.RetryLaterException;
import org.thoughtcrime.securesms.transport.UndeliverableMessageException; import org.thoughtcrime.securesms.transport.UndeliverableMessageException;
import org.session.libsignal.libsignal.util.guava.Optional; import org.session.libsignal.libsignal.util.guava.Optional;
import org.session.libsignal.service.api.SignalServiceMessageSender; import org.session.libsignal.service.api.SignalServiceMessageSender;
import org.session.libsignal.service.api.crypto.UnidentifiedAccessPair;
import org.session.libsignal.service.api.crypto.UntrustedIdentityException; import org.session.libsignal.service.api.crypto.UntrustedIdentityException;
import org.session.libsignal.service.api.messages.SendMessageResult; import org.session.libsignal.service.api.messages.SendMessageResult;
import org.session.libsignal.service.api.messages.SignalServiceAttachment; import org.session.libsignal.service.api.messages.SignalServiceAttachment;
@ -236,7 +236,7 @@ public class PushGroupSendJob extends PushSendJob implements InjectableType {
Address address = message.getRecipient().getAddress(); Address address = message.getRecipient().getAddress();
List<SignalServiceAddress> addresses = Stream.of(destinations).map(this::getPushAddress).toList(); List<SignalServiceAddress> addresses = Stream.of(destinations).map(this::getPushAddress).toList();
List<Optional<UnidentifiedAccessPair>> unidentifiedAccess = Stream.of(addresses) List<Optional<UnidentifiedAccess>> unidentifiedAccess = Stream.of(addresses)
.map(a -> Address.fromSerialized(a.getNumber())) .map(a -> Address.fromSerialized(a.getNumber()))
.map(a -> Recipient.from(context, a, false)) .map(a -> Recipient.from(context, a, false))
.map(recipient -> UnidentifiedAccessUtil.getAccessFor(context, recipient)) .map(recipient -> UnidentifiedAccessUtil.getAccessFor(context, recipient))

View File

@ -13,6 +13,7 @@ import org.session.libsession.messaging.sending_receiving.attachments.DatabaseAt
import org.session.libsession.messaging.threads.recipients.Recipient.UnidentifiedAccessMode; import org.session.libsession.messaging.threads.recipients.Recipient.UnidentifiedAccessMode;
import org.session.libsession.utilities.TextSecurePreferences; import org.session.libsession.utilities.TextSecurePreferences;
import org.session.libsignal.service.api.crypto.UnidentifiedAccess;
import org.thoughtcrime.securesms.ApplicationContext; import org.thoughtcrime.securesms.ApplicationContext;
import org.thoughtcrime.securesms.crypto.UnidentifiedAccessUtil; import org.thoughtcrime.securesms.crypto.UnidentifiedAccessUtil;
import org.thoughtcrime.securesms.database.DatabaseFactory; import org.thoughtcrime.securesms.database.DatabaseFactory;
@ -33,7 +34,6 @@ import org.thoughtcrime.securesms.transport.RetryLaterException;
import org.thoughtcrime.securesms.transport.UndeliverableMessageException; import org.thoughtcrime.securesms.transport.UndeliverableMessageException;
import org.session.libsignal.libsignal.util.guava.Optional; import org.session.libsignal.libsignal.util.guava.Optional;
import org.session.libsignal.service.api.SignalServiceMessageSender; import org.session.libsignal.service.api.SignalServiceMessageSender;
import org.session.libsignal.service.api.crypto.UnidentifiedAccessPair;
import org.session.libsignal.service.api.crypto.UntrustedIdentityException; import org.session.libsignal.service.api.crypto.UntrustedIdentityException;
import org.session.libsignal.service.api.messages.SendMessageResult; import org.session.libsignal.service.api.messages.SendMessageResult;
import org.session.libsignal.service.api.messages.SignalServiceAttachment; import org.session.libsignal.service.api.messages.SignalServiceAttachment;
@ -181,17 +181,15 @@ public class PushMediaSendJob extends PushSendJob implements InjectableType {
DatabaseFactory.getMmsSmsDatabase(context).incrementReadReceiptCount(id, System.currentTimeMillis()); DatabaseFactory.getMmsSmsDatabase(context).incrementReadReceiptCount(id, System.currentTimeMillis());
} }
if (TextSecurePreferences.isUnidentifiedDeliveryEnabled(context)) { if (unidentified && accessMode == UnidentifiedAccessMode.UNKNOWN && profileKey == null) {
if (unidentified && accessMode == UnidentifiedAccessMode.UNKNOWN && profileKey == null) { log(TAG, "Marking recipient as UD-unrestricted following a UD send.");
log(TAG, "Marking recipient as UD-unrestricted following a UD send."); DatabaseFactory.getRecipientDatabase(context).setUnidentifiedAccessMode(recipient, UnidentifiedAccessMode.UNRESTRICTED);
DatabaseFactory.getRecipientDatabase(context).setUnidentifiedAccessMode(recipient, UnidentifiedAccessMode.UNRESTRICTED); } else if (unidentified && accessMode == UnidentifiedAccessMode.UNKNOWN) {
} else if (unidentified && accessMode == UnidentifiedAccessMode.UNKNOWN) { log(TAG, "Marking recipient as UD-enabled following a UD send.");
log(TAG, "Marking recipient as UD-enabled following a UD send."); DatabaseFactory.getRecipientDatabase(context).setUnidentifiedAccessMode(recipient, UnidentifiedAccessMode.ENABLED);
DatabaseFactory.getRecipientDatabase(context).setUnidentifiedAccessMode(recipient, UnidentifiedAccessMode.ENABLED); } else if (!unidentified && accessMode != UnidentifiedAccessMode.DISABLED) {
} else if (!unidentified && accessMode != UnidentifiedAccessMode.DISABLED) { log(TAG, "Marking recipient as UD-disabled following a non-UD send.");
log(TAG, "Marking recipient as UD-disabled following a non-UD send."); DatabaseFactory.getRecipientDatabase(context).setUnidentifiedAccessMode(recipient, UnidentifiedAccessMode.DISABLED);
DatabaseFactory.getRecipientDatabase(context).setUnidentifiedAccessMode(recipient, UnidentifiedAccessMode.DISABLED);
}
} }
if (messageId > 0 && message.getExpiresIn() > 0 && !message.isExpirationUpdate()) { if (messageId > 0 && message.getExpiresIn() > 0 && !message.isExpirationUpdate()) {
@ -207,12 +205,6 @@ public class PushMediaSendJob extends PushSendJob implements InjectableType {
database.markAsPendingInsecureSmsFallback(messageId); database.markAsPendingInsecureSmsFallback(messageId);
notifyMediaMessageDeliveryFailed(context, messageId); notifyMediaMessageDeliveryFailed(context, messageId);
} }
} catch (UntrustedIdentityException uie) {
warn(TAG, "Failure", uie);
if (messageId >= 0) {
database.addMismatchedIdentity(messageId, Address.fromSerialized(uie.getE164Number()), uie.getIdentityKey());
database.markAsSentFailed(messageId);
}
} catch (SnodeAPI.Error e) { } catch (SnodeAPI.Error e) {
Log.d("Loki", "Couldn't send message due to error: " + e.getDescription()); Log.d("Loki", "Couldn't send message due to error: " + e.getDescription());
if (messageId >= 0) { if (messageId >= 0) {
@ -238,8 +230,7 @@ public class PushMediaSendJob extends PushSendJob implements InjectableType {
} }
private boolean deliver(OutgoingMediaMessage message) private boolean deliver(OutgoingMediaMessage message)
throws RetryLaterException, InsecureFallbackApprovalException, UntrustedIdentityException, throws RetryLaterException, InsecureFallbackApprovalException, UndeliverableMessageException, SnodeAPI.Error
UndeliverableMessageException, SnodeAPI.Error
{ {
try { try {
Recipient recipient = Recipient.from(context, destination, false); Recipient recipient = Recipient.from(context, destination, false);
@ -250,11 +241,10 @@ public class PushMediaSendJob extends PushSendJob implements InjectableType {
List<SignalServiceAttachment> serviceAttachments = getAttachmentPointersFor(attachments); List<SignalServiceAttachment> serviceAttachments = getAttachmentPointersFor(attachments);
Optional<byte[]> profileKey = getProfileKey(message.getRecipient()); Optional<byte[]> profileKey = getProfileKey(message.getRecipient());
Optional<SignalServiceDataMessage.Quote> quote = getQuoteFor(message); Optional<SignalServiceDataMessage.Quote> quote = getQuoteFor(message);
Optional<SignalServiceDataMessage.Sticker> sticker = getStickerFor(message);
List<SharedContact> sharedContacts = getSharedContactsFor(message); List<SharedContact> sharedContacts = getSharedContactsFor(message);
List<Preview> previews = getPreviewsFor(message); List<Preview> previews = getPreviewsFor(message);
Optional<UnidentifiedAccessPair> unidentifiedAccessPair = UnidentifiedAccessUtil.getAccessFor(context, recipient); Optional<UnidentifiedAccess> unidentifiedAccessPair = UnidentifiedAccessUtil.getAccessFor(context, recipient);
SignalServiceDataMessage mediaMessage = SignalServiceDataMessage.newBuilder() SignalServiceDataMessage mediaMessage = SignalServiceDataMessage.newBuilder()
.withBody(message.getBody()) .withBody(message.getBody())
@ -298,7 +288,7 @@ public class PushMediaSendJob extends PushSendJob implements InjectableType {
try { try {
// send to ourselves to sync multi-device // send to ourselves to sync multi-device
Optional<UnidentifiedAccessPair> syncAccess = UnidentifiedAccessUtil.getAccessForSync(context); Optional<UnidentifiedAccess> syncAccess = UnidentifiedAccessUtil.getAccessForSync(context);
SendMessageResult selfSendResult = messageSender.sendMessage(messageId, localAddress, syncAccess, mediaSelfSendMessage); SendMessageResult selfSendResult = messageSender.sendMessage(messageId, localAddress, syncAccess, mediaSelfSendMessage);
if (selfSendResult.getLokiAPIError() != null) { if (selfSendResult.getLokiAPIError() != null) {
throw selfSendResult.getLokiAPIError(); throw selfSendResult.getLokiAPIError();

View File

@ -26,7 +26,6 @@ import org.thoughtcrime.securesms.transport.InsecureFallbackApprovalException;
import org.thoughtcrime.securesms.transport.RetryLaterException; import org.thoughtcrime.securesms.transport.RetryLaterException;
import org.session.libsignal.libsignal.util.guava.Optional; import org.session.libsignal.libsignal.util.guava.Optional;
import org.session.libsignal.service.api.SignalServiceMessageSender; import org.session.libsignal.service.api.SignalServiceMessageSender;
import org.session.libsignal.service.api.crypto.UnidentifiedAccessPair;
import org.session.libsignal.service.api.crypto.UntrustedIdentityException; import org.session.libsignal.service.api.crypto.UntrustedIdentityException;
import org.session.libsignal.service.api.messages.SendMessageResult; import org.session.libsignal.service.api.messages.SendMessageResult;
import org.session.libsignal.service.api.messages.SignalServiceDataMessage; import org.session.libsignal.service.api.messages.SignalServiceDataMessage;
@ -124,17 +123,15 @@ public class PushTextSendJob extends PushSendJob implements InjectableType {
DatabaseFactory.getMmsSmsDatabase(context).incrementReadReceiptCount(id, System.currentTimeMillis()); DatabaseFactory.getMmsSmsDatabase(context).incrementReadReceiptCount(id, System.currentTimeMillis());
} }
if (TextSecurePreferences.isUnidentifiedDeliveryEnabled(context)) { if (unidentified && accessMode == UnidentifiedAccessMode.UNKNOWN && profileKey == null) {
if (unidentified && accessMode == UnidentifiedAccessMode.UNKNOWN && profileKey == null) { log(TAG, "Marking recipient as UD-unrestricted following a UD send.");
log(TAG, "Marking recipient as UD-unrestricted following a UD send."); DatabaseFactory.getRecipientDatabase(context).setUnidentifiedAccessMode(recipient, UnidentifiedAccessMode.UNRESTRICTED);
DatabaseFactory.getRecipientDatabase(context).setUnidentifiedAccessMode(recipient, UnidentifiedAccessMode.UNRESTRICTED); } else if (unidentified && accessMode == UnidentifiedAccessMode.UNKNOWN) {
} else if (unidentified && accessMode == UnidentifiedAccessMode.UNKNOWN) { log(TAG, "Marking recipient as UD-enabled following a UD send.");
log(TAG, "Marking recipient as UD-enabled following a UD send."); DatabaseFactory.getRecipientDatabase(context).setUnidentifiedAccessMode(recipient, UnidentifiedAccessMode.ENABLED);
DatabaseFactory.getRecipientDatabase(context).setUnidentifiedAccessMode(recipient, UnidentifiedAccessMode.ENABLED); } else if (!unidentified && accessMode != UnidentifiedAccessMode.DISABLED) {
} else if (!unidentified && accessMode != UnidentifiedAccessMode.DISABLED) { log(TAG, "Marking recipient as UD-disabled following a non-UD send.");
log(TAG, "Marking recipient as UD-disabled following a non-UD send."); DatabaseFactory.getRecipientDatabase(context).setUnidentifiedAccessMode(recipient, UnidentifiedAccessMode.DISABLED);
DatabaseFactory.getRecipientDatabase(context).setUnidentifiedAccessMode(recipient, UnidentifiedAccessMode.DISABLED);
}
} }
if (record.getExpiresIn() > 0 && messageId >= 0) { if (record.getExpiresIn() > 0 && messageId >= 0) {
@ -196,15 +193,10 @@ public class PushTextSendJob extends PushSendJob implements InjectableType {
SignalServiceAddress address = getPushAddress(recipient.getAddress()); SignalServiceAddress address = getPushAddress(recipient.getAddress());
SignalServiceAddress localAddress = new SignalServiceAddress(userPublicKey); SignalServiceAddress localAddress = new SignalServiceAddress(userPublicKey);
Optional<byte[]> profileKey = getProfileKey(recipient); Optional<byte[]> profileKey = getProfileKey(recipient);
Optional<UnidentifiedAccessPair> unidentifiedAccess = UnidentifiedAccessUtil.getAccessFor(context, recipient); Optional<UnidentifiedAccess> unidentifiedAccess = UnidentifiedAccessUtil.getAccessFor(context, recipient);
log(TAG, "Have access key to use: " + unidentifiedAccess.isPresent()); log(TAG, "Have access key to use: " + unidentifiedAccess.isPresent());
// PreKeyBundle preKeyBundle = null;
// if (message.isEndSession()) {
// preKeyBundle = DatabaseFactory.getLokiPreKeyBundleDatabase(context).generatePreKeyBundle(destination.serialize());
// }
SignalServiceDataMessage textSecureMessage = SignalServiceDataMessage.newBuilder() SignalServiceDataMessage textSecureMessage = SignalServiceDataMessage.newBuilder()
.withTimestamp(message.getDateSent()) .withTimestamp(message.getDateSent())
.withBody(message.getBody()) .withBody(message.getBody())
@ -237,7 +229,7 @@ public class PushTextSendJob extends PushSendJob implements InjectableType {
try { try {
// send to ourselves to sync multi-device // send to ourselves to sync multi-device
Optional<UnidentifiedAccessPair> syncAccess = UnidentifiedAccessUtil.getAccessForSync(context); Optional<UnidentifiedAccess> syncAccess = UnidentifiedAccessUtil.getAccessForSync(context);
SendMessageResult selfSendResult = messageSender.sendMessage(messageId, localAddress, syncAccess, textSecureSelfSendMessage); SendMessageResult selfSendResult = messageSender.sendMessage(messageId, localAddress, syncAccess, textSecureSelfSendMessage);
if (selfSendResult.getLokiAPIError() != null) { if (selfSendResult.getLokiAPIError() != null) {
throw selfSendResult.getLokiAPIError(); throw selfSendResult.getLokiAPIError();

View File

@ -5,20 +5,19 @@ import androidx.annotation.NonNull;
import com.annimon.stream.Stream; import com.annimon.stream.Stream;
import org.session.libsession.messaging.jobs.Data; import org.session.libsession.messaging.jobs.Data;
import org.session.libsignal.libsignal.util.guava.Optional;
import org.session.libsignal.service.api.crypto.UnidentifiedAccess;
import org.thoughtcrime.securesms.crypto.UnidentifiedAccessUtil; import org.thoughtcrime.securesms.crypto.UnidentifiedAccessUtil;
import org.thoughtcrime.securesms.database.DatabaseFactory; import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.dependencies.InjectableType; import org.thoughtcrime.securesms.dependencies.InjectableType;
import org.thoughtcrime.securesms.jobmanager.Job; import org.thoughtcrime.securesms.jobmanager.Job;
import org.session.libsignal.utilities.logging.Log; import org.session.libsignal.utilities.logging.Log;
import org.session.libsignal.libsignal.util.guava.Optional;
import org.session.libsignal.service.api.SignalServiceMessageSender; import org.session.libsignal.service.api.SignalServiceMessageSender;
import org.session.libsignal.service.api.crypto.UnidentifiedAccessPair;
import org.session.libsignal.service.api.messages.SignalServiceTypingMessage; import org.session.libsignal.service.api.messages.SignalServiceTypingMessage;
import org.session.libsignal.service.api.messages.SignalServiceTypingMessage.Action; import org.session.libsignal.service.api.messages.SignalServiceTypingMessage.Action;
import org.session.libsignal.service.api.push.SignalServiceAddress; import org.session.libsignal.service.api.push.SignalServiceAddress;
import org.session.libsession.messaging.threads.recipients.Recipient; import org.session.libsession.messaging.threads.recipients.Recipient;
import org.session.libsession.utilities.GroupUtil;
import org.session.libsession.utilities.TextSecurePreferences; import org.session.libsession.utilities.TextSecurePreferences;
import java.util.Collections; import java.util.Collections;
@ -93,7 +92,7 @@ public class TypingSendJob extends BaseJob implements InjectableType {
} }
List<SignalServiceAddress> addresses = Stream.of(recipients).map(r -> new SignalServiceAddress(r.getAddress().serialize())).toList(); List<SignalServiceAddress> addresses = Stream.of(recipients).map(r -> new SignalServiceAddress(r.getAddress().serialize())).toList();
List<Optional<UnidentifiedAccessPair>> unidentifiedAccess = Stream.of(recipients).map(r -> UnidentifiedAccessUtil.getAccessFor(context, r)).toList(); List<Optional<UnidentifiedAccess>> unidentifiedAccess = Stream.of(recipients).map(r -> UnidentifiedAccessUtil.getAccessFor(context, r)).toList();
SignalServiceTypingMessage typingMessage = new SignalServiceTypingMessage(typing ? Action.STARTED : Action.STOPPED, System.currentTimeMillis()); SignalServiceTypingMessage typingMessage = new SignalServiceTypingMessage(typing ? Action.STARTED : Action.STOPPED, System.currentTimeMillis());
messageSender.sendTyping(addresses, unidentifiedAccess, typingMessage); messageSender.sendTyping(addresses, unidentifiedAccess, typingMessage);

View File

@ -223,7 +223,7 @@ class ClosedGroupUpdateMessageSendJobV2 private constructor(parameters: Paramete
} }
try { try {
// isClosedGroup can always be false as it's only used in the context of legacy closed groups // isClosedGroup can always be false as it's only used in the context of legacy closed groups
messageSender.sendMessage(0, address, udAccess.get().targetUnidentifiedAccess, messageSender.sendMessage(0, address, udAccess,
sentTime, serializedContentMessage, false, ttl, sentTime, serializedContentMessage, false, ttl,
true, false, false, Optional.absent()) true, false, false, Optional.absent())
} catch (e: Exception) { } catch (e: Exception) {

View File

@ -34,7 +34,7 @@ object MultiDeviceProtocol {
val recipient = recipient(context, userPublicKey) val recipient = recipient(context, userPublicKey)
val udAccess = UnidentifiedAccessUtil.getAccessFor(context, recipient) val udAccess = UnidentifiedAccessUtil.getAccessFor(context, recipient)
try { try {
messageSender.sendMessage(0, address, udAccess.get().targetUnidentifiedAccess, messageSender.sendMessage(0, address, udAccess,
Date().time, serializedMessage, false, configurationMessage.ttl.toInt(), Date().time, serializedMessage, false, configurationMessage.ttl.toInt(),
true, false, true, Optional.absent()) true, false, true, Optional.absent())
TextSecurePreferences.setLastConfigurationSyncTime(context, now) TextSecurePreferences.setLastConfigurationSyncTime(context, now)
@ -53,7 +53,7 @@ object MultiDeviceProtocol {
val recipient = recipient(context, userPublicKey) val recipient = recipient(context, userPublicKey)
val udAccess = UnidentifiedAccessUtil.getAccessFor(context, recipient) val udAccess = UnidentifiedAccessUtil.getAccessFor(context, recipient)
try { try {
messageSender.sendMessage(0, address, udAccess.get().targetUnidentifiedAccess, messageSender.sendMessage(0, address, udAccess,
Date().time, serializedMessage, false, configurationMessage.ttl.toInt(), Date().time, serializedMessage, false, configurationMessage.ttl.toInt(),
true, false, true, Optional.absent()) true, false, true, Optional.absent())
} catch (e: Exception) { } catch (e: Exception) {

View File

@ -1,39 +1,42 @@
package org.session.libsession.messaging.utilities package org.session.libsession.messaging.utilities
import android.content.Context
import com.goterl.lazycode.lazysodium.LazySodiumAndroid import com.goterl.lazycode.lazysodium.LazySodiumAndroid
import com.goterl.lazycode.lazysodium.SodiumAndroid import com.goterl.lazycode.lazysodium.SodiumAndroid
import org.session.libsession.messaging.MessagingConfiguration import org.session.libsession.messaging.MessagingConfiguration
import org.session.libsession.utilities.TextSecurePreferences.isUniversalUnidentifiedAccess
import org.session.libsignal.utilities.logging.Log import org.session.libsession.utilities.Util.getSecretBytes
import org.session.libsignal.metadata.SignalProtos import org.session.libsignal.metadata.SignalProtos
import org.session.libsignal.metadata.certificate.InvalidCertificateException
import org.session.libsignal.service.api.crypto.UnidentifiedAccess import org.session.libsignal.service.api.crypto.UnidentifiedAccess
import org.session.libsignal.service.api.crypto.UnidentifiedAccessPair import org.session.libsignal.utilities.logging.Log
object UnidentifiedAccessUtil { object UnidentifiedAccessUtil {
private val TAG = UnidentifiedAccessUtil::class.simpleName private val TAG = UnidentifiedAccessUtil::class.simpleName
private val sodium by lazy { LazySodiumAndroid(SodiumAndroid()) } private val sodium by lazy { LazySodiumAndroid(SodiumAndroid()) }
fun getAccessFor(recipientPublicKey: String): UnidentifiedAccessPair? { fun getAccessFor(recipientPublicKey: String): UnidentifiedAccess? {
try { val theirUnidentifiedAccessKey = getTargetUnidentifiedAccessKey(recipientPublicKey)
val theirUnidentifiedAccessKey = getTargetUnidentifiedAccessKey(recipientPublicKey) val ourUnidentifiedAccessKey = getSelfUnidentifiedAccessKey()
val ourUnidentifiedAccessKey = getSelfUnidentifiedAccessKey() val ourUnidentifiedAccessCertificate = getUnidentifiedAccessCertificate()
val ourUnidentifiedAccessCertificate = getUnidentifiedAccessCertificate()
Log.i(TAG, "Their access key present? " + (theirUnidentifiedAccessKey != null) + Log.i(TAG, "Their access key present? " + (theirUnidentifiedAccessKey != null) +
" | Our access key present? " + (ourUnidentifiedAccessKey != null) + " | Our access key present? " + (ourUnidentifiedAccessKey != null) +
" | Our certificate present? " + (ourUnidentifiedAccessCertificate != null)) " | Our certificate present? " + (ourUnidentifiedAccessCertificate != null))
if (theirUnidentifiedAccessKey != null && ourUnidentifiedAccessKey != null && ourUnidentifiedAccessCertificate != null) { return if (theirUnidentifiedAccessKey != null && ourUnidentifiedAccessKey != null && ourUnidentifiedAccessCertificate != null) {
return UnidentifiedAccessPair(UnidentifiedAccess(theirUnidentifiedAccessKey, ourUnidentifiedAccessCertificate), UnidentifiedAccess(theirUnidentifiedAccessKey)
UnidentifiedAccess(ourUnidentifiedAccessKey, ourUnidentifiedAccessCertificate)) } else null
} }
return null
} catch (e: InvalidCertificateException) { fun getAccessForSync(context: Context): UnidentifiedAccess? {
Log.w(TAG, e) var ourUnidentifiedAccessKey = getSelfUnidentifiedAccessKey()
return null val ourUnidentifiedAccessCertificate = getUnidentifiedAccessCertificate()
if (isUniversalUnidentifiedAccess(context)) {
ourUnidentifiedAccessKey = getSecretBytes(16)
} }
return if (ourUnidentifiedAccessKey != null && ourUnidentifiedAccessCertificate != null) {
UnidentifiedAccess(ourUnidentifiedAccessKey)
} else null
} }
private fun getTargetUnidentifiedAccessKey(recipientPublicKey: String): ByteArray? { private fun getTargetUnidentifiedAccessKey(recipientPublicKey: String): ByteArray? {

View File

@ -448,13 +448,6 @@ object TextSecurePreferences {
return getBooleanPreference(context, UNIVERSAL_UNIDENTIFIED_ACCESS, false) return getBooleanPreference(context, UNIVERSAL_UNIDENTIFIED_ACCESS, false)
} }
@JvmStatic
fun isUnidentifiedDeliveryEnabled(context: Context): Boolean {
// Loki - Always enable unidentified sender
return true
// return getBooleanPreference(context, UNIDENTIFIED_DELIVERY_ENABLED, true);
}
@JvmStatic @JvmStatic
fun getUpdateApkRefreshTime(context: Context): Long { fun getUpdateApkRefreshTime(context: Context): Long {
return getLongPreference(context, UPDATE_APK_REFRESH_TIME_PREF, 0L) return getLongPreference(context, UPDATE_APK_REFRESH_TIME_PREF, 0L)

View File

@ -1,50 +0,0 @@
/**
* Copyright (C) 2014-2016 Open Whisper Systems
*
* Licensed according to the LICENSE file in this repository.
*/
package org.session.libsignal.libsignal.kdf;
import org.session.libsignal.libsignal.util.ByteUtil;
import java.text.ParseException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
public class DerivedMessageSecrets {
public static final int SIZE = 80;
private static final int CIPHER_KEY_LENGTH = 32;
private static final int MAC_KEY_LENGTH = 32;
private static final int IV_LENGTH = 16;
private final SecretKeySpec cipherKey;
private final SecretKeySpec macKey;
private final IvParameterSpec iv;
public DerivedMessageSecrets(byte[] okm) {
try {
byte[][] keys = ByteUtil.split(okm, CIPHER_KEY_LENGTH, MAC_KEY_LENGTH, IV_LENGTH);
this.cipherKey = new SecretKeySpec(keys[0], "AES");
this.macKey = new SecretKeySpec(keys[1], "HmacSHA256");
this.iv = new IvParameterSpec(keys[2]);
} catch (ParseException e) {
throw new AssertionError(e);
}
}
public SecretKeySpec getCipherKey() {
return cipherKey;
}
public SecretKeySpec getMacKey() {
return macKey;
}
public IvParameterSpec getIv() {
return iv;
}
}

View File

@ -1,31 +0,0 @@
/**
* Copyright (C) 2014-2016 Open Whisper Systems
*
* Licensed according to the LICENSE file in this repository.
*/
package org.session.libsignal.libsignal.kdf;
import org.session.libsignal.libsignal.util.ByteUtil;
public class DerivedRootSecrets {
public static final int SIZE = 64;
private final byte[] rootKey;
private final byte[] chainKey;
public DerivedRootSecrets(byte[] okm) {
byte[][] keys = ByteUtil.split(okm, 32, 32);
this.rootKey = keys[0];
this.chainKey = keys[1];
}
public byte[] getRootKey() {
return rootKey;
}
public byte[] getChainKey() {
return chainKey;
}
}

View File

@ -6,9 +6,6 @@
package org.session.libsignal.libsignal.kdf; package org.session.libsignal.libsignal.kdf;
import org.session.libsignal.libsignal.kdf.HKDFv2;
import org.session.libsignal.libsignal.kdf.HKDFv3;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.security.InvalidKeyException; import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
@ -22,7 +19,6 @@ public abstract class HKDF {
public static HKDF createFor(int messageVersion) { public static HKDF createFor(int messageVersion) {
switch (messageVersion) { switch (messageVersion) {
case 2: return new HKDFv2();
case 3: return new HKDFv3(); case 3: return new HKDFv3();
default: throw new AssertionError("Unknown version: " + messageVersion); default: throw new AssertionError("Unknown version: " + messageVersion);
} }

View File

@ -1,13 +0,0 @@
/**
* Copyright (C) 2014-2016 Open Whisper Systems
*
* Licensed according to the LICENSE file in this repository.
*/
package org.session.libsignal.libsignal.kdf;
public class HKDFv2 extends HKDF {
@Override
protected int getIterationStartOffset() {
return 0;
}
}

View File

@ -1,24 +0,0 @@
package org.session.libsignal.metadata.certificate;
import java.util.HashSet;
import java.util.Set;
public class CertificateValidator {
@SuppressWarnings("MismatchedQueryAndUpdateOfCollection")
private static final Set<Integer> REVOKED = new HashSet<Integer>() {{
}};
public void validate(SenderCertificate certificate, long validationTime) throws InvalidCertificateException {
if (certificate.getSender() == null || certificate.getSenderDeviceId() <= 0) {
throw new InvalidCertificateException("Sender or sender device id is invalid");
}
}
// VisibleForTesting
void validate(ServerCertificate certificate) throws InvalidCertificateException {
}
}

View File

@ -1,12 +0,0 @@
package org.session.libsignal.metadata.certificate;
public class InvalidCertificateException extends Exception {
public InvalidCertificateException(String s) {
super(s);
}
public InvalidCertificateException(Exception e) {
super(e);
}
}

View File

@ -1,51 +0,0 @@
package org.session.libsignal.metadata.certificate;
import com.google.protobuf.InvalidProtocolBufferException;
import org.session.libsignal.metadata.SignalProtos;
public class SenderCertificate {
private final int senderDeviceId;
private final String sender;
private final byte[] serialized;
private final byte[] certificate;
public SenderCertificate(byte[] serialized) throws InvalidCertificateException {
try {
SignalProtos.SenderCertificate certificate = SignalProtos.SenderCertificate.parseFrom(serialized);
if (!certificate.hasSenderDevice() || !certificate.hasSender()) {
throw new InvalidCertificateException("Missing fields");
}
this.sender = certificate.getSender();
this.senderDeviceId = certificate.getSenderDevice();
this.serialized = serialized;
this.certificate = certificate.toByteArray();
} catch (InvalidProtocolBufferException e) {
throw new InvalidCertificateException(e);
}
}
public int getSenderDeviceId() {
return senderDeviceId;
}
public String getSender() {
return sender;
}
public byte[] getSerialized() {
return serialized;
}
public byte[] getCertificate() {
return certificate;
}
}

View File

@ -1,66 +0,0 @@
package org.session.libsignal.metadata.certificate;
import com.google.protobuf.InvalidProtocolBufferException;
import org.session.libsignal.metadata.SignalProtos;
import org.session.libsignal.libsignal.InvalidKeyException;
import org.session.libsignal.libsignal.ecc.Curve;
import org.session.libsignal.libsignal.ecc.ECPublicKey;
public class ServerCertificate {
private final int keyId;
private final ECPublicKey key;
private final byte[] serialized;
private final byte[] certificate;
private final byte[] signature;
public ServerCertificate(byte[] serialized) throws InvalidCertificateException {
try {
SignalProtos.ServerCertificate wrapper = SignalProtos.ServerCertificate.parseFrom(serialized);
if (!wrapper.hasCertificate() || !wrapper.hasSignature()) {
throw new InvalidCertificateException("Missing fields");
}
SignalProtos.ServerCertificate.Certificate certificate = SignalProtos.ServerCertificate.Certificate.parseFrom(wrapper.getCertificate());
if (!certificate.hasId() || !certificate.hasKey()) {
throw new InvalidCertificateException("Missing fields");
}
this.keyId = certificate.getId();
this.key = Curve.decodePoint(certificate.getKey().toByteArray(), 0);
this.serialized = serialized;
this.certificate = wrapper.getCertificate().toByteArray();
this.signature = wrapper.getSignature().toByteArray();
} catch (InvalidProtocolBufferException e) {
throw new InvalidCertificateException(e);
} catch (InvalidKeyException e) {
throw new InvalidCertificateException(e);
}
}
public int getKeyId() {
return keyId;
}
public ECPublicKey getKey() {
return key;
}
public byte[] getSerialized() {
return serialized;
}
public byte[] getCertificate() {
return certificate;
}
public byte[] getSignature() {
return signature;
}
}

View File

@ -14,7 +14,6 @@ import org.session.libsignal.utilities.logging.Log;
import org.session.libsignal.libsignal.util.guava.Optional; import org.session.libsignal.libsignal.util.guava.Optional;
import org.session.libsignal.service.api.crypto.AttachmentCipherOutputStream; import org.session.libsignal.service.api.crypto.AttachmentCipherOutputStream;
import org.session.libsignal.service.api.crypto.UnidentifiedAccess; import org.session.libsignal.service.api.crypto.UnidentifiedAccess;
import org.session.libsignal.service.api.crypto.UnidentifiedAccessPair;
import org.session.libsignal.service.api.crypto.UntrustedIdentityException; import org.session.libsignal.service.api.crypto.UntrustedIdentityException;
import org.session.libsignal.service.api.messages.SendMessageResult; import org.session.libsignal.service.api.messages.SendMessageResult;
import org.session.libsignal.service.api.messages.SignalServiceAttachment; import org.session.libsignal.service.api.messages.SignalServiceAttachment;
@ -165,21 +164,21 @@ public class SignalServiceMessageSender {
* @throws IOException * @throws IOException
*/ */
public void sendReceipt(SignalServiceAddress recipient, public void sendReceipt(SignalServiceAddress recipient,
Optional<UnidentifiedAccessPair> unidentifiedAccess, Optional<UnidentifiedAccess> unidentifiedAccess,
SignalServiceReceiptMessage message) SignalServiceReceiptMessage message)
throws IOException { throws IOException {
byte[] content = createReceiptContent(message); byte[] content = createReceiptContent(message);
boolean useFallbackEncryption = true; boolean useFallbackEncryption = true;
sendMessage(recipient, getTargetUnidentifiedAccess(unidentifiedAccess), message.getWhen(), content, false, message.getTTL(), useFallbackEncryption); sendMessage(recipient, unidentifiedAccess, message.getWhen(), content, false, message.getTTL(), useFallbackEncryption);
} }
public void sendTyping(List<SignalServiceAddress> recipients, public void sendTyping(List<SignalServiceAddress> recipients,
List<Optional<UnidentifiedAccessPair>> unidentifiedAccess, List<Optional<UnidentifiedAccess>> unidentifiedAccess,
SignalServiceTypingMessage message) SignalServiceTypingMessage message)
throws IOException throws IOException
{ {
byte[] content = createTypingContent(message); byte[] content = createTypingContent(message);
sendMessage(0, recipients, getTargetUnidentifiedAccess(unidentifiedAccess), message.getTimestamp(), content, true, message.getTTL(), false, false); sendMessage(0, recipients, unidentifiedAccess, message.getTimestamp(), content, true, message.getTTL(), false, false);
} }
/** /**
@ -191,14 +190,14 @@ public class SignalServiceMessageSender {
*/ */
public SendMessageResult sendMessage(long messageID, public SendMessageResult sendMessage(long messageID,
SignalServiceAddress recipient, SignalServiceAddress recipient,
Optional<UnidentifiedAccessPair> unidentifiedAccess, Optional<UnidentifiedAccess> unidentifiedAccess,
SignalServiceDataMessage message) SignalServiceDataMessage message)
throws IOException throws IOException
{ {
byte[] content = createMessageContent(message, recipient); byte[] content = createMessageContent(message, recipient);
long timestamp = message.getTimestamp(); long timestamp = message.getTimestamp();
boolean isClosedGroup = message.group.isPresent() && message.group.get().getGroupType() == SignalServiceGroup.GroupType.SIGNAL; boolean isClosedGroup = message.group.isPresent() && message.group.get().getGroupType() == SignalServiceGroup.GroupType.SIGNAL;
SendMessageResult result = sendMessage(messageID, recipient, getTargetUnidentifiedAccess(unidentifiedAccess), timestamp, content, false, message.getTTL(), true, isClosedGroup, message.hasVisibleContent(), message.getSyncTarget()); SendMessageResult result = sendMessage(messageID, recipient, unidentifiedAccess, timestamp, content, false, message.getTTL(), true, isClosedGroup, message.hasVisibleContent(), message.getSyncTarget());
return result; return result;
} }
@ -212,7 +211,7 @@ public class SignalServiceMessageSender {
*/ */
public List<SendMessageResult> sendMessage(long messageID, public List<SendMessageResult> sendMessage(long messageID,
List<SignalServiceAddress> recipients, List<SignalServiceAddress> recipients,
List<Optional<UnidentifiedAccessPair>> unidentifiedAccess, List<Optional<UnidentifiedAccess>> unidentifiedAccess,
SignalServiceDataMessage message) SignalServiceDataMessage message)
throws IOException { throws IOException {
// Loki - We only need the first recipient in the line below. This is because the recipient is only used to determine // Loki - We only need the first recipient in the line below. This is because the recipient is only used to determine
@ -221,7 +220,7 @@ public class SignalServiceMessageSender {
long timestamp = message.getTimestamp(); long timestamp = message.getTimestamp();
boolean isClosedGroup = message.group.isPresent() && message.group.get().getGroupType() == SignalServiceGroup.GroupType.SIGNAL; boolean isClosedGroup = message.group.isPresent() && message.group.get().getGroupType() == SignalServiceGroup.GroupType.SIGNAL;
return sendMessage(messageID, recipients, getTargetUnidentifiedAccess(unidentifiedAccess), timestamp, content, false, message.getTTL(), isClosedGroup, message.hasVisibleContent()); return sendMessage(messageID, recipients, unidentifiedAccess, timestamp, content, false, message.getTTL(), isClosedGroup, message.hasVisibleContent());
} }
public void setMessagePipe(SignalServiceMessagePipe pipe, SignalServiceMessagePipe unidentifiedPipe) { public void setMessagePipe(SignalServiceMessagePipe pipe, SignalServiceMessagePipe unidentifiedPipe) {
@ -885,25 +884,6 @@ public class SignalServiceMessageSender {
return new OutgoingPushMessageList(publicKey, timestamp, messages, false); return new OutgoingPushMessageList(publicKey, timestamp, messages, false);
} }
private Optional<UnidentifiedAccess> getTargetUnidentifiedAccess(Optional<UnidentifiedAccessPair> unidentifiedAccess) {
if (unidentifiedAccess.isPresent()) {
return unidentifiedAccess.get().getTargetUnidentifiedAccess();
}
return Optional.absent();
}
private List<Optional<UnidentifiedAccess>> getTargetUnidentifiedAccess(List<Optional<UnidentifiedAccessPair>> unidentifiedAccess) {
List<Optional<UnidentifiedAccess>> results = new LinkedList<>();
for (Optional<UnidentifiedAccessPair> item : unidentifiedAccess) {
if (item.isPresent()) results.add(item.get().getTargetUnidentifiedAccess());
else results.add(Optional.<UnidentifiedAccess>absent());
}
return results;
}
public static interface EventListener { public static interface EventListener {
public void onSecurityEvent(SignalServiceAddress address); public void onSecurityEvent(SignalServiceAddress address);

View File

@ -1,8 +1,6 @@
package org.session.libsignal.service.api.crypto; package org.session.libsignal.service.api.crypto;
import org.session.libsignal.metadata.certificate.InvalidCertificateException;
import org.session.libsignal.metadata.certificate.SenderCertificate;
import org.session.libsignal.libsignal.util.ByteUtil; import org.session.libsignal.libsignal.util.ByteUtil;
import java.security.InvalidAlgorithmParameterException; import java.security.InvalidAlgorithmParameterException;
@ -19,23 +17,16 @@ import javax.crypto.spec.SecretKeySpec;
public class UnidentifiedAccess { public class UnidentifiedAccess {
private final byte[] unidentifiedAccessKey; private final byte[] unidentifiedAccessKey;
private final SenderCertificate unidentifiedCertificate;
public UnidentifiedAccess(byte[] unidentifiedAccessKey, byte[] unidentifiedCertificate) public UnidentifiedAccess(byte[] unidentifiedAccessKey)
throws InvalidCertificateException
{ {
this.unidentifiedAccessKey = unidentifiedAccessKey; this.unidentifiedAccessKey = unidentifiedAccessKey;
this.unidentifiedCertificate = new SenderCertificate(unidentifiedCertificate);
} }
public byte[] getUnidentifiedAccessKey() { public byte[] getUnidentifiedAccessKey() {
return unidentifiedAccessKey; return unidentifiedAccessKey;
} }
public SenderCertificate getUnidentifiedCertificate() {
return unidentifiedCertificate;
}
public static byte[] deriveAccessKeyFrom(byte[] profileKey) { public static byte[] deriveAccessKeyFrom(byte[] profileKey) {
try { try {
byte[] nonce = new byte[12]; byte[] nonce = new byte[12];
@ -47,17 +38,7 @@ public class UnidentifiedAccess {
byte[] ciphertext = cipher.doFinal(input); byte[] ciphertext = cipher.doFinal(input);
return ByteUtil.trim(ciphertext, 16); return ByteUtil.trim(ciphertext, 16);
} catch (NoSuchAlgorithmException e) { } catch (NoSuchAlgorithmException | InvalidKeyException | NoSuchPaddingException | InvalidAlgorithmParameterException | BadPaddingException | IllegalBlockSizeException e) {
throw new AssertionError(e);
} catch (InvalidKeyException e) {
throw new AssertionError(e);
} catch (NoSuchPaddingException e) {
throw new AssertionError(e);
} catch (InvalidAlgorithmParameterException e) {
throw new AssertionError(e);
} catch (BadPaddingException e) {
throw new AssertionError(e);
} catch (IllegalBlockSizeException e) {
throw new AssertionError(e); throw new AssertionError(e);
} }
} }

View File

@ -1,23 +0,0 @@
package org.session.libsignal.service.api.crypto;
import org.session.libsignal.libsignal.util.guava.Optional;
public class UnidentifiedAccessPair {
private final Optional<UnidentifiedAccess> targetUnidentifiedAccess;
private final Optional<UnidentifiedAccess> selfUnidentifiedAccess;
public UnidentifiedAccessPair(UnidentifiedAccess targetUnidentifiedAccess, UnidentifiedAccess selfUnidentifiedAccess) {
this.targetUnidentifiedAccess = Optional.of(targetUnidentifiedAccess);
this.selfUnidentifiedAccess = Optional.of(selfUnidentifiedAccess);
}
public Optional<UnidentifiedAccess> getTargetUnidentifiedAccess() {
return targetUnidentifiedAccess;
}
public Optional<UnidentifiedAccess> getSelfUnidentifiedAccess() {
return selfUnidentifiedAccess;
}
}