From e9700e04d865b470c5e45120ad05d0c36444e34c Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 9 Jul 2019 17:31:44 +0200 Subject: [PATCH] Move method to JsonCanonicalizer and fix test compilation --- .../session/room/timeline/ChunkEntityTest.kt | 8 ++-- .../android/internal/crypto/CryptoManager.kt | 5 +-- .../android/internal/crypto/MXOlmDevice.kt | 3 +- .../internal/crypto/OneTimeKeysUploader.kt | 4 +- .../crypto/actions/MessageEncrypter.kt | 5 +-- .../algorithms/megolm/MXMegolmEncryption.kt | 4 +- .../internal/crypto/keysbackup/KeysBackup.kt | 5 ++- .../IncomingSASVerificationTransaction.kt | 4 +- .../OutgoingSASVerificationRequest.kt | 4 +- .../database/helper/ChunkEntityHelper.kt | 24 ++++++------ .../android/internal/di/MoshiProvider.kt | 14 ------- .../internal/util/JsonCanonicalizer.kt | 37 ++++++++++--------- 12 files changed, 53 insertions(+), 64 deletions(-) diff --git a/matrix-sdk-android/src/androidTest/java/im/vector/matrix/android/session/room/timeline/ChunkEntityTest.kt b/matrix-sdk-android/src/androidTest/java/im/vector/matrix/android/session/room/timeline/ChunkEntityTest.kt index b76014d18b..be351fb03c 100644 --- a/matrix-sdk-android/src/androidTest/java/im/vector/matrix/android/session/room/timeline/ChunkEntityTest.kt +++ b/matrix-sdk-android/src/androidTest/java/im/vector/matrix/android/session/room/timeline/ChunkEntityTest.kt @@ -59,7 +59,7 @@ internal class ChunkEntityTest : InstrumentedTest { val chunk: ChunkEntity = realm.createObject() val fakeEvent = createFakeMessageEvent() chunk.add("roomId", fakeEvent, PaginationDirection.FORWARDS) - chunk.events.size shouldEqual 1 + chunk.timelineEvents.size shouldEqual 1 } } @@ -70,7 +70,7 @@ internal class ChunkEntityTest : InstrumentedTest { val fakeEvent = createFakeMessageEvent() chunk.add("roomId", fakeEvent, PaginationDirection.FORWARDS) chunk.add("roomId", fakeEvent, PaginationDirection.FORWARDS) - chunk.events.size shouldEqual 1 + chunk.timelineEvents.size shouldEqual 1 } } @@ -126,7 +126,7 @@ internal class ChunkEntityTest : InstrumentedTest { chunk1.addAll("roomId", createFakeListOfEvents(30), PaginationDirection.BACKWARDS) chunk2.addAll("roomId", createFakeListOfEvents(30), PaginationDirection.BACKWARDS) chunk1.merge("roomId", chunk2, PaginationDirection.BACKWARDS) - chunk1.events.size shouldEqual 60 + chunk1.timelineEvents.size shouldEqual 60 } } @@ -142,7 +142,7 @@ internal class ChunkEntityTest : InstrumentedTest { chunk1.addAll("roomId", eventsForChunk1, PaginationDirection.FORWARDS) chunk2.addAll("roomId", eventsForChunk2, PaginationDirection.BACKWARDS) chunk1.merge("roomId", chunk2, PaginationDirection.BACKWARDS) - chunk1.events.size shouldEqual 40 + chunk1.timelineEvents.size shouldEqual 40 chunk1.isLastForward.shouldBeTrue() } } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/CryptoManager.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/CryptoManager.kt index 342c7ee53c..5993548ecf 100755 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/CryptoManager.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/CryptoManager.kt @@ -48,7 +48,6 @@ import im.vector.matrix.android.internal.crypto.actions.SetDeviceVerificationAct import im.vector.matrix.android.internal.crypto.algorithms.IMXEncrypting import im.vector.matrix.android.internal.crypto.algorithms.megolm.MXMegolmEncryptionFactory import im.vector.matrix.android.internal.crypto.algorithms.olm.MXOlmEncryptionFactory -import im.vector.matrix.android.internal.crypto.attachments.ElementToDecrypt import im.vector.matrix.android.internal.crypto.keysbackup.KeysBackup import im.vector.matrix.android.internal.crypto.model.ImportRoomKeysResult import im.vector.matrix.android.internal.crypto.model.MXDeviceInfo @@ -74,12 +73,12 @@ import im.vector.matrix.android.internal.session.room.membership.RoomMembers import im.vector.matrix.android.internal.session.sync.model.SyncResponse import im.vector.matrix.android.internal.task.TaskExecutor import im.vector.matrix.android.internal.task.configureWith +import im.vector.matrix.android.internal.util.JsonCanonicalizer import im.vector.matrix.android.internal.util.MatrixCoroutineDispatchers import im.vector.matrix.android.internal.util.fetchCopied import kotlinx.coroutines.* import org.matrix.olm.OlmManager import timber.log.Timber -import java.io.File import java.util.* import java.util.concurrent.atomic.AtomicBoolean import javax.inject.Inject @@ -766,7 +765,7 @@ internal class CryptoManager @Inject constructor( private suspend fun uploadDeviceKeys(): Try { // Prepare the device keys data to send // Sign it - val canonicalJson = MoshiProvider.getCanonicalJson(Map::class.java, getMyDevice().signalableJSONDictionary()) + val canonicalJson = JsonCanonicalizer.getCanonicalJson(Map::class.java, getMyDevice().signalableJSONDictionary()) getMyDevice().signatures = objectSigner.signObject(canonicalJson) // For now, we set the device id explicitly, as we may not be using the diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/MXOlmDevice.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/MXOlmDevice.kt index 519a850f14..8f0bfcd4d2 100755 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/MXOlmDevice.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/MXOlmDevice.kt @@ -28,6 +28,7 @@ import im.vector.matrix.android.internal.crypto.model.OlmSessionWrapper import im.vector.matrix.android.internal.crypto.store.IMXCryptoStore import im.vector.matrix.android.internal.di.MoshiProvider import im.vector.matrix.android.internal.session.SessionScope +import im.vector.matrix.android.internal.util.JsonCanonicalizer import im.vector.matrix.android.internal.util.convertFromUTF8 import im.vector.matrix.android.internal.util.convertToUTF8 import org.matrix.olm.* @@ -728,7 +729,7 @@ internal class MXOlmDevice @Inject constructor( @Throws(Exception::class) fun verifySignature(key: String, jsonDictionary: Map, signature: String) { // Check signature on the canonical version of the JSON - olmUtility!!.verifyEd25519Signature(signature, key, MoshiProvider.getCanonicalJson>(Map::class.java, jsonDictionary)) + olmUtility!!.verifyEd25519Signature(signature, key, JsonCanonicalizer.getCanonicalJson(Map::class.java, jsonDictionary)) } /** diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/OneTimeKeysUploader.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/OneTimeKeysUploader.kt index 9cf981b55e..a81cbfcf76 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/OneTimeKeysUploader.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/OneTimeKeysUploader.kt @@ -22,8 +22,8 @@ import im.vector.matrix.android.api.auth.data.Credentials import im.vector.matrix.android.internal.crypto.model.MXKey import im.vector.matrix.android.internal.crypto.model.rest.KeysUploadResponse import im.vector.matrix.android.internal.crypto.tasks.UploadKeysTask -import im.vector.matrix.android.internal.di.MoshiProvider import im.vector.matrix.android.internal.session.SessionScope +import im.vector.matrix.android.internal.util.JsonCanonicalizer import org.matrix.olm.OlmAccount import timber.log.Timber import java.util.* @@ -158,7 +158,7 @@ internal class OneTimeKeysUploader @Inject constructor( k["key"] = curve25519Map.getValue(key_id) // the key is also signed - val canonicalJson = MoshiProvider.getCanonicalJson(Map::class.java, k) + val canonicalJson = JsonCanonicalizer.getCanonicalJson(Map::class.java, k) k["signatures"] = objectSigner.signObject(canonicalJson) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/actions/MessageEncrypter.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/actions/MessageEncrypter.kt index 336a5a0fbb..3328de0eaf 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/actions/MessageEncrypter.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/actions/MessageEncrypter.kt @@ -22,8 +22,7 @@ import im.vector.matrix.android.internal.crypto.MXCRYPTO_ALGORITHM_OLM import im.vector.matrix.android.internal.crypto.MXOlmDevice import im.vector.matrix.android.internal.crypto.model.MXDeviceInfo import im.vector.matrix.android.internal.crypto.model.rest.EncryptedMessage -import im.vector.matrix.android.internal.di.MoshiProvider -import im.vector.matrix.android.internal.session.SessionScope +import im.vector.matrix.android.internal.util.JsonCanonicalizer import im.vector.matrix.android.internal.util.convertToUTF8 import timber.log.Timber import java.util.* @@ -81,7 +80,7 @@ internal class MessageEncrypter @Inject constructor(private val credentials: Cre recipientsKeysMap["ed25519"] = deviceInfo.fingerprint()!! payloadJson["recipient_keys"] = recipientsKeysMap - val payloadString = convertToUTF8(MoshiProvider.getCanonicalJson(Map::class.java, payloadJson)) + val payloadString = convertToUTF8(JsonCanonicalizer.getCanonicalJson(Map::class.java, payloadJson)) ciphertext[deviceKey] = olmDevice.encryptMessage(deviceKey, sessionId!!, payloadString!!)!! } } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/algorithms/megolm/MXMegolmEncryption.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/algorithms/megolm/MXMegolmEncryption.kt index ca9a105eaa..165fc73674 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/algorithms/megolm/MXMegolmEncryption.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/algorithms/megolm/MXMegolmEncryption.kt @@ -36,7 +36,7 @@ import im.vector.matrix.android.internal.crypto.model.MXUsersDevicesMap import im.vector.matrix.android.internal.crypto.repository.WarnOnUnknownDeviceRepository import im.vector.matrix.android.internal.crypto.store.IMXCryptoStore import im.vector.matrix.android.internal.crypto.tasks.SendToDeviceTask -import im.vector.matrix.android.internal.di.MoshiProvider +import im.vector.matrix.android.internal.util.JsonCanonicalizer import im.vector.matrix.android.internal.util.convertToUTF8 import timber.log.Timber import java.util.* @@ -263,7 +263,7 @@ internal class MXMegolmEncryption( // Get canonical Json from - val payloadString = convertToUTF8(MoshiProvider.getCanonicalJson(Map::class.java, payloadJson)) + val payloadString = convertToUTF8(JsonCanonicalizer.getCanonicalJson(Map::class.java, payloadJson)) val ciphertext = olmDevice.encryptGroupMessage(session.sessionId, payloadString!!) val map = HashMap() diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/KeysBackup.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/KeysBackup.kt index 5d4a950492..9350fd448e 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/KeysBackup.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/keysbackup/KeysBackup.kt @@ -55,6 +55,7 @@ import im.vector.matrix.android.internal.task.Task import im.vector.matrix.android.internal.task.TaskExecutor import im.vector.matrix.android.internal.task.TaskThread import im.vector.matrix.android.internal.task.configureWith +import im.vector.matrix.android.internal.util.JsonCanonicalizer import im.vector.matrix.android.internal.util.MatrixCoroutineDispatchers import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch @@ -176,7 +177,7 @@ internal class KeysBackup @Inject constructor( megolmBackupAuthData.publicKey = publicKey } - val canonicalJson = MoshiProvider.getCanonicalJson(Map::class.java, megolmBackupAuthData.signalableJSONDictionary()) + val canonicalJson = JsonCanonicalizer.getCanonicalJson(Map::class.java, megolmBackupAuthData.signalableJSONDictionary()) megolmBackupAuthData.signatures = objectSigner.signObject(canonicalJson) @@ -456,7 +457,7 @@ internal class KeysBackup @Inject constructor( if (trust) { // Add current device signature - val canonicalJson = MoshiProvider.getCanonicalJson(Map::class.java, authData.signalableJSONDictionary()) + val canonicalJson = JsonCanonicalizer.getCanonicalJson(Map::class.java, authData.signalableJSONDictionary()) val deviceSignatures = objectSigner.signObject(canonicalJson) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/IncomingSASVerificationTransaction.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/IncomingSASVerificationTransaction.kt index 2a4f0a1dde..641062d7f2 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/IncomingSASVerificationTransaction.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/IncomingSASVerificationTransaction.kt @@ -29,8 +29,8 @@ import im.vector.matrix.android.internal.crypto.model.rest.KeyVerificationMac import im.vector.matrix.android.internal.crypto.model.rest.KeyVerificationStart import im.vector.matrix.android.internal.crypto.store.IMXCryptoStore import im.vector.matrix.android.internal.crypto.tasks.SendToDeviceTask -import im.vector.matrix.android.internal.di.MoshiProvider import im.vector.matrix.android.internal.task.TaskExecutor +import im.vector.matrix.android.internal.util.JsonCanonicalizer import timber.log.Timber internal class IncomingSASVerificationTransaction( @@ -147,7 +147,7 @@ internal class IncomingSASVerificationTransaction( //The hash commitment is the hash (using the selected hash algorithm) of the unpadded base64 representation of QB, // concatenated with the canonical JSON representation of the content of the m.key.verification.start message - val concat = getSAS().publicKey + MoshiProvider.getCanonicalJson(KeyVerificationStart::class.java, startReq!!) + val concat = getSAS().publicKey + JsonCanonicalizer.getCanonicalJson(KeyVerificationStart::class.java, startReq!!) accept.commitment = hashUsingAgreedHashMethod(concat) ?: "" //we need to send this to other device now state = SasVerificationTxState.SendingAccept diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/OutgoingSASVerificationRequest.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/OutgoingSASVerificationRequest.kt index a33f8878a8..0500be5426 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/OutgoingSASVerificationRequest.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/OutgoingSASVerificationRequest.kt @@ -27,8 +27,8 @@ import im.vector.matrix.android.internal.crypto.model.rest.KeyVerificationMac import im.vector.matrix.android.internal.crypto.model.rest.KeyVerificationStart import im.vector.matrix.android.internal.crypto.store.IMXCryptoStore import im.vector.matrix.android.internal.crypto.tasks.SendToDeviceTask -import im.vector.matrix.android.internal.di.MoshiProvider import im.vector.matrix.android.internal.task.TaskExecutor +import im.vector.matrix.android.internal.util.JsonCanonicalizer import timber.log.Timber internal class OutgoingSASVerificationRequest( @@ -164,7 +164,7 @@ internal class OutgoingSASVerificationRequest( // in Bob’s m.key.verification.key and the content of Alice’s m.key.verification.start message. //check commitment - val concat = vKey.key + MoshiProvider.getCanonicalJson(KeyVerificationStart::class.java, startReq!!) + val concat = vKey.key + JsonCanonicalizer.getCanonicalJson(KeyVerificationStart::class.java, startReq!!) val otherCommitment = hashUsingAgreedHashMethod(concat) ?: "" if (accepted!!.commitment.equals(otherCommitment)) { diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/helper/ChunkEntityHelper.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/helper/ChunkEntityHelper.kt index 8e877f89ce..af8317aaa7 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/helper/ChunkEntityHelper.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/helper/ChunkEntityHelper.kt @@ -16,6 +16,7 @@ package im.vector.matrix.android.internal.database.helper +import androidx.annotation.VisibleForTesting import im.vector.matrix.android.api.session.events.model.Event import im.vector.matrix.android.api.session.events.model.EventType import im.vector.matrix.android.api.session.room.send.SendState @@ -102,11 +103,12 @@ internal fun ChunkEntity.updateSenderDataFor(eventIds: List) { } } -private fun ChunkEntity.add(roomId: String, - event: Event, - direction: PaginationDirection, - stateIndexOffset: Int = 0, - isUnlinked: Boolean = false) { +@VisibleForTesting +internal fun ChunkEntity.add(roomId: String, + event: Event, + direction: PaginationDirection, + stateIndexOffset: Int = 0, + isUnlinked: Boolean = false) { assertIsManaged() if (event.eventId != null && timelineEvents.find(event.eventId) != null) { @@ -149,14 +151,14 @@ private fun ChunkEntity.add(roomId: String, internal fun ChunkEntity.lastDisplayIndex(direction: PaginationDirection, defaultValue: Int = 0): Int { return when (direction) { - PaginationDirection.FORWARDS -> forwardsDisplayIndex - PaginationDirection.BACKWARDS -> backwardsDisplayIndex - } ?: defaultValue + PaginationDirection.FORWARDS -> forwardsDisplayIndex + PaginationDirection.BACKWARDS -> backwardsDisplayIndex + } ?: defaultValue } internal fun ChunkEntity.lastStateIndex(direction: PaginationDirection, defaultValue: Int = 0): Int { return when (direction) { - PaginationDirection.FORWARDS -> forwardsStateIndex - PaginationDirection.BACKWARDS -> backwardsStateIndex - } ?: defaultValue + PaginationDirection.FORWARDS -> forwardsStateIndex + PaginationDirection.BACKWARDS -> backwardsStateIndex + } ?: defaultValue } \ No newline at end of file diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/MoshiProvider.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/MoshiProvider.kt index 3849a2f749..e430329892 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/MoshiProvider.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/di/MoshiProvider.kt @@ -23,7 +23,6 @@ import im.vector.matrix.android.internal.network.parsing.UriMoshiAdapter import im.vector.matrix.android.internal.session.sync.model.UserAccountData import im.vector.matrix.android.internal.session.sync.model.UserAccountDataDirectMessages import im.vector.matrix.android.internal.session.sync.model.UserAccountDataFallback -import im.vector.matrix.android.internal.util.JsonCanonicalizer object MoshiProvider { @@ -50,19 +49,6 @@ object MoshiProvider { return moshi } - // TODO Move - fun getCanonicalJson(type: Class, o: T): String { - val adapter = moshi.adapter(type) - - val json = adapter.toJson(o) - - // Canonicalize manually - val can = JsonCanonicalizer.canonicalize(json) - - val jsonSafe = can.replace("\\/", "/") - - return jsonSafe - } } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/util/JsonCanonicalizer.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/util/JsonCanonicalizer.kt index f7fd3cf4f6..2bf7820114 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/util/JsonCanonicalizer.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/util/JsonCanonicalizer.kt @@ -16,6 +16,8 @@ package im.vector.matrix.android.internal.util +import androidx.annotation.VisibleForTesting +import im.vector.matrix.android.internal.di.MoshiProvider import org.json.JSONArray import org.json.JSONException import org.json.JSONObject @@ -28,22 +30,24 @@ import java.util.* */ object JsonCanonicalizer { - fun canonicalize(json: String): String { - var can: String? = null - try { - val _json = JSONObject(json) + fun getCanonicalJson(type: Class, o: T): String { + val adapter = MoshiProvider.providesMoshi().adapter(type) - can = _canonicalize(_json) + // Canonicalize manually + return canonicalize(adapter.toJson(o)) + .replace("\\/", "/") + } + + @VisibleForTesting + fun canonicalize(jsonString: String): String { + return try { + val jsonObject = JSONObject(jsonString) + + canonicalizeRecursive(jsonObject) } catch (e: JSONException) { Timber.e(e, "Unable to canonicalize") + jsonString } - - if (can == null) { - Timber.e("Error") - return json - } - - return can } /** @@ -52,11 +56,8 @@ object JsonCanonicalizer { * @param src the src * @return the canonicalize element */ - private fun _canonicalize(src: Any?): String? { + private fun canonicalizeRecursive(src: Any): String { // sanity check - if (null == src) { - return null - } when (src) { is JSONArray -> { @@ -65,7 +66,7 @@ object JsonCanonicalizer { val result = StringBuilder("[") for (i in 0 until srcArray!!.length()) { - result.append(_canonicalize(srcArray.get(i))) + result.append(canonicalizeRecursive(srcArray.get(i))) if (i < srcArray.length() - 1) { result.append(",") } @@ -89,7 +90,7 @@ object JsonCanonicalizer { .append(attribute.value) .append("\"") .append(":") - .append(_canonicalize(src[attribute.value])) + .append(canonicalizeRecursive(src[attribute.value])) if (attribute.index < attributes.size - 1) { result.append(",")