Skip to content

Commit

Permalink
add matching decryption code to swift
Browse files Browse the repository at this point in the history
  • Loading branch information
nplasterer committed Nov 15, 2023
1 parent 74d57e1 commit 9d6a2cb
Show file tree
Hide file tree
Showing 6 changed files with 148 additions and 25 deletions.
13 changes: 13 additions & 0 deletions library/src/main/java/org/xmtp/android/library/Conversation.kt
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import org.xmtp.proto.keystore.api.v1.Keystore.TopicMap.TopicData
import org.xmtp.proto.message.api.v1.MessageApiOuterClass
import org.xmtp.proto.message.contents.Invitation
import org.xmtp.proto.message.contents.Invitation.InvitationV1.Aes256gcmHkdfsha256
import uniffi.xmtp_dh.org.xmtp.android.library.messages.DecryptedMessage
import java.util.Date

sealed class Conversation {
Expand Down Expand Up @@ -180,6 +181,18 @@ sealed class Conversation {
}
}

fun decryptedMessages(
limit: Int? = null,
before: Date? = null,
after: Date? = null,
direction: PagingInfoSortDirection = MessageApiOuterClass.SortDirection.SORT_DIRECTION_DESCENDING,
): List<DecryptedMessage> {
return when (this) {
is V1 -> conversationV1.decryptedMessages(limit, before, after, direction)
is V2 -> conversationV2.decryptedMessages(limit, before, after, direction)
}
}

val client: Client
get() {
return when (this) {
Expand Down
65 changes: 52 additions & 13 deletions library/src/main/java/org/xmtp/android/library/ConversationV1.kt
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import org.xmtp.android.library.messages.sentAt
import org.xmtp.android.library.messages.toPublicKeyBundle
import org.xmtp.android.library.messages.walletAddress
import org.xmtp.proto.message.api.v1.MessageApiOuterClass
import uniffi.xmtp_dh.org.xmtp.android.library.messages.DecryptedMessage
import java.util.Date

data class ConversationV1(
Expand Down Expand Up @@ -56,21 +57,59 @@ data class ConversationV1(
}
}

fun decode(envelope: Envelope): DecodedMessage {
val message = Message.parseFrom(envelope.message)
val decrypted = message.v1.decrypt(client.privateKeyBundleV1)
val encodedMessage = EncodedContent.parseFrom(decrypted)
val header = message.v1.header
val decoded = DecodedMessage(
topic = envelope.contentTopic,
encodedContent = encodedMessage,
senderAddress = header.sender.walletAddress,
sent = message.v1.sentAt
)
fun decryptedMessages(
limit: Int? = null,
before: Date? = null,
after: Date? = null,
direction: PagingInfoSortDirection = MessageApiOuterClass.SortDirection.SORT_DIRECTION_DESCENDING,
): List<DecryptedMessage> {
val pagination =
Pagination(limit = limit, before = before, after = after, direction = direction)

val envelopes = runBlocking {
client.apiClient.envelopes(
topic = Topic.directMessageV1(client.address, peerAddress).description,
pagination = pagination
)
}

decoded.id = generateId(envelope)
return envelopes.map { decrypt(it) }
}

return decoded
fun decrypt(envelope: Envelope): DecryptedMessage {
try {
val message = Message.parseFrom(envelope.message)
val decrypted = message.v1.decrypt(client.privateKeyBundleV1)

val encodedMessage = EncodedContent.parseFrom(decrypted)
val header = message.v1.header

return DecryptedMessage(
id = generateId(envelope),
encodedContent = encodedMessage,
senderAddress = header.sender.walletAddress,
sentAt = message.v1.sentAt
)
} catch (e: Exception) {
throw XMTPException("Error decrypting message", e)
}
}

fun decode(envelope: Envelope): DecodedMessage {
try {
val decryptedMessage = decrypt(envelope)

return DecodedMessage(
id = generateId(envelope),
client = client,
topic = envelope.contentTopic,
encodedContent = decryptedMessage.encodedContent,
senderAddress = decryptedMessage.senderAddress,
sent = decryptedMessage.sentAt
)
} catch (e: Exception) {
throw XMTPException("Error decoding message", e)
}
}

private fun decodeOrNull(envelope: Envelope): DecodedMessage? {
Expand Down
36 changes: 30 additions & 6 deletions library/src/main/java/org/xmtp/android/library/ConversationV2.kt
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import org.xmtp.android.library.messages.getPublicKeyBundle
import org.xmtp.android.library.messages.walletAddress
import org.xmtp.proto.message.api.v1.MessageApiOuterClass
import org.xmtp.proto.message.contents.Invitation
import uniffi.xmtp_dh.org.xmtp.android.library.messages.DecryptedMessage
import java.util.Date

data class ConversationV2(
Expand Down Expand Up @@ -77,6 +78,28 @@ data class ConversationV2(
}
}

fun decryptedMessages(
limit: Int? = null,
before: Date? = null,
after: Date? = null,
direction: PagingInfoSortDirection = MessageApiOuterClass.SortDirection.SORT_DIRECTION_DESCENDING,
): List<DecryptedMessage> {
val pagination =
Pagination(limit = limit, before = before, after = after, direction = direction)
val envelopes = runBlocking { client.apiClient.envelopes(topic, pagination) }

return envelopes.map { envelope ->
val message = Message.parseFrom(envelope.message)
MessageV2Builder.buildDecrypt(
id = generateId(envelope = envelope),
topic,
message.v2,
keyMaterial,
client
)
}
}

fun streamMessages(): Flow<DecodedMessage> = flow {
client.subscribe(listOf(topic)).mapNotNull { decodeEnvelopeOrNull(envelope = it) }.collect {
emit(it)
Expand All @@ -85,9 +108,13 @@ data class ConversationV2(

fun decodeEnvelope(envelope: Envelope): DecodedMessage {
val message = Message.parseFrom(envelope.message)
val decoded = decode(message.v2)
decoded.id = generateId(envelope)
return decoded
return MessageV2Builder.buildDecode(
generateId(envelope = envelope),
topic = topic,
message.v2,
keyMaterial = keyMaterial,
client = client
)
}

private fun decodeEnvelopeOrNull(envelope: Envelope): DecodedMessage? {
Expand All @@ -99,9 +126,6 @@ data class ConversationV2(
}
}

fun decode(message: MessageV2): DecodedMessage =
MessageV2Builder.buildDecode(message, keyMaterial = keyMaterial, topic = topic)

fun <T> send(content: T, options: SendOptions? = null): String {
val preparedMessage = prepareMessage(content = content, options = options)
return send(preparedMessage)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,18 @@ import org.xmtp.proto.message.contents.Content
import java.util.Date

data class DecodedMessage(
var id: String = "",
val client: Client,
var topic: String,
var encodedContent: Content.EncodedContent,
var senderAddress: String,
var sent: Date
) {
var id: String = ""
companion object {
fun preview(topic: String, body: String, senderAddress: String, sent: Date): DecodedMessage {
fun preview(client: Client, topic: String, body: String, senderAddress: String, sent: Date): DecodedMessage {
val encoded = TextCodec().encode(content = body)
return DecodedMessage(
client = client,
topic = topic,
encodedContent = encoded,
senderAddress = senderAddress,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package uniffi.xmtp_dh.org.xmtp.android.library.messages

import org.xmtp.android.library.codecs.EncodedContent
import java.util.Date

data class DecryptedMessage(
var id: String,
var encodedContent: EncodedContent,
var senderAddress: String,
var sentAt: Date,
var topic: String = ""
)
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import org.xmtp.android.library.DecodedMessage
import org.xmtp.android.library.KeyUtil
import org.xmtp.android.library.XMTPException
import org.xmtp.android.library.codecs.EncodedContent
import uniffi.xmtp_dh.org.xmtp.android.library.messages.DecryptedMessage
import java.math.BigInteger
import java.util.Date

Expand All @@ -25,7 +26,36 @@ class MessageV2Builder {
}.build()
}

fun buildDecode(message: MessageV2, keyMaterial: ByteArray, topic: String): DecodedMessage {
fun buildDecode(
id: String,
topic: String,
message: MessageV2,
keyMaterial: ByteArray,
client: Client,
): DecodedMessage {
try {
val decryptedMessage = buildDecrypt(id, topic, message, keyMaterial, client)

return DecodedMessage(
id = id,
client = client,
topic = decryptedMessage.topic,
encodedContent = decryptedMessage.encodedContent,
senderAddress = decryptedMessage.senderAddress,
sent = decryptedMessage.sentAt
)
} catch (e: Exception) {
throw XMTPException("Error decoding message", e)
}
}

fun buildDecrypt(
id: String,
topic: String,
message: MessageV2,
keyMaterial: ByteArray,
client: Client,
): DecryptedMessage {
val decrypted =
Crypto.decrypt(keyMaterial, message.ciphertext, message.headerBytes.toByteArray())
val signed = SignedContent.parseFrom(decrypted)
Expand Down Expand Up @@ -68,16 +98,19 @@ class MessageV2Builder {
if (key.walletAddress != (PublicKeyBuilder.buildFromSignedPublicKey(signed.sender.preKey).walletAddress)) {
throw XMTPException("Invalid signature")
}

val encodedMessage = EncodedContent.parseFrom(signed.payload)
val header = MessageHeaderV2.parseFrom(message.headerBytes)
if (header.topic != topic) {
throw XMTPException("Topic mismatch")
}
return DecodedMessage(
topic = header.topic,

return DecryptedMessage(
id = id,
encodedContent = encodedMessage,
senderAddress = signed.sender.walletAddress,
sent = Date(header.createdNs / 1_000_000)
sentAt = Date(header.createdNs / 1_000_000),
topic = topic
)
}

Expand Down

0 comments on commit 9d6a2cb

Please sign in to comment.