Message validation refactor

This commit is contained in:
charles 2022-05-06 11:38:09 +10:00
parent edb4f96f0a
commit bb50182a18
5 changed files with 54 additions and 23 deletions

View File

@ -359,7 +359,7 @@ object OpenGroupApi {
room: String,
server: String
): Promise<OpenGroupMessage, Exception> {
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,

View File

@ -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,31 +31,48 @@ data class OpenGroupMessage(
fun fromJSON(json: Map<String, Any>): 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 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
val signature = try {
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))
}

View File

@ -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<ByteArray, String> {
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

View File

@ -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)

View File

@ -229,15 +229,15 @@ object MessageSender {
message.profile = Profile(displayName)
}
}
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)
when (destination) {
is Destination.LegacyOpenGroup -> {
message.recipient = "${destination.server}.${destination.roomToken}"
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