From bb50182a18fb7ff40f761c1d847542863f345262 Mon Sep 17 00:00:00 2001 From: charles Date: Fri, 6 May 2022 11:38:09 +1000 Subject: [PATCH] Message validation refactor --- .../messaging/open_groups/OpenGroupApi.kt | 2 +- .../messaging/open_groups/OpenGroupMessage.kt | 41 ++++++++++++++----- .../sending_receiving/MessageDecrypter.kt | 6 +-- .../sending_receiving/MessageEncrypter.kt | 4 +- .../sending_receiving/MessageSender.kt | 24 ++++++++--- 5 files changed, 54 insertions(+), 23 deletions(-) diff --git a/libsession/src/main/java/org/session/libsession/messaging/open_groups/OpenGroupApi.kt b/libsession/src/main/java/org/session/libsession/messaging/open_groups/OpenGroupApi.kt index 91ee9e107b..c1b0dffb5b 100644 --- a/libsession/src/main/java/org/session/libsession/messaging/open_groups/OpenGroupApi.kt +++ b/libsession/src/main/java/org/session/libsession/messaging/open_groups/OpenGroupApi.kt @@ -359,7 +359,7 @@ object OpenGroupApi { room: String, server: String ): Promise { - val signedMessage = message.sign() ?: return Promise.ofFail(Error.SigningFailed) + val signedMessage = message.sign(room, server, fallbackSigningType = IdPrefix.STANDARD) ?: return Promise.ofFail(Error.SigningFailed) val jsonMessage = signedMessage.toJSON() val request = Request( verb = POST, diff --git a/libsession/src/main/java/org/session/libsession/messaging/open_groups/OpenGroupMessage.kt b/libsession/src/main/java/org/session/libsession/messaging/open_groups/OpenGroupMessage.kt index 8af19e884d..1c16d7d4a7 100644 --- a/libsession/src/main/java/org/session/libsession/messaging/open_groups/OpenGroupMessage.kt +++ b/libsession/src/main/java/org/session/libsession/messaging/open_groups/OpenGroupMessage.kt @@ -1,10 +1,12 @@ package org.session.libsession.messaging.open_groups import org.session.libsession.messaging.MessagingModuleConfiguration +import org.session.libsession.messaging.utilities.SodiumUtilities import org.session.libsignal.crypto.PushTransportDetails import org.session.libsignal.protos.SignalServiceProtos import org.session.libsignal.utilities.Base64 import org.session.libsignal.utilities.Base64.decode +import org.session.libsignal.utilities.IdPrefix import org.session.libsignal.utilities.Log import org.session.libsignal.utilities.toHexString import org.whispersystems.curve25519.Curve25519 @@ -29,30 +31,47 @@ data class OpenGroupMessage( fun fromJSON(json: Map): OpenGroupMessage? { val base64EncodedData = json["data"] as? String ?: return null - val sentTimestamp = json["posted"] as? Long ?: return null + val sentTimestamp = json["posted"] as? Double ?: return null val serverID = json["id"] as? Int val sender = json["session_id"] as? String val base64EncodedSignature = json["signature"] as? String return OpenGroupMessage( serverID = serverID?.toLong(), sender = sender, - sentTimestamp = sentTimestamp, + sentTimestamp = (sentTimestamp * 1000).toLong(), base64EncodedData = base64EncodedData, base64EncodedSignature = base64EncodedSignature ) } - } - fun sign(): OpenGroupMessage? { + fun sign(room: String, server: String, fallbackSigningType: IdPrefix): OpenGroupMessage? { if (base64EncodedData.isEmpty()) return null - val (publicKey, privateKey) = MessagingModuleConfiguration.shared.storage.getUserX25519KeyPair().let { it.publicKey to it.privateKey } - if (sender != publicKey.serialize().toHexString()) return null - val signature = try { - curve.calculateSignature(privateKey.serialize(), decode(base64EncodedData)) - } catch (e: Exception) { - Log.w("Loki", "Couldn't sign open group message.", e) - return null + val userEdKeyPair = MessagingModuleConfiguration.shared.getUserED25519KeyPair() ?: return null + val openGroup = MessagingModuleConfiguration.shared.storage.getOpenGroup(room, server) ?: return null + val signature = when { + openGroup.capabilities.contains("blind") -> { + val blindedKeyPair = SodiumUtilities.blindedKeyPair(openGroup.publicKey, userEdKeyPair) ?: return null + SodiumUtilities.sogsSignature( + decode(base64EncodedData), + userEdKeyPair.secretKey.asBytes, + blindedKeyPair.secretKey.asBytes, + blindedKeyPair.publicKey.asBytes + ) ?: return null + } + fallbackSigningType == IdPrefix.UN_BLINDED -> { + curve.calculateSignature(userEdKeyPair.secretKey.asBytes, decode(base64EncodedData)) + } + else -> { + val (publicKey, privateKey) = MessagingModuleConfiguration.shared.storage.getUserX25519KeyPair().let { it.publicKey to it.privateKey } + if (sender != publicKey.serialize().toHexString()) return null + try { + curve.calculateSignature(privateKey.serialize(), decode(base64EncodedData)) + } catch (e: Exception) { + Log.w("Loki", "Couldn't sign open group message.", e) + return null + } + } } return copy(base64EncodedSignature = Base64.encodeBytes(signature)) } diff --git a/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/MessageDecrypter.kt b/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/MessageDecrypter.kt index 6ef1bb0ef0..6b0b5d9882 100644 --- a/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/MessageDecrypter.kt +++ b/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/MessageDecrypter.kt @@ -8,9 +8,9 @@ import com.goterl.lazysodium.interfaces.Sign import org.session.libsession.messaging.utilities.SessionId import org.session.libsignal.crypto.ecc.ECKeyPair import org.session.libsignal.utilities.Hex +import org.session.libsignal.utilities.IdPrefix import org.session.libsignal.utilities.hexEncodedPublicKey -import org.session.libsignal.utilities.removing05PrefixIfNeeded -import org.session.libsignal.utilities.toHexString +import org.session.libsignal.utilities.removingIdPrefixIfNeeded object MessageDecrypter { @@ -26,7 +26,7 @@ object MessageDecrypter { */ public fun decrypt(ciphertext: ByteArray, x25519KeyPair: ECKeyPair): Pair { val recipientX25519PrivateKey = x25519KeyPair.privateKey.serialize() - val recipientX25519PublicKey = Hex.fromStringCondensed(x25519KeyPair.hexEncodedPublicKey.removing05PrefixIfNeeded()) + val recipientX25519PublicKey = Hex.fromStringCondensed(x25519KeyPair.hexEncodedPublicKey.removingIdPrefixIfNeeded()) val signatureSize = Sign.BYTES val ed25519PublicKeySize = Sign.PUBLICKEYBYTES diff --git a/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/MessageEncrypter.kt b/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/MessageEncrypter.kt index 52485acd45..4992eb4fb7 100644 --- a/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/MessageEncrypter.kt +++ b/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/MessageEncrypter.kt @@ -8,7 +8,7 @@ import org.session.libsession.messaging.MessagingModuleConfiguration import org.session.libsession.messaging.sending_receiving.MessageSender.Error import org.session.libsignal.utilities.Hex import org.session.libsignal.utilities.Log -import org.session.libsignal.utilities.removing05PrefixIfNeeded +import org.session.libsignal.utilities.removingIdPrefixIfNeeded object MessageEncrypter { @@ -24,7 +24,7 @@ object MessageEncrypter { */ internal fun encrypt(plaintext: ByteArray, recipientHexEncodedX25519PublicKey: String): ByteArray { val userED25519KeyPair = MessagingModuleConfiguration.shared.getUserED25519KeyPair() ?: throw Error.NoUserED25519KeyPair - val recipientX25519PublicKey = Hex.fromStringCondensed(recipientHexEncodedX25519PublicKey.removing05PrefixIfNeeded()) + val recipientX25519PublicKey = Hex.fromStringCondensed(recipientHexEncodedX25519PublicKey.removingIdPrefixIfNeeded()) val verificationData = plaintext + userED25519KeyPair.publicKey.asBytes + recipientX25519PublicKey val signature = ByteArray(Sign.BYTES) diff --git a/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/MessageSender.kt b/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/MessageSender.kt index ce3952d7c4..1977d44cc0 100644 --- a/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/MessageSender.kt +++ b/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/MessageSender.kt @@ -229,15 +229,15 @@ object MessageSender { message.profile = Profile(displayName) } } - // Validate the message - if (message !is VisibleMessage || !message.isValid()) { - throw Error.InvalidMessage - } - val messageBody = message.toProto()?.toByteArray()!! - val plaintext = PushTransportDetails.getPaddedMessageBody(messageBody) when (destination) { is Destination.LegacyOpenGroup -> { message.recipient = "${destination.server}.${destination.roomToken}" + // Validate the message + if (message !is VisibleMessage || !message.isValid()) { + throw Error.InvalidMessage + } + val messageBody = message.toProto()?.toByteArray()!! + val plaintext = PushTransportDetails.getPaddedMessageBody(messageBody) val openGroupMessage = OpenGroupMessage( sender = message.sender, sentTimestamp = message.sentTimestamp!!, @@ -253,6 +253,12 @@ object MessageSender { } is Destination.OpenGroup -> { message.recipient = "${destination.server}.${destination.roomToken}" + // Validate the message + if (message !is VisibleMessage || !message.isValid()) { + throw Error.InvalidMessage + } + val messageBody = message.toProto()?.toByteArray()!! + val plaintext = PushTransportDetails.getPaddedMessageBody(messageBody) val openGroupMessage = OpenGroupMessage( sender = message.sender, sentTimestamp = message.sentTimestamp!!, @@ -268,6 +274,12 @@ object MessageSender { } is Destination.OpenGroupInbox -> { message.recipient = destination.blinkedPublicKey + // Validate the message + if (message !is VisibleMessage || !message.isValid()) { + throw Error.InvalidMessage + } + val messageBody = message.toProto()?.toByteArray()!! + val plaintext = PushTransportDetails.getPaddedMessageBody(messageBody) val base64EncodedData = Base64.encodeBytes(plaintext) OpenGroupApi.sendDirectMessage(base64EncodedData, destination.blinkedPublicKey, destination.server).success { message.openGroupServerMessageID = it.id