Skip to content

Commit

Permalink
Improve security (#53)
Browse files Browse the repository at this point in the history
* add api client with grpc kotlin

* protect against invalid/spoofed contact bundle

* prevents injecting messages across topics

* clean up curve code

* fix up the lint

* check contacts in loop
  • Loading branch information
nplasterer authored Mar 14, 2023
1 parent 6a72eca commit 10f861b
Show file tree
Hide file tree
Showing 5 changed files with 19 additions and 21 deletions.
11 changes: 9 additions & 2 deletions library/src/main/java/org/xmtp/android/library/Contacts.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import kotlinx.coroutines.runBlocking
import org.xmtp.android.library.messages.ContactBundle
import org.xmtp.android.library.messages.ContactBundleBuilder
import org.xmtp.android.library.messages.Topic
import org.xmtp.android.library.messages.walletAddress

data class Contacts(
var client: Client,
Expand All @@ -27,8 +28,14 @@ data class Contacts(
if (response.envelopesList.isNullOrEmpty()) return null

for (envelope in response.envelopesList) {
knownBundles[peerAddress] = ContactBundleBuilder.buildFromEnvelope(envelope)
val contactBundle = ContactBundleBuilder.buildFromEnvelope(envelope)
knownBundles[peerAddress] = contactBundle
val address = contactBundle.walletAddress
if (address == peerAddress) {
return contactBundle
}
}
return ContactBundleBuilder.buildFromEnvelope(response.envelopesList.first())

return null
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ data class ConversationV2(
}

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

fun <T> send(content: T, options: SendOptions? = null) {
val codec = Client.codecRegistry.find(options?.contentType)
Expand Down
17 changes: 2 additions & 15 deletions library/src/main/java/org/xmtp/android/library/KeyUtil.kt
Original file line number Diff line number Diff line change
@@ -1,25 +1,12 @@
package org.xmtp.android.library

import org.bouncycastle.asn1.sec.SECNamedCurves
import org.bouncycastle.crypto.params.ECDomainParameters
import org.bouncycastle.math.ec.FixedPointCombMultiplier
import org.bouncycastle.util.Arrays
import org.web3j.crypto.Sign
import org.web3j.crypto.Sign.SignatureData
import java.math.BigInteger

object KeyUtil {
fun getPublicKey(privateKey: ByteArray): ByteArray {
val params = SECNamedCurves.getByName("secp256k1")
val curve = ECDomainParameters(params.curve, params.g, params.n, params.h)

var privKey = BigInteger(1, privateKey)

if (privKey.bitLength() > curve.n.bitLength()) {
privKey = privKey.mod(curve.n)
}

val point = FixedPointCombMultiplier().multiply(curve.getG(), privKey)
return Arrays.copyOfRange(point.getEncoded(false), 1, 65)
return Sign.publicKeyFromPrivate(BigInteger(1, privateKey)).toByteArray()
}

fun addUncompressedByte(publicKey: ByteArray): ByteArray {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ class MessageV2Builder {
}.build()
}

fun buildDecode(message: MessageV2, keyMaterial: ByteArray): DecodedMessage {
fun buildDecode(message: MessageV2, keyMaterial: ByteArray, topic: String): DecodedMessage {
val decrypted =
Crypto.decrypt(keyMaterial, message.ciphertext, message.headerBytes.toByteArray())
val signed = SignedContent.parseFrom(decrypted)
Expand Down Expand Up @@ -64,10 +64,13 @@ class MessageV2Builder {
}.build()

if (key.walletAddress != (PublicKeyBuilder.buildFromSignedPublicKey(signed.sender.preKey).walletAddress)) {
throw throw XMTPException("Invalid signature")
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(
encodedContent = encodedMessage,
senderAddress = signed.sender.walletAddress,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,8 @@ class MessageTest {
)
val decoded = MessageV2Builder.buildDecode(
message1,
keyMaterial = invitationv1.aes256GcmHkdfSha256.keyMaterial.toByteArray()
keyMaterial = invitationv1.aes256GcmHkdfSha256.keyMaterial.toByteArray(),
topic = invitationv1.topic
)
val result: String? = decoded.content()
assertEquals(result, "Yo!")
Expand Down

0 comments on commit 10f861b

Please sign in to comment.