feat(ff_preview): decrypt e2ee messages

This commit is contained in:
rhunk 2024-01-17 19:02:54 +01:00
parent a95c75a0b6
commit 0f3fb7bcd0
3 changed files with 25 additions and 17 deletions

View File

@ -19,6 +19,7 @@ import me.rhunk.snapenhance.common.data.ContentType
import me.rhunk.snapenhance.common.data.MessageState
import me.rhunk.snapenhance.common.data.MessagingRuleType
import me.rhunk.snapenhance.common.data.RuleState
import me.rhunk.snapenhance.common.database.impl.ConversationMessage
import me.rhunk.snapenhance.common.util.protobuf.ProtoEditor
import me.rhunk.snapenhance.common.util.protobuf.ProtoReader
import me.rhunk.snapenhance.common.util.protobuf.ProtoWriter
@ -50,7 +51,7 @@ class EndToEndEncryption : MessagingRuleFeature(
MessagingRuleType.E2E_ENCRYPTION,
loadParams = FeatureLoadParams.ACTIVITY_CREATE_SYNC or FeatureLoadParams.INIT_SYNC or FeatureLoadParams.INIT_ASYNC
) {
private val isEnabled get() = context.config.experimental.e2eEncryption.globalState == true
val isEnabled get() = context.config.experimental.e2eEncryption.globalState == true
private val e2eeInterface by lazy { context.bridgeClient.getE2eeInterface() }
companion object {
@ -268,7 +269,19 @@ class EndToEndEncryption : MessagingRuleFeature(
}.digest()
}
fun tryDecryptMessage(senderId: String, clientMessageId: Long, conversationId: String, contentType: ContentType, messageBuffer: ByteArray): Pair<ContentType, ByteArray> {
fun decryptDatabaseMessage(conversationMessage: ConversationMessage): ProtoReader {
return tryDecryptMessage(
senderId = conversationMessage.senderId!!,
clientMessageId = conversationMessage.clientMessageId.toLong(),
conversationId = conversationMessage.clientConversationId!!,
contentType = ContentType.fromId(conversationMessage.contentType),
messageBuffer = ProtoReader(conversationMessage.messageContent!!).getByteArray(4, 4)!!
).let { (_, buffer) ->
ProtoReader(buffer)
}
}
private fun tryDecryptMessage(senderId: String, clientMessageId: Long, conversationId: String, contentType: ContentType, messageBuffer: ByteArray): Pair<ContentType, ByteArray> {
if (contentType != ContentType.STATUS && decryptedMessageCache.containsKey(clientMessageId)) {
return decryptedMessageCache[clientMessageId]!!
}

View File

@ -50,16 +50,8 @@ class FriendFeedMessagePreview : Feature("FriendFeedMessagePreview", loadParams
val messageContainer =
message.messageContent
?.let { ProtoReader(it) }
?.followPath(4, 4)?.let { messageReader ->
takeIf { hasE2EE }?.let takeIf@{
endToEndEncryption.tryDecryptMessage(
senderId = message.senderId ?: return@takeIf null,
clientMessageId = message.clientMessageId.toLong(),
conversationId = message.clientConversationId ?: return@takeIf null,
contentType = ContentType.fromId(message.contentType),
messageBuffer = messageReader.getBuffer()
).second
}?.let { ProtoReader(it) } ?: messageReader
?.followPath(4, 4)?.let {
if (hasE2EE) endToEndEncryption.decryptDatabaseMessage(message) else it
}
?: return@mapNotNull null

View File

@ -29,6 +29,7 @@ import me.rhunk.snapenhance.common.scripting.ui.ScriptInterface
import me.rhunk.snapenhance.common.ui.createComposeView
import me.rhunk.snapenhance.common.util.protobuf.ProtoReader
import me.rhunk.snapenhance.common.util.snap.BitmojiSelfie
import me.rhunk.snapenhance.core.features.impl.experiments.EndToEndEncryption
import me.rhunk.snapenhance.core.features.impl.messaging.Messaging
import me.rhunk.snapenhance.core.features.impl.spying.MessageLogger
import me.rhunk.snapenhance.core.ui.ViewAppearanceHelper
@ -159,6 +160,7 @@ class FriendFeedInfoMenu : AbstractMenu() {
private fun showPreview(userId: String?, conversationId: String) {
//query message
val messageLogger = context.feature(MessageLogger::class)
val endToEndEncryption = context.feature(EndToEndEncryption::class)
val messages: List<ConversationMessage> = context.database.getMessagesFromConversationId(
conversationId,
context.config.messaging.messagePreviewLength.get()
@ -174,11 +176,12 @@ class FriendFeedInfoMenu : AbstractMenu() {
messages.forEach { message ->
val sender = participants[message.senderId]
val messageProtoReader =
messageLogger.takeIf {
it.isEnabled && message.contentType == ContentType.STATUS.id // only process deleted messages
}?.getMessageProto(conversationId, message.clientMessageId.toLong())
?: ProtoReader(message.messageContent ?: return@forEach).followPath(4, 4)
?: return@forEach
(
messageLogger.takeIf { it.isEnabled && message.contentType == ContentType.STATUS.id }?.getMessageProto(conversationId, message.clientMessageId.toLong()) // process deleted messages if message logger is enabled
?: ProtoReader(message.messageContent!!).followPath(4, 4) // database message
)?.let {
if (endToEndEncryption.isEnabled) endToEndEncryption.decryptDatabaseMessage(message) else it // try to decrypt message if e2ee is enabled
} ?: return@forEach
val contentType = ContentType.fromMessageContainer(messageProtoReader) ?: ContentType.fromId(message.contentType)
var messageString = if (contentType == ContentType.CHAT) {