diff --git a/app/src/main/java/org/thoughtcrime/securesms/ApplicationContext.java b/app/src/main/java/org/thoughtcrime/securesms/ApplicationContext.java index 16ee21cabb..2e8294b565 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/ApplicationContext.java +++ b/app/src/main/java/org/thoughtcrime/securesms/ApplicationContext.java @@ -70,7 +70,6 @@ import org.thoughtcrime.securesms.loki.activities.HomeActivity; import org.thoughtcrime.securesms.loki.api.BackgroundPollWorker; import org.thoughtcrime.securesms.loki.api.LokiPushNotificationManager; import org.thoughtcrime.securesms.loki.api.PublicChatManager; -import org.thoughtcrime.securesms.loki.api.SessionProtocolImpl; import org.thoughtcrime.securesms.loki.database.LokiAPIDatabase; import org.thoughtcrime.securesms.loki.database.LokiThreadDatabase; import org.thoughtcrime.securesms.loki.database.LokiUserDatabase; @@ -178,8 +177,7 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc String userPublicKey = TextSecurePreferences.getLocalNumber(this); MessagingModuleConfiguration.Companion.configure(this, DatabaseFactory.getStorage(this), - DatabaseFactory.getAttachmentProvider(this), - new SessionProtocolImpl(this)); + DatabaseFactory.getAttachmentProvider(this)); SnodeModule.Companion.configure(apiDB, broadcaster); if (userPublicKey != null) { MentionsManager.Companion.configureIfNeeded(userPublicKey, userDB); diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt b/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt index 2c82d60aa7..42cb63eb1b 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt @@ -347,7 +347,7 @@ class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context, DatabaseFactory.getLokiAPIDatabase(context).removeLastDeletionServerID(group, server) } - override fun isMessageDuplicated(timestamp: Long, sender: String): Boolean { + override fun isDuplicateMessage(timestamp: Long, sender: String): Boolean { return getReceivedMessageTimestamps().contains(timestamp) } diff --git a/app/src/main/java/org/thoughtcrime/securesms/loki/activities/SettingsActivity.kt b/app/src/main/java/org/thoughtcrime/securesms/loki/activities/SettingsActivity.kt index 077ced7b11..6c6d95511f 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/loki/activities/SettingsActivity.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/loki/activities/SettingsActivity.kt @@ -24,6 +24,7 @@ import network.loki.messenger.R import nl.komponents.kovenant.Promise import nl.komponents.kovenant.all import nl.komponents.kovenant.ui.alwaysUi +import nl.komponents.kovenant.ui.successUi import org.session.libsession.messaging.avatars.AvatarHelper import org.session.libsession.messaging.open_groups.OpenGroupAPI import org.session.libsession.messaging.threads.Address @@ -189,7 +190,7 @@ class SettingsActivity : PassphraseRequiredActionBarActivity() { promises.add(ProfilePictureUtilities.upload(profilePicture, encodedProfileKey, this)) } val compoundPromise = all(promises) - compoundPromise.success { + compoundPromise.successUi { // Do this on the UI thread so that it happens before the alwaysUi clause below if (isUpdatingProfilePicture && profilePicture != null) { AvatarHelper.setAvatar(this, Address.fromSerialized(TextSecurePreferences.getLocalNumber(this)!!), profilePicture) TextSecurePreferences.setProfileAvatarId(this, SecureRandom().nextInt()) @@ -206,7 +207,7 @@ class SettingsActivity : PassphraseRequiredActionBarActivity() { btnGroupNameDisplay.text = displayName } if (isUpdatingProfilePicture && profilePicture != null) { - profilePictureView.recycle() // clear cached image before update tje profilePictureView + profilePictureView.recycle() // Clear the cached image before updating profilePictureView.update() } displayNameToBeUploaded = null diff --git a/app/src/main/java/org/thoughtcrime/securesms/loki/protocol/ClosedGroupsProtocolV2.kt b/app/src/main/java/org/thoughtcrime/securesms/loki/protocol/ClosedGroupsProtocolV2.kt index 5f61506504..5d181e5207 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/loki/protocol/ClosedGroupsProtocolV2.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/loki/protocol/ClosedGroupsProtocolV2.kt @@ -3,6 +3,7 @@ package org.thoughtcrime.securesms.loki.protocol import android.content.Context import android.util.Log import com.google.protobuf.ByteString +import org.session.libsession.messaging.sending_receiving.* import org.session.libsignal.libsignal.ecc.DjbECPrivateKey import org.session.libsignal.libsignal.ecc.DjbECPublicKey import org.session.libsignal.libsignal.ecc.ECKeyPair @@ -15,12 +16,7 @@ import org.thoughtcrime.securesms.database.DatabaseFactory import org.thoughtcrime.securesms.database.GroupDatabase import org.thoughtcrime.securesms.loki.api.LokiPushNotificationManager import org.thoughtcrime.securesms.loki.api.LokiPushNotificationManager.ClosedGroupOperation -import org.thoughtcrime.securesms.loki.api.SessionProtocolImpl import org.thoughtcrime.securesms.loki.database.LokiAPIDatabase -import org.session.libsession.messaging.sending_receiving.MessageSender -import org.session.libsession.messaging.sending_receiving.generateAndSendNewEncryptionKeyPair -import org.session.libsession.messaging.sending_receiving.pendingKeyPair -import org.session.libsession.messaging.sending_receiving.sendEncryptionKeyPair import org.session.libsession.messaging.threads.Address import org.session.libsession.messaging.threads.GroupRecord @@ -330,7 +326,7 @@ object ClosedGroupsProtocolV2 { // Find our wrapper and decrypt it if possible val wrapper = closedGroupUpdate.wrappersList.firstOrNull { it.publicKey.toByteArray().toHexString() == userPublicKey } ?: return val encryptedKeyPair = wrapper.encryptedKeyPair.toByteArray() - val plaintext = SessionProtocolImpl(context).decrypt(encryptedKeyPair, userKeyPair).first + val plaintext = MessageDecrypter.decrypt(encryptedKeyPair, userKeyPair).first // Parse it val proto = SignalServiceProtos.KeyPair.parseFrom(plaintext) val keyPair = ECKeyPair(DjbECPublicKey(proto.publicKey.toByteArray().removing05PrefixIfNeeded()), DjbECPrivateKey(proto.privateKey.toByteArray())) diff --git a/libsession/src/main/java/org/session/libsession/messaging/MessagingModuleConfiguration.kt b/libsession/src/main/java/org/session/libsession/messaging/MessagingModuleConfiguration.kt index 68610f9638..98a9588332 100644 --- a/libsession/src/main/java/org/session/libsession/messaging/MessagingModuleConfiguration.kt +++ b/libsession/src/main/java/org/session/libsession/messaging/MessagingModuleConfiguration.kt @@ -2,13 +2,11 @@ package org.session.libsession.messaging import android.content.Context import org.session.libsession.database.MessageDataProvider -import org.session.libsignal.service.loki.api.crypto.SessionProtocol class MessagingModuleConfiguration( val context: Context, val storage: StorageProtocol, - val messageDataProvider: MessageDataProvider, - val sessionProtocol: SessionProtocol + val messageDataProvider: MessageDataProvider ) { companion object { @@ -16,11 +14,10 @@ class MessagingModuleConfiguration( fun configure(context: Context, storage: StorageProtocol, - messageDataProvider: MessageDataProvider, - sessionProtocol: SessionProtocol + messageDataProvider: MessageDataProvider ) { if (Companion::shared.isInitialized) { return } - shared = MessagingModuleConfiguration(context, storage, messageDataProvider, sessionProtocol) + shared = MessagingModuleConfiguration(context, storage, messageDataProvider) } } } \ No newline at end of file diff --git a/libsession/src/main/java/org/session/libsession/messaging/StorageProtocol.kt b/libsession/src/main/java/org/session/libsession/messaging/StorageProtocol.kt index d850e30664..816ede3414 100644 --- a/libsession/src/main/java/org/session/libsession/messaging/StorageProtocol.kt +++ b/libsession/src/main/java/org/session/libsession/messaging/StorageProtocol.kt @@ -92,7 +92,7 @@ interface StorageProtocol { fun removeLastDeletionServerId(room: String, server: String) // Message Handling - fun isMessageDuplicated(timestamp: Long, sender: String): Boolean + fun isDuplicateMessage(timestamp: Long, sender: String): Boolean fun getReceivedMessageTimestamps(): Set fun addReceivedMessageTimestamp(timestamp: Long) fun removeReceivedMessageTimestamps(timestamps: Set) diff --git a/app/src/main/java/org/thoughtcrime/securesms/loki/api/SessionProtocolImpl.kt b/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/MessageDecrypter.kt similarity index 80% rename from app/src/main/java/org/thoughtcrime/securesms/loki/api/SessionProtocolImpl.kt rename to libsession/src/main/java/org/session/libsession/messaging/sending_receiving/MessageDecrypter.kt index 4916ef483d..e7b09bc623 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/loki/api/SessionProtocolImpl.kt +++ b/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/MessageDecrypter.kt @@ -1,26 +1,21 @@ -package org.thoughtcrime.securesms.loki.api +package org.session.libsession.messaging.sending_receiving -import android.content.Context import android.util.Log import com.goterl.lazycode.lazysodium.LazySodiumAndroid import com.goterl.lazycode.lazysodium.SodiumAndroid import com.goterl.lazycode.lazysodium.interfaces.Box import com.goterl.lazycode.lazysodium.interfaces.Sign - -import org.session.libsignal.utilities.Hex - import org.session.libsignal.libsignal.ecc.ECKeyPair -import org.session.libsignal.service.loki.api.crypto.SessionProtocol import org.session.libsignal.service.loki.utilities.hexEncodedPublicKey import org.session.libsignal.service.loki.utilities.removing05PrefixIfNeeded import org.session.libsignal.service.loki.utilities.toHexString -import org.session.libsession.utilities.KeyPairUtilities +import org.session.libsignal.utilities.Hex -class SessionProtocolImpl(private val context: Context) : SessionProtocol { +object MessageDecrypter { private val sodium by lazy { LazySodiumAndroid(SodiumAndroid()) } - override fun decrypt(ciphertext: ByteArray, x25519KeyPair: ECKeyPair): Pair { + public fun decrypt(ciphertext: ByteArray, x25519KeyPair: ECKeyPair): Pair { val recipientX25519PrivateKey = x25519KeyPair.privateKey.serialize() val recipientX25519PublicKey = Hex.fromStringCondensed(x25519KeyPair.hexEncodedPublicKey.removing05PrefixIfNeeded()) val signatureSize = Sign.BYTES @@ -32,9 +27,9 @@ class SessionProtocolImpl(private val context: Context) : SessionProtocol { sodium.cryptoBoxSealOpen(plaintextWithMetadata, ciphertext, ciphertext.size.toLong(), recipientX25519PublicKey, recipientX25519PrivateKey) } catch (exception: Exception) { Log.d("Loki", "Couldn't decrypt message due to error: $exception.") - throw SessionProtocol.Exception.DecryptionFailed + throw MessageReceiver.Error.DecryptionFailed } - if (plaintextWithMetadata.size <= (signatureSize + ed25519PublicKeySize)) { throw SessionProtocol.Exception.DecryptionFailed } + if (plaintextWithMetadata.size <= (signatureSize + ed25519PublicKeySize)) { throw MessageReceiver.Error.DecryptionFailed } // 2. ) Get the message parts val signature = plaintextWithMetadata.sliceArray(plaintextWithMetadata.size - signatureSize until plaintextWithMetadata.size) val senderED25519PublicKey = plaintextWithMetadata.sliceArray(plaintextWithMetadata.size - (signatureSize + ed25519PublicKeySize) until plaintextWithMetadata.size - signatureSize) @@ -43,10 +38,10 @@ class SessionProtocolImpl(private val context: Context) : SessionProtocol { val verificationData = (plaintext + senderED25519PublicKey + recipientX25519PublicKey) try { val isValid = sodium.cryptoSignVerifyDetached(signature, verificationData, verificationData.size, senderED25519PublicKey) - if (!isValid) { throw SessionProtocol.Exception.InvalidSignature } + if (!isValid) { throw MessageReceiver.Error.InvalidSignature } } catch (exception: Exception) { Log.d("Loki", "Couldn't verify message signature due to error: $exception.") - throw SessionProtocol.Exception.InvalidSignature + throw MessageReceiver.Error.InvalidSignature } // 4. ) Get the sender's X25519 public key val senderX25519PublicKey = ByteArray(Sign.CURVE25519_PUBLICKEYBYTES) diff --git a/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/MessageReceiver.kt b/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/MessageReceiver.kt index d6c2d82c76..28f73521f2 100644 --- a/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/MessageReceiver.kt +++ b/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/MessageReceiver.kt @@ -10,35 +10,25 @@ import org.session.libsignal.service.internal.push.SignalServiceProtos object MessageReceiver { - private val lastEncryptionKeyPairRequest = mutableMapOf() - - internal sealed class Error(val description: String) : Exception(description) { + internal sealed class Error(message: String) : Exception(message) { object DuplicateMessage: Error("Duplicate message.") object InvalidMessage: Error("Invalid message.") object UnknownMessage: Error("Unknown message type.") object UnknownEnvelopeType: Error("Unknown envelope type.") - object NoUserX25519KeyPair: Error("Couldn't find user X25519 key pair.") - object NoUserED25519KeyPair: Error("Couldn't find user ED25519 key pair.") + object DecryptionFailed : Exception("Couldn't decrypt message.") object InvalidSignature: Error("Invalid message signature.") object NoData: Error("Received an empty envelope.") object SenderBlocked: Error("Received a message from a blocked user.") object NoThread: Error("Couldn't find thread for message.") object SelfSend: Error("Message addressed at self.") - object ParsingFailed : Error("Couldn't parse ciphertext message.") // Shared sender keys object InvalidGroupPublicKey: Error("Invalid group public key.") object NoGroupKeyPair: Error("Missing group key pair.") internal val isRetryable: Boolean = when (this) { - is DuplicateMessage -> false - is InvalidMessage -> false - is UnknownMessage -> false - is UnknownEnvelopeType -> false - is InvalidSignature -> false - is NoData -> false - is NoThread -> false - is SenderBlocked -> false - is SelfSend -> false + is DuplicateMessage, is InvalidMessage, is UnknownMessage, + is UnknownEnvelopeType, is InvalidSignature, is NoData, + is SenderBlocked, is SelfSend -> false else -> true } } @@ -46,13 +36,15 @@ object MessageReceiver { internal fun parse(data: ByteArray, openGroupServerID: Long?, isRetry: Boolean = false): Pair { val storage = MessagingModuleConfiguration.shared.storage val userPublicKey = storage.getUserPublicKey() - val isOpenGroupMessage = openGroupServerID != null + val isOpenGroupMessage = (openGroupServerID != null) // Parse the envelope val envelope = SignalServiceProtos.Envelope.parseFrom(data) // If the message failed to process the first time around we retry it later (if the error is retryable). In this case the timestamp // will already be in the database but we don't want to treat the message as a duplicate. The isRetry flag is a simple workaround // for this issue. - if (storage.isMessageDuplicated(envelope.timestamp, GroupUtil.doubleEncodeGroupID(envelope.source)) && !isRetry) throw Error.DuplicateMessage + if (storage.isDuplicateMessage(envelope.timestamp, GroupUtil.doubleEncodeGroupID(envelope.source)) && !isRetry) { + throw Error.DuplicateMessage + } // Decrypt the contents val ciphertext = envelope.content ?: throw Error.NoData var plaintext: ByteArray? = null @@ -65,7 +57,7 @@ object MessageReceiver { when (envelope.type) { SignalServiceProtos.Envelope.Type.SESSION_MESSAGE -> { val userX25519KeyPair = MessagingModuleConfiguration.shared.storage.getUserX25519KeyPair() - val decryptionResult = MessageReceiverDecryption.decryptWithSessionProtocol(ciphertext.toByteArray(), userX25519KeyPair) + val decryptionResult = MessageDecrypter.decrypt(ciphertext.toByteArray(), userX25519KeyPair) plaintext = decryptionResult.first sender = decryptionResult.second } @@ -81,7 +73,7 @@ object MessageReceiver { var encryptionKeyPair = encryptionKeyPairs.removeLast() fun decrypt() { try { - val decryptionResult = MessageReceiverDecryption.decryptWithSessionProtocol(ciphertext.toByteArray(), encryptionKeyPair) + val decryptionResult = MessageDecrypter.decrypt(ciphertext.toByteArray(), encryptionKeyPair) plaintext = decryptionResult.first sender = decryptionResult.second } catch (e: Exception) { @@ -100,9 +92,9 @@ object MessageReceiver { } } // Don't process the envelope any further if the message has been handled already - if (storage.isMessageDuplicated(envelope.timestamp, sender!!) && !isRetry) throw Error.DuplicateMessage + if (storage.isDuplicateMessage(envelope.timestamp, sender!!) && !isRetry) throw Error.DuplicateMessage // Don't process the envelope any further if the sender is blocked - if (isBlock(sender!!)) throw Error.SenderBlocked + if (isBlocked(sender!!)) throw Error.SenderBlocked // Parse the proto val proto = SignalServiceProtos.Content.parseFrom(PushTransportDetails.getStrippedPaddingMessageBody(plaintext)) // Parse the message @@ -113,7 +105,7 @@ object MessageReceiver { ExpirationTimerUpdate.fromProto(proto) ?: ConfigurationMessage.fromProto(proto) ?: VisibleMessage.fromProto(proto) ?: throw Error.UnknownMessage - // Ignore self sends if needed + // Ignore self send if needed if (!message.isSelfSendValid && sender == userPublicKey) throw Error.SelfSend // Guard against control messages in open groups if (isOpenGroupMessage && message !is VisibleMessage) throw Error.InvalidMessage diff --git a/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/MessageReceiverDecryption.kt b/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/MessageReceiverDecryption.kt deleted file mode 100644 index 6c0fb5953e..0000000000 --- a/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/MessageReceiverDecryption.kt +++ /dev/null @@ -1,11 +0,0 @@ -package org.session.libsession.messaging.sending_receiving - -import org.session.libsession.messaging.MessagingModuleConfiguration -import org.session.libsignal.libsignal.ecc.ECKeyPair - -object MessageReceiverDecryption { - - internal fun decryptWithSessionProtocol(ciphertext: ByteArray, x25519KeyPair: ECKeyPair): Pair { - return MessagingModuleConfiguration.shared.sessionProtocol.decrypt(ciphertext, x25519KeyPair) - } -} \ No newline at end of file diff --git a/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/ReceivedMessageHandler.kt b/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/ReceivedMessageHandler.kt index be331891b0..ec5744c7f0 100644 --- a/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/ReceivedMessageHandler.kt +++ b/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/ReceivedMessageHandler.kt @@ -34,7 +34,7 @@ import java.security.MessageDigest import java.util.* import kotlin.collections.ArrayList -internal fun MessageReceiver.isBlock(publicKey: String): Boolean { +internal fun MessageReceiver.isBlocked(publicKey: String): Boolean { val context = MessagingModuleConfiguration.shared.context val recipient = Recipient.from(context, Address.fromSerialized(publicKey), false) return recipient.isBlocked @@ -323,7 +323,7 @@ private fun MessageReceiver.handleClosedGroupEncryptionKeyPair(message: ClosedGr // Find our wrapper and decrypt it if possible val wrapper = kind.wrappers.firstOrNull { it.publicKey!! == userPublicKey } ?: return val encryptedKeyPair = wrapper.encryptedKeyPair!!.toByteArray() - val plaintext = MessageReceiverDecryption.decryptWithSessionProtocol(encryptedKeyPair, userKeyPair).first + val plaintext = MessageDecrypter.decrypt(encryptedKeyPair, userKeyPair).first // Parse it val proto = SignalServiceProtos.KeyPair.parseFrom(plaintext) val keyPair = ECKeyPair(DjbECPublicKey(proto.publicKey.toByteArray().removing05PrefixIfNeeded()), DjbECPrivateKey(proto.privateKey.toByteArray())) diff --git a/libsignal/src/main/java/org/session/libsignal/service/api/crypto/SignalServiceCipher.java b/libsignal/src/main/java/org/session/libsignal/service/api/crypto/SignalServiceCipher.java index 5e425464ea..7f1cd6051e 100644 --- a/libsignal/src/main/java/org/session/libsignal/service/api/crypto/SignalServiceCipher.java +++ b/libsignal/src/main/java/org/session/libsignal/service/api/crypto/SignalServiceCipher.java @@ -31,8 +31,6 @@ import org.session.libsignal.service.internal.push.SignalServiceProtos.Content; import org.session.libsignal.service.internal.push.SignalServiceProtos.DataMessage; import org.session.libsignal.service.internal.push.SignalServiceProtos.ReceiptMessage; import org.session.libsignal.service.internal.push.SignalServiceProtos.TypingMessage; -import org.session.libsignal.service.loki.api.crypto.SessionProtocol; -import org.session.libsignal.service.loki.api.crypto.SessionProtocolUtilities; import org.session.libsignal.service.loki.LokiAPIDatabaseProtocol; import java.util.ArrayList; @@ -51,13 +49,10 @@ public class SignalServiceCipher { @SuppressWarnings("unused") private static final String TAG = SignalServiceCipher.class.getSimpleName(); - private final SessionProtocol sessionProtocolImpl; private final LokiAPIDatabaseProtocol apiDB; - public SignalServiceCipher(SessionProtocol sessionProtocolImpl, - LokiAPIDatabaseProtocol apiDB) + public SignalServiceCipher(LokiAPIDatabaseProtocol apiDB) { - this.sessionProtocolImpl = sessionProtocolImpl; this.apiDB = apiDB; } @@ -125,27 +120,7 @@ public class SignalServiceCipher { protected Plaintext decrypt(SignalServiceEnvelope envelope, byte[] ciphertext) throws InvalidMetadataMessageException { - byte[] paddedMessage; - Metadata metadata; - - if (envelope.isClosedGroupCiphertext()) { - String groupPublicKey = envelope.getSource(); - kotlin.Pair plaintextAndSenderPublicKey = SessionProtocolUtilities.INSTANCE.decryptClosedGroupCiphertext(ciphertext, groupPublicKey, apiDB, sessionProtocolImpl); - paddedMessage = plaintextAndSenderPublicKey.getFirst(); - String senderPublicKey = plaintextAndSenderPublicKey.getSecond(); - metadata = new Metadata(senderPublicKey, 1, envelope.getTimestamp(), false); - } else if (envelope.isUnidentifiedSender()) { - ECKeyPair userX25519KeyPair = apiDB.getUserX25519KeyPair(); - kotlin.Pair plaintextAndSenderPublicKey = sessionProtocolImpl.decrypt(ciphertext, userX25519KeyPair); - paddedMessage = plaintextAndSenderPublicKey.getFirst(); - String senderPublicKey = plaintextAndSenderPublicKey.getSecond(); - metadata = new Metadata(senderPublicKey, 1, envelope.getTimestamp(), false); - } else { - throw new InvalidMetadataMessageException("Unknown type: " + envelope.getType()); - } - byte[] data = PushTransportDetails.getStrippedPaddingMessageBody(paddedMessage); - - return new Plaintext(metadata, data); + throw new IllegalStateException("This shouldn't be used anymore"); } private SignalServiceDataMessage createSignalServiceMessage(Metadata metadata, DataMessage content) throws ProtocolInvalidMessageException { diff --git a/libsignal/src/main/java/org/session/libsignal/service/loki/SessionProtocol.kt b/libsignal/src/main/java/org/session/libsignal/service/loki/SessionProtocol.kt deleted file mode 100644 index 201ad4e85d..0000000000 --- a/libsignal/src/main/java/org/session/libsignal/service/loki/SessionProtocol.kt +++ /dev/null @@ -1,53 +0,0 @@ -package org.session.libsignal.service.loki.api.crypto - -import org.session.libsignal.libsignal.ecc.ECKeyPair -import org.session.libsignal.service.loki.LokiAPIDatabaseProtocol - -interface SessionProtocol { - - sealed class Exception(val description: String) : kotlin.Exception(description) { - // Encryption - object NoUserED25519KeyPair : Exception("Couldn't find user ED25519 key pair.") - object SigningFailed : Exception("Couldn't sign message.") - object EncryptionFailed : Exception("Couldn't encrypt message.") - // Decryption - object NoData : Exception("Received an empty envelope.") - object InvalidGroupPublicKey : Exception("Invalid group public key.") - object NoGroupKeyPair : Exception("Missing group key pair.") - object DecryptionFailed : Exception("Couldn't decrypt message.") - object InvalidSignature : Exception("Invalid message signature.") - } - /** - * Decrypts `ciphertext` using the Session protocol and `x25519KeyPair`. - * - * @param ciphertext the data to decrypt. - * @param x25519KeyPair the key pair to use for decryption. This could be the current user's key pair, or the key pair of a closed group. - * - * @return the padded plaintext. - */ - fun decrypt(ciphertext: ByteArray, x25519KeyPair: ECKeyPair): Pair -} - -object SessionProtocolUtilities { - - fun decryptClosedGroupCiphertext(ciphertext: ByteArray, groupPublicKey: String, apiDB: LokiAPIDatabaseProtocol, sessionProtocolImpl: SessionProtocol): Pair { - val encryptionKeyPairs = apiDB.getClosedGroupEncryptionKeyPairs(groupPublicKey).toMutableList() - if (encryptionKeyPairs.isEmpty()) { throw SessionProtocol.Exception.NoGroupKeyPair } - // Loop through all known group key pairs in reverse order (i.e. try the latest key pair first (which'll more than - // likely be the one we want) but try older ones in case that didn't work) - var encryptionKeyPair = encryptionKeyPairs.removeAt(encryptionKeyPairs.lastIndex) - fun decrypt(): Pair { - try { - return sessionProtocolImpl.decrypt(ciphertext, encryptionKeyPair) - } catch(exception: Exception) { - if (encryptionKeyPairs.isNotEmpty()) { - encryptionKeyPair = encryptionKeyPairs.removeAt(encryptionKeyPairs.lastIndex) - return decrypt() - } else { - throw exception - } - } - } - return decrypt() - } -} \ No newline at end of file