mirror of
https://github.com/SchildiChat/SchildiChat-android.git
synced 2024-11-26 19:36:08 +03:00
WIP
This commit is contained in:
parent
102bc9c01b
commit
a2210a6b0d
12 changed files with 111 additions and 78 deletions
|
@ -26,8 +26,7 @@ import im.vector.matrix.android.internal.crypto.MXEventDecryptionResult
|
||||||
import im.vector.matrix.android.internal.di.MoshiProvider
|
import im.vector.matrix.android.internal.di.MoshiProvider
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import java.lang.reflect.ParameterizedType
|
import java.lang.reflect.ParameterizedType
|
||||||
import java.util.ArrayList
|
import java.util.*
|
||||||
import java.util.HashMap
|
|
||||||
|
|
||||||
typealias Content = JsonDict
|
typealias Content = JsonDict
|
||||||
|
|
||||||
|
@ -94,7 +93,8 @@ data class Event(
|
||||||
* This is a small MXEvent instance with typically value for `type` and 'content' fields.
|
* This is a small MXEvent instance with typically value for `type` and 'content' fields.
|
||||||
*/
|
*/
|
||||||
@Transient
|
@Transient
|
||||||
private var mClearEvent: Event? = null
|
var mClearEvent: Event? = null
|
||||||
|
private set
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Curve25519 key which we believe belongs to the sender of the event.
|
* Curve25519 key which we believe belongs to the sender of the event.
|
||||||
|
@ -121,7 +121,8 @@ data class Event(
|
||||||
* Decryption error
|
* Decryption error
|
||||||
*/
|
*/
|
||||||
@Transient
|
@Transient
|
||||||
private var mCryptoError: MXCryptoError? = null
|
var mCryptoError: MXCryptoError? = null
|
||||||
|
private set
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return true if this event is encrypted.
|
* @return true if this event is encrypted.
|
||||||
|
@ -141,16 +142,16 @@ data class Event(
|
||||||
mClearEvent = null
|
mClearEvent = null
|
||||||
|
|
||||||
if (null != decryptionResult) {
|
if (null != decryptionResult) {
|
||||||
if (null != decryptionResult!!.mClearEvent) {
|
if (null != decryptionResult.mClearEvent) {
|
||||||
mClearEvent = decryptionResult!!.mClearEvent
|
mClearEvent = decryptionResult.mClearEvent
|
||||||
}
|
}
|
||||||
|
|
||||||
if (null != mClearEvent) {
|
if (null != mClearEvent) {
|
||||||
mClearEvent!!.mSenderCurve25519Key = decryptionResult!!.mSenderCurve25519Key
|
mClearEvent!!.mSenderCurve25519Key = decryptionResult.mSenderCurve25519Key
|
||||||
mClearEvent!!.mClaimedEd25519Key = decryptionResult!!.mClaimedEd25519Key
|
mClearEvent!!.mClaimedEd25519Key = decryptionResult.mClaimedEd25519Key
|
||||||
|
|
||||||
if (null != decryptionResult!!.mForwardingCurve25519KeyChain) {
|
if (null != decryptionResult.mForwardingCurve25519KeyChain) {
|
||||||
mClearEvent!!.mForwardingCurve25519KeyChain = decryptionResult!!.mForwardingCurve25519KeyChain
|
mClearEvent!!.mForwardingCurve25519KeyChain = decryptionResult.mForwardingCurve25519KeyChain
|
||||||
} else {
|
} else {
|
||||||
mClearEvent!!.mForwardingCurve25519KeyChain = ArrayList()
|
mClearEvent!!.mForwardingCurve25519KeyChain = ArrayList()
|
||||||
}
|
}
|
||||||
|
@ -163,7 +164,7 @@ data class Event(
|
||||||
// .add("m.relates_to", getWireContent().getAsJsonObject().get("m.relates_to"))
|
// .add("m.relates_to", getWireContent().getAsJsonObject().get("m.relates_to"))
|
||||||
//}
|
//}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Timber.e(e,"Unable to restore 'm.relates_to' the clear event")
|
Timber.e(e, "Unable to restore 'm.relates_to' the clear event")
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -151,7 +151,7 @@ internal class CryptoManager(
|
||||||
|
|
||||||
fun onLiveEvent(roomId: String, event: Event) {
|
fun onLiveEvent(roomId: String, event: Event) {
|
||||||
if (event.type == EventType.ENCRYPTION) {
|
if (event.type == EventType.ENCRYPTION) {
|
||||||
onCryptoEvent(roomId, event)
|
onRoomEncryptionEvent(roomId, event)
|
||||||
} else if (event.type == EventType.STATE_ROOM_MEMBER) {
|
} else if (event.type == EventType.STATE_ROOM_MEMBER) {
|
||||||
onRoomMembershipEvent(roomId, event)
|
onRoomMembershipEvent(roomId, event)
|
||||||
}
|
}
|
||||||
|
@ -206,7 +206,7 @@ internal class CryptoManager(
|
||||||
mCryptoConfig = MXCryptoConfig()
|
mCryptoConfig = MXCryptoConfig()
|
||||||
}
|
}
|
||||||
|
|
||||||
mRoomEncryptors = HashMap()
|
mRoomEncryptors = HashMap() // TODO Merge with declaration
|
||||||
|
|
||||||
var deviceId = mCredentials.deviceId
|
var deviceId = mCredentials.deviceId
|
||||||
// deviceId should always be defined
|
// deviceId should always be defined
|
||||||
|
@ -770,6 +770,7 @@ internal class CryptoManager(
|
||||||
|
|
||||||
alg.initWithMatrixSession(this,
|
alg.initWithMatrixSession(this,
|
||||||
mOlmDevice,
|
mOlmDevice,
|
||||||
|
mKeysBackup,
|
||||||
deviceListManager,
|
deviceListManager,
|
||||||
mCredentials,
|
mCredentials,
|
||||||
mSendToDeviceTask,
|
mSendToDeviceTask,
|
||||||
|
@ -1146,7 +1147,7 @@ internal class CryptoManager(
|
||||||
|
|
||||||
getDecryptingThreadHandler().post {
|
getDecryptingThreadHandler().post {
|
||||||
var result: MXEventDecryptionResult? = null
|
var result: MXEventDecryptionResult? = null
|
||||||
val alg = roomDecryptorProvider.getRoomDecryptor(event.roomId, eventContent["algorithm"] as String)
|
val alg = roomDecryptorProvider.getOrCreateRoomDecryptor(this, event.roomId, eventContent["algorithm"] as String)
|
||||||
|
|
||||||
if (null == alg) {
|
if (null == alg) {
|
||||||
val reason = String.format(MXCryptoError.UNABLE_TO_DECRYPT_REASON, event.eventId, eventContent["algorithm"] as String)
|
val reason = String.format(MXCryptoError.UNABLE_TO_DECRYPT_REASON, event.eventId, eventContent["algorithm"] as String)
|
||||||
|
@ -1342,7 +1343,8 @@ internal class CryptoManager(
|
||||||
*
|
*
|
||||||
* @param event the encryption event.
|
* @param event the encryption event.
|
||||||
*/
|
*/
|
||||||
fun onCryptoEvent(roomId: String, event: Event) {
|
private fun onRoomEncryptionEvent(roomId: String, event: Event) {
|
||||||
|
// TODO Parse the event
|
||||||
val eventContent = event.content // wireEventContent
|
val eventContent = event.content // wireEventContent
|
||||||
|
|
||||||
val room = mRoomService.getRoom(roomId)!!
|
val room = mRoomService.getRoom(roomId)!!
|
||||||
|
@ -1520,7 +1522,7 @@ internal class CryptoManager(
|
||||||
// But that message might never arrive leaving us stuck with duff
|
// But that message might never arrive leaving us stuck with duff
|
||||||
// private keys clogging up our local storage.
|
// private keys clogging up our local storage.
|
||||||
// So we need some kind of enginering compromise to balance all of
|
// So we need some kind of enginering compromise to balance all of
|
||||||
// these factors.
|
// these factors. // TODO Why we do not set mOneTimeKeyCount here?
|
||||||
val keyCount = data.oneTimeKeyCountsForAlgorithm(MXKey.KEY_SIGNED_CURVE_25519_TYPE)
|
val keyCount = data.oneTimeKeyCountsForAlgorithm(MXKey.KEY_SIGNED_CURVE_25519_TYPE)
|
||||||
uploadOTK(keyCount, keyLimit, callback)
|
uploadOTK(keyCount, keyLimit, callback)
|
||||||
}
|
}
|
||||||
|
@ -1765,7 +1767,7 @@ internal class CryptoManager(
|
||||||
cpt++
|
cpt++
|
||||||
|
|
||||||
|
|
||||||
val decrypting = roomDecryptorProvider.getRoomDecryptor(megolmSessionData.roomId, megolmSessionData.algorithm)
|
val decrypting = roomDecryptorProvider.getOrCreateRoomDecryptor(this, megolmSessionData.roomId, megolmSessionData.algorithm)
|
||||||
|
|
||||||
if (null != decrypting) {
|
if (null != decrypting) {
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -51,10 +51,10 @@ internal class MXOlmDevice(
|
||||||
var deviceEd25519Key: String? = null
|
var deviceEd25519Key: String? = null
|
||||||
private set
|
private set
|
||||||
|
|
||||||
// The OLMKit account instance.
|
// The OLM lib account instance.
|
||||||
private var mOlmAccount: OlmAccount? = null
|
private var mOlmAccount: OlmAccount? = null
|
||||||
|
|
||||||
// The OLMKit utility instance.
|
// The OLM lib utility instance.
|
||||||
private var mOlmUtility: OlmUtility? = null
|
private var mOlmUtility: OlmUtility? = null
|
||||||
|
|
||||||
// The outbound group session.
|
// The outbound group session.
|
||||||
|
@ -144,9 +144,7 @@ internal class MXOlmDevice(
|
||||||
* Release the instance
|
* Release the instance
|
||||||
*/
|
*/
|
||||||
fun release() {
|
fun release() {
|
||||||
if (null != mOlmAccount) {
|
mOlmAccount?.releaseAccount()
|
||||||
mOlmAccount!!.releaseAccount()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -265,7 +263,7 @@ internal class MXOlmDevice(
|
||||||
|
|
||||||
Timber.d("## createInboundSession() : ciphertext: $ciphertext")
|
Timber.d("## createInboundSession() : ciphertext: $ciphertext")
|
||||||
try {
|
try {
|
||||||
Timber.d("## createInboundSession() :ciphertext: SHA256:" + mOlmUtility!!.sha256(URLEncoder.encode(ciphertext, "utf-8")))
|
Timber.d("## createInboundSession() :ciphertext: SHA256:" + mOlmUtility!!.sha256(URLEncoder.encode(ciphertext, "utf-8"))) // TODO Extract code from the Log method...
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Timber.e(e, "## createInboundSession() :ciphertext: cannot encode ciphertext")
|
Timber.e(e, "## createInboundSession() :ciphertext: cannot encode ciphertext")
|
||||||
}
|
}
|
||||||
|
|
|
@ -298,7 +298,7 @@ internal class MXOutgoingRoomKeyRequestManager(
|
||||||
val contentMap = MXUsersDevicesMap<Any>()
|
val contentMap = MXUsersDevicesMap<Any>()
|
||||||
|
|
||||||
for (recipient in recipients) {
|
for (recipient in recipients) {
|
||||||
contentMap.setObject(message, recipient["userId"], recipient["deviceId"])
|
contentMap.setObject(message, recipient["userId"], recipient["deviceId"]) // TODO Change this two hard coded key to something better
|
||||||
}
|
}
|
||||||
|
|
||||||
mSendToDeviceTask.configureWith(SendToDeviceTask.Params(EventType.ROOM_KEY_REQUEST, contentMap, transactionId))
|
mSendToDeviceTask.configureWith(SendToDeviceTask.Params(EventType.ROOM_KEY_REQUEST, contentMap, transactionId))
|
||||||
|
|
|
@ -33,7 +33,7 @@ internal class RoomDecryptorProvider(
|
||||||
) {
|
) {
|
||||||
|
|
||||||
// A map from algorithm to MXDecrypting instance, for each room
|
// A map from algorithm to MXDecrypting instance, for each room
|
||||||
private val mRoomDecryptors: MutableMap<String, MutableMap<String /* algorithm */, IMXDecrypting>>/* room id */ = HashMap()
|
private val mRoomDecryptors: MutableMap<String /* room id */, MutableMap<String /* algorithm */, IMXDecrypting>> = HashMap()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a decryptor for a given room and algorithm.
|
* Get a decryptor for a given room and algorithm.
|
||||||
|
@ -43,7 +43,7 @@ internal class RoomDecryptorProvider(
|
||||||
* @param roomId the room id
|
* @param roomId the room id
|
||||||
* @param algorithm the crypto algorithm
|
* @param algorithm the crypto algorithm
|
||||||
* @return the decryptor
|
* @return the decryptor
|
||||||
* TODO do not provide cryptoManager?
|
* TODO do not provide cryptoManager? // TODO Create another method for the case of roomId is null
|
||||||
*/
|
*/
|
||||||
fun getOrCreateRoomDecryptor(cryptoManager: CryptoManager, roomId: String?, algorithm: String?): IMXDecrypting? {
|
fun getOrCreateRoomDecryptor(cryptoManager: CryptoManager, roomId: String?, algorithm: String?): IMXDecrypting? {
|
||||||
// sanity check
|
// sanity check
|
||||||
|
|
|
@ -23,6 +23,7 @@ import im.vector.matrix.android.api.session.events.model.Content
|
||||||
import im.vector.matrix.android.internal.crypto.DeviceListManager
|
import im.vector.matrix.android.internal.crypto.DeviceListManager
|
||||||
import im.vector.matrix.android.internal.crypto.MXOlmDevice
|
import im.vector.matrix.android.internal.crypto.MXOlmDevice
|
||||||
import im.vector.matrix.android.internal.crypto.CryptoManager
|
import im.vector.matrix.android.internal.crypto.CryptoManager
|
||||||
|
import im.vector.matrix.android.internal.crypto.keysbackup.KeysBackup
|
||||||
import im.vector.matrix.android.internal.crypto.tasks.SendToDeviceTask
|
import im.vector.matrix.android.internal.crypto.tasks.SendToDeviceTask
|
||||||
import im.vector.matrix.android.internal.task.TaskExecutor
|
import im.vector.matrix.android.internal.task.TaskExecutor
|
||||||
|
|
||||||
|
@ -39,6 +40,7 @@ internal interface IMXEncrypting {
|
||||||
*/
|
*/
|
||||||
fun initWithMatrixSession(crypto: CryptoManager,
|
fun initWithMatrixSession(crypto: CryptoManager,
|
||||||
olmDevice: MXOlmDevice,
|
olmDevice: MXOlmDevice,
|
||||||
|
keysBackup: KeysBackup,
|
||||||
deviceListManager: DeviceListManager,
|
deviceListManager: DeviceListManager,
|
||||||
credentials: Credentials,
|
credentials: Credentials,
|
||||||
sendToDeviceTask: SendToDeviceTask,
|
sendToDeviceTask: SendToDeviceTask,
|
||||||
|
|
|
@ -62,7 +62,7 @@ internal class MXMegolmDecryption : IMXDecrypting {
|
||||||
* Events which we couldn't decrypt due to unknown sessions / indexes: map from
|
* Events which we couldn't decrypt due to unknown sessions / indexes: map from
|
||||||
* senderKey|sessionId to timelines to list of MatrixEvents.
|
* senderKey|sessionId to timelines to list of MatrixEvents.
|
||||||
*/
|
*/
|
||||||
private var mPendingEvents: MutableMap<String, MutableMap<String /* timelineId */, MutableList<Event>>>? = null/* senderKey|sessionId */
|
private var mPendingEvents: MutableMap<String /* senderKey|sessionId */, MutableMap<String /* timelineId */, MutableList<Event>>> = HashMap()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Init the object fields
|
* Init the object fields
|
||||||
|
@ -74,11 +74,11 @@ internal class MXMegolmDecryption : IMXDecrypting {
|
||||||
sendToDeviceTask: SendToDeviceTask,
|
sendToDeviceTask: SendToDeviceTask,
|
||||||
taskExecutor: TaskExecutor) {
|
taskExecutor: TaskExecutor) {
|
||||||
mCredentials = credentials
|
mCredentials = credentials
|
||||||
|
mCrypto = crypto
|
||||||
|
mOlmDevice = olmDevice
|
||||||
mDeviceListManager = deviceListManager
|
mDeviceListManager = deviceListManager
|
||||||
mSendToDeviceTask = sendToDeviceTask
|
mSendToDeviceTask = sendToDeviceTask
|
||||||
mTaskExecutor = taskExecutor
|
mTaskExecutor = taskExecutor
|
||||||
mOlmDevice = olmDevice
|
|
||||||
mPendingEvents = HashMap()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Throws(MXDecryptionException::class)
|
@Throws(MXDecryptionException::class)
|
||||||
|
@ -167,7 +167,7 @@ internal class MXMegolmDecryption : IMXDecrypting {
|
||||||
val recipients = ArrayList<Map<String, String>>()
|
val recipients = ArrayList<Map<String, String>>()
|
||||||
|
|
||||||
val selfMap = HashMap<String, String>()
|
val selfMap = HashMap<String, String>()
|
||||||
selfMap["userId"] = mCredentials.userId
|
selfMap["userId"] = mCredentials.userId // TODO Replace this hard coded keys (see MXOutgoingRoomKeyRequestManager)
|
||||||
selfMap["deviceId"] = "*"
|
selfMap["deviceId"] = "*"
|
||||||
recipients.add(selfMap)
|
recipients.add(selfMap)
|
||||||
|
|
||||||
|
@ -196,27 +196,21 @@ internal class MXMegolmDecryption : IMXDecrypting {
|
||||||
* @param timelineId the timeline identifier
|
* @param timelineId the timeline identifier
|
||||||
*/
|
*/
|
||||||
private fun addEventToPendingList(event: Event, timelineId: String) {
|
private fun addEventToPendingList(event: Event, timelineId: String) {
|
||||||
var timelineId = timelineId
|
|
||||||
val encryptedEventContent = event.content.toModel<EncryptedEventContent>()!!
|
val encryptedEventContent = event.content.toModel<EncryptedEventContent>()!!
|
||||||
|
|
||||||
val k = "${encryptedEventContent.senderKey}|${encryptedEventContent.sessionId}"
|
val k = "${encryptedEventContent.senderKey}|${encryptedEventContent.sessionId}"
|
||||||
|
|
||||||
// avoid undefined timelineId
|
if (!mPendingEvents.containsKey(k)) {
|
||||||
if (TextUtils.isEmpty(timelineId)) {
|
mPendingEvents[k] = HashMap()
|
||||||
timelineId = ""
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mPendingEvents!!.containsKey(k)) {
|
if (!mPendingEvents[k]!!.containsKey(timelineId)) {
|
||||||
mPendingEvents!![k] = HashMap()
|
mPendingEvents[k]!!.put(timelineId, ArrayList<Event>())
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mPendingEvents!![k]!!.containsKey(timelineId)) {
|
if (mPendingEvents[k]!![timelineId]!!.indexOf(event) < 0) {
|
||||||
mPendingEvents!![k]!!.put(timelineId, ArrayList<Event>())
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mPendingEvents!![k]!![timelineId]!!.indexOf(event) < 0) {
|
|
||||||
Timber.d("## addEventToPendingList() : add Event " + event.eventId + " in room id " + event.roomId)
|
Timber.d("## addEventToPendingList() : add Event " + event.eventId + " in room id " + event.roomId)
|
||||||
mPendingEvents!![k]!![timelineId]!!.add(event)
|
mPendingEvents[k]!![timelineId]!!.add(event)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -304,11 +298,11 @@ internal class MXMegolmDecryption : IMXDecrypting {
|
||||||
override fun onNewSession(senderKey: String, sessionId: String) {
|
override fun onNewSession(senderKey: String, sessionId: String) {
|
||||||
val k = "$senderKey|$sessionId"
|
val k = "$senderKey|$sessionId"
|
||||||
|
|
||||||
val pending = mPendingEvents!![k]
|
val pending = mPendingEvents[k]
|
||||||
|
|
||||||
if (null != pending) {
|
if (null != pending) {
|
||||||
// Have another go at decrypting events sent with this session.
|
// Have another go at decrypting events sent with this session.
|
||||||
mPendingEvents!!.remove(k)
|
mPendingEvents.remove(k)
|
||||||
|
|
||||||
val timelineIds = pending.keys
|
val timelineIds = pending.keys
|
||||||
|
|
||||||
|
|
|
@ -27,17 +27,13 @@ import im.vector.matrix.android.api.session.crypto.MXCryptoError
|
||||||
import im.vector.matrix.android.api.session.events.model.Content
|
import im.vector.matrix.android.api.session.events.model.Content
|
||||||
import im.vector.matrix.android.api.session.events.model.EventType
|
import im.vector.matrix.android.api.session.events.model.EventType
|
||||||
import im.vector.matrix.android.api.session.events.model.toContent
|
import im.vector.matrix.android.api.session.events.model.toContent
|
||||||
import im.vector.matrix.android.internal.crypto.CryptoAsyncHelper
|
import im.vector.matrix.android.internal.crypto.*
|
||||||
import im.vector.matrix.android.internal.crypto.DeviceListManager
|
|
||||||
import im.vector.matrix.android.internal.crypto.MXCRYPTO_ALGORITHM_MEGOLM
|
|
||||||
import im.vector.matrix.android.internal.crypto.MXOlmDevice
|
|
||||||
import im.vector.matrix.android.internal.crypto.algorithms.IMXEncrypting
|
import im.vector.matrix.android.internal.crypto.algorithms.IMXEncrypting
|
||||||
|
import im.vector.matrix.android.internal.crypto.keysbackup.KeysBackup
|
||||||
import im.vector.matrix.android.internal.crypto.model.MXDeviceInfo
|
import im.vector.matrix.android.internal.crypto.model.MXDeviceInfo
|
||||||
import im.vector.matrix.android.internal.crypto.model.MXOlmSessionResult
|
import im.vector.matrix.android.internal.crypto.model.MXOlmSessionResult
|
||||||
import im.vector.matrix.android.internal.crypto.model.MXQueuedEncryption
|
import im.vector.matrix.android.internal.crypto.model.MXQueuedEncryption
|
||||||
import im.vector.matrix.android.internal.crypto.model.MXUsersDevicesMap
|
import im.vector.matrix.android.internal.crypto.model.MXUsersDevicesMap
|
||||||
import im.vector.matrix.android.internal.crypto.CryptoManager
|
|
||||||
import im.vector.matrix.android.internal.crypto.keysbackup.KeysBackup
|
|
||||||
import im.vector.matrix.android.internal.crypto.tasks.SendToDeviceTask
|
import im.vector.matrix.android.internal.crypto.tasks.SendToDeviceTask
|
||||||
import im.vector.matrix.android.internal.di.MoshiProvider
|
import im.vector.matrix.android.internal.di.MoshiProvider
|
||||||
import im.vector.matrix.android.internal.task.TaskExecutor
|
import im.vector.matrix.android.internal.task.TaskExecutor
|
||||||
|
@ -51,15 +47,15 @@ internal class MXMegolmEncryption : IMXEncrypting {
|
||||||
|
|
||||||
private lateinit var mCrypto: CryptoManager
|
private lateinit var mCrypto: CryptoManager
|
||||||
private lateinit var olmDevice: MXOlmDevice
|
private lateinit var olmDevice: MXOlmDevice
|
||||||
|
private lateinit var mKeysBackup: KeysBackup
|
||||||
private lateinit var mDeviceListManager: DeviceListManager
|
private lateinit var mDeviceListManager: DeviceListManager
|
||||||
|
|
||||||
private lateinit var mKeysBackup: KeysBackup
|
|
||||||
private lateinit var mCredentials: Credentials
|
private lateinit var mCredentials: Credentials
|
||||||
private lateinit var mSendToDeviceTask: SendToDeviceTask
|
private lateinit var mSendToDeviceTask: SendToDeviceTask
|
||||||
private lateinit var mTaskExecutor: TaskExecutor
|
private lateinit var mTaskExecutor: TaskExecutor
|
||||||
|
|
||||||
// The id of the room we will be sending to.
|
// The id of the room we will be sending to.
|
||||||
private var mRoomId: String? = null
|
private lateinit var mRoomId: String
|
||||||
|
|
||||||
private var mDeviceId: String? = null
|
private var mDeviceId: String? = null
|
||||||
|
|
||||||
|
@ -93,6 +89,7 @@ internal class MXMegolmEncryption : IMXEncrypting {
|
||||||
|
|
||||||
override fun initWithMatrixSession(crypto: CryptoManager,
|
override fun initWithMatrixSession(crypto: CryptoManager,
|
||||||
olmDevice: MXOlmDevice,
|
olmDevice: MXOlmDevice,
|
||||||
|
keysBackup: KeysBackup,
|
||||||
deviceListManager: DeviceListManager,
|
deviceListManager: DeviceListManager,
|
||||||
credentials: Credentials,
|
credentials: Credentials,
|
||||||
sendToDeviceTask: SendToDeviceTask,
|
sendToDeviceTask: SendToDeviceTask,
|
||||||
|
@ -101,6 +98,7 @@ internal class MXMegolmEncryption : IMXEncrypting {
|
||||||
mCrypto = crypto
|
mCrypto = crypto
|
||||||
this.olmDevice = olmDevice
|
this.olmDevice = olmDevice
|
||||||
mDeviceListManager = deviceListManager
|
mDeviceListManager = deviceListManager
|
||||||
|
mKeysBackup = keysBackup
|
||||||
mCredentials = credentials
|
mCredentials = credentials
|
||||||
mSendToDeviceTask = sendToDeviceTask
|
mSendToDeviceTask = sendToDeviceTask
|
||||||
mTaskExecutor = taskExecutor
|
mTaskExecutor = taskExecutor
|
||||||
|
@ -108,6 +106,7 @@ internal class MXMegolmEncryption : IMXEncrypting {
|
||||||
mRoomId = roomId
|
mRoomId = roomId
|
||||||
mDeviceId = mCredentials.deviceId
|
mDeviceId = mCredentials.deviceId
|
||||||
|
|
||||||
|
|
||||||
// Default rotation periods
|
// Default rotation periods
|
||||||
// TODO: Make it configurable via parameters
|
// TODO: Make it configurable via parameters
|
||||||
mSessionRotationPeriodMsgs = 100
|
mSessionRotationPeriodMsgs = 100
|
||||||
|
|
|
@ -25,10 +25,9 @@ import im.vector.matrix.android.api.session.events.model.Event
|
||||||
import im.vector.matrix.android.api.session.events.model.toModel
|
import im.vector.matrix.android.api.session.events.model.toModel
|
||||||
import im.vector.matrix.android.internal.crypto.*
|
import im.vector.matrix.android.internal.crypto.*
|
||||||
import im.vector.matrix.android.internal.crypto.algorithms.IMXDecrypting
|
import im.vector.matrix.android.internal.crypto.algorithms.IMXDecrypting
|
||||||
import im.vector.matrix.android.internal.crypto.store.IMXCryptoStore
|
|
||||||
import im.vector.matrix.android.internal.crypto.CryptoManager
|
|
||||||
import im.vector.matrix.android.internal.crypto.model.event.OlmEventContent
|
import im.vector.matrix.android.internal.crypto.model.event.OlmEventContent
|
||||||
import im.vector.matrix.android.internal.crypto.model.event.OlmPayloadContent
|
import im.vector.matrix.android.internal.crypto.model.event.OlmPayloadContent
|
||||||
|
import im.vector.matrix.android.internal.crypto.store.IMXCryptoStore
|
||||||
import im.vector.matrix.android.internal.crypto.tasks.SendToDeviceTask
|
import im.vector.matrix.android.internal.crypto.tasks.SendToDeviceTask
|
||||||
import im.vector.matrix.android.internal.task.TaskExecutor
|
import im.vector.matrix.android.internal.task.TaskExecutor
|
||||||
import im.vector.matrix.android.internal.util.convertFromUTF8
|
import im.vector.matrix.android.internal.util.convertFromUTF8
|
||||||
|
@ -42,7 +41,7 @@ import java.util.*
|
||||||
internal class MXOlmDecryption : IMXDecrypting {
|
internal class MXOlmDecryption : IMXDecrypting {
|
||||||
|
|
||||||
// The olm device interface
|
// The olm device interface
|
||||||
private var mOlmDevice: MXOlmDevice? = null
|
private lateinit var mOlmDevice: MXOlmDevice
|
||||||
|
|
||||||
// the matrix credentials
|
// the matrix credentials
|
||||||
private lateinit var mCredentials: Credentials
|
private lateinit var mCredentials: Credentials
|
||||||
|
@ -60,9 +59,9 @@ internal class MXOlmDecryption : IMXDecrypting {
|
||||||
taskExecutor: TaskExecutor) {
|
taskExecutor: TaskExecutor) {
|
||||||
mCredentials = credentials
|
mCredentials = credentials
|
||||||
mCrypto = crypto
|
mCrypto = crypto
|
||||||
|
mOlmDevice = olmDevice
|
||||||
mSendToDeviceTask = sendToDeviceTask
|
mSendToDeviceTask = sendToDeviceTask
|
||||||
mTaskExecutor = taskExecutor
|
mTaskExecutor = taskExecutor
|
||||||
mOlmDevice = olmDevice
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Throws(MXDecryptionException::class)
|
@Throws(MXDecryptionException::class)
|
||||||
|
@ -81,15 +80,15 @@ internal class MXOlmDecryption : IMXDecrypting {
|
||||||
MXCryptoError.UNABLE_TO_DECRYPT, MXCryptoError.MISSING_CIPHER_TEXT_REASON))
|
MXCryptoError.UNABLE_TO_DECRYPT, MXCryptoError.MISSING_CIPHER_TEXT_REASON))
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!olmEventContent.ciphertext!!.containsKey(mOlmDevice!!.deviceCurve25519Key)) {
|
if (!olmEventContent.ciphertext!!.containsKey(mOlmDevice.deviceCurve25519Key)) {
|
||||||
Timber.e("## decryptEvent() : our device " + mOlmDevice!!.deviceCurve25519Key
|
Timber.e("## decryptEvent() : our device " + mOlmDevice.deviceCurve25519Key
|
||||||
+ " is not included in recipients. Event")
|
+ " is not included in recipients. Event")
|
||||||
throw MXDecryptionException(MXCryptoError(MXCryptoError.NOT_INCLUDE_IN_RECIPIENTS_ERROR_CODE,
|
throw MXDecryptionException(MXCryptoError(MXCryptoError.NOT_INCLUDE_IN_RECIPIENTS_ERROR_CODE,
|
||||||
MXCryptoError.UNABLE_TO_DECRYPT, MXCryptoError.NOT_INCLUDED_IN_RECIPIENT_REASON))
|
MXCryptoError.UNABLE_TO_DECRYPT, MXCryptoError.NOT_INCLUDED_IN_RECIPIENT_REASON))
|
||||||
}
|
}
|
||||||
|
|
||||||
// The message for myUser
|
// The message for myUser
|
||||||
val message = olmEventContent.ciphertext!![mOlmDevice!!.deviceCurve25519Key] as Map<String, Any>
|
val message = olmEventContent.ciphertext!![mOlmDevice.deviceCurve25519Key] as Map<String, Any>
|
||||||
val payloadString = decryptMessage(message, olmEventContent.senderKey)
|
val payloadString = decryptMessage(message, olmEventContent.senderKey)
|
||||||
|
|
||||||
if (null == payloadString) {
|
if (null == payloadString) {
|
||||||
|
@ -131,7 +130,7 @@ internal class MXOlmDecryption : IMXDecrypting {
|
||||||
|
|
||||||
val ed25519 = olmPayloadContent.recipient_keys!!.get("ed25519")
|
val ed25519 = olmPayloadContent.recipient_keys!!.get("ed25519")
|
||||||
|
|
||||||
if (!TextUtils.equals(ed25519, mOlmDevice!!.deviceEd25519Key)) {
|
if (!TextUtils.equals(ed25519, mOlmDevice.deviceEd25519Key)) {
|
||||||
Timber.e("## decryptEvent() : Event " + event.eventId + ": Intended recipient ed25519 key " + ed25519 + " did not match ours")
|
Timber.e("## decryptEvent() : Event " + event.eventId + ": Intended recipient ed25519 key " + ed25519 + " did not match ours")
|
||||||
throw MXDecryptionException(MXCryptoError(MXCryptoError.BAD_RECIPIENT_KEY_ERROR_CODE,
|
throw MXDecryptionException(MXCryptoError(MXCryptoError.BAD_RECIPIENT_KEY_ERROR_CODE,
|
||||||
MXCryptoError.UNABLE_TO_DECRYPT, MXCryptoError.BAD_RECIPIENT_KEY_REASON))
|
MXCryptoError.UNABLE_TO_DECRYPT, MXCryptoError.BAD_RECIPIENT_KEY_REASON))
|
||||||
|
@ -194,7 +193,7 @@ internal class MXOlmDecryption : IMXDecrypting {
|
||||||
* @return payload, if decrypted successfully.
|
* @return payload, if decrypted successfully.
|
||||||
*/
|
*/
|
||||||
private fun decryptMessage(message: Map<String, Any>, theirDeviceIdentityKey: String?): String? {
|
private fun decryptMessage(message: Map<String, Any>, theirDeviceIdentityKey: String?): String? {
|
||||||
val sessionIdsSet = mOlmDevice!!.getSessionIds(theirDeviceIdentityKey!!)
|
val sessionIdsSet = mOlmDevice.getSessionIds(theirDeviceIdentityKey!!)
|
||||||
|
|
||||||
val sessionIds: List<String>
|
val sessionIds: List<String>
|
||||||
|
|
||||||
|
@ -226,13 +225,13 @@ internal class MXOlmDecryption : IMXDecrypting {
|
||||||
// Try each session in turn
|
// Try each session in turn
|
||||||
// decryptionErrors = {};
|
// decryptionErrors = {};
|
||||||
for (sessionId in sessionIds) {
|
for (sessionId in sessionIds) {
|
||||||
val payload = mOlmDevice!!.decryptMessage(messageBody, messageType, sessionId, theirDeviceIdentityKey)
|
val payload = mOlmDevice.decryptMessage(messageBody, messageType, sessionId, theirDeviceIdentityKey)
|
||||||
|
|
||||||
if (null != payload) {
|
if (null != payload) {
|
||||||
Timber.d("## decryptMessage() : Decrypted Olm message from $theirDeviceIdentityKey with session $sessionId")
|
Timber.d("## decryptMessage() : Decrypted Olm message from $theirDeviceIdentityKey with session $sessionId")
|
||||||
return payload
|
return payload
|
||||||
} else {
|
} else {
|
||||||
val foundSession = mOlmDevice!!.matchesSession(theirDeviceIdentityKey, sessionId, messageType, messageBody)
|
val foundSession = mOlmDevice.matchesSession(theirDeviceIdentityKey, sessionId, messageType, messageBody)
|
||||||
|
|
||||||
if (foundSession) {
|
if (foundSession) {
|
||||||
// Decryption failed, but it was a prekey message matching this
|
// Decryption failed, but it was a prekey message matching this
|
||||||
|
@ -258,7 +257,7 @@ internal class MXOlmDecryption : IMXDecrypting {
|
||||||
|
|
||||||
// prekey message which doesn't match any existing sessions: make a new
|
// prekey message which doesn't match any existing sessions: make a new
|
||||||
// session.
|
// session.
|
||||||
val res = mOlmDevice!!.createInboundSession(theirDeviceIdentityKey, messageType, messageBody)
|
val res = mOlmDevice.createInboundSession(theirDeviceIdentityKey, messageType, messageBody)
|
||||||
|
|
||||||
if (null == res) {
|
if (null == res) {
|
||||||
Timber.e("## decryptMessage() : Error decrypting non-prekey message with existing sessions")
|
Timber.e("## decryptMessage() : Error decrypting non-prekey message with existing sessions")
|
||||||
|
@ -269,8 +268,4 @@ internal class MXOlmDecryption : IMXDecrypting {
|
||||||
|
|
||||||
return res["payload"]
|
return res["payload"]
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
|
||||||
private val LOG_TAG = "MXOlmDecryption"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,13 +24,14 @@ import im.vector.matrix.android.api.MatrixCallback
|
||||||
import im.vector.matrix.android.api.auth.data.Credentials
|
import im.vector.matrix.android.api.auth.data.Credentials
|
||||||
import im.vector.matrix.android.api.session.events.model.Content
|
import im.vector.matrix.android.api.session.events.model.Content
|
||||||
import im.vector.matrix.android.api.session.events.model.toContent
|
import im.vector.matrix.android.api.session.events.model.toContent
|
||||||
|
import im.vector.matrix.android.internal.crypto.CryptoManager
|
||||||
import im.vector.matrix.android.internal.crypto.DeviceListManager
|
import im.vector.matrix.android.internal.crypto.DeviceListManager
|
||||||
import im.vector.matrix.android.internal.crypto.MXOlmDevice
|
import im.vector.matrix.android.internal.crypto.MXOlmDevice
|
||||||
import im.vector.matrix.android.internal.crypto.algorithms.IMXEncrypting
|
import im.vector.matrix.android.internal.crypto.algorithms.IMXEncrypting
|
||||||
|
import im.vector.matrix.android.internal.crypto.keysbackup.KeysBackup
|
||||||
import im.vector.matrix.android.internal.crypto.model.MXDeviceInfo
|
import im.vector.matrix.android.internal.crypto.model.MXDeviceInfo
|
||||||
import im.vector.matrix.android.internal.crypto.model.MXOlmSessionResult
|
import im.vector.matrix.android.internal.crypto.model.MXOlmSessionResult
|
||||||
import im.vector.matrix.android.internal.crypto.model.MXUsersDevicesMap
|
import im.vector.matrix.android.internal.crypto.model.MXUsersDevicesMap
|
||||||
import im.vector.matrix.android.internal.crypto.CryptoManager
|
|
||||||
import im.vector.matrix.android.internal.crypto.tasks.SendToDeviceTask
|
import im.vector.matrix.android.internal.crypto.tasks.SendToDeviceTask
|
||||||
import im.vector.matrix.android.internal.task.TaskExecutor
|
import im.vector.matrix.android.internal.task.TaskExecutor
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
@ -49,6 +50,7 @@ internal class MXOlmEncryption : IMXEncrypting {
|
||||||
|
|
||||||
override fun initWithMatrixSession(crypto: CryptoManager,
|
override fun initWithMatrixSession(crypto: CryptoManager,
|
||||||
olmDevice: MXOlmDevice,
|
olmDevice: MXOlmDevice,
|
||||||
|
keysBackup: KeysBackup,
|
||||||
deviceListManager: DeviceListManager,
|
deviceListManager: DeviceListManager,
|
||||||
credentials: Credentials,
|
credentials: Credentials,
|
||||||
sendToDeviceTask: SendToDeviceTask,
|
sendToDeviceTask: SendToDeviceTask,
|
||||||
|
@ -69,7 +71,7 @@ internal class MXOlmEncryption : IMXEncrypting {
|
||||||
//
|
//
|
||||||
// TODO: there is a race condition here! What if a new user turns up
|
// TODO: there is a race condition here! What if a new user turns up
|
||||||
ensureSession(userIds, object : MatrixCallback<Unit> {
|
ensureSession(userIds, object : MatrixCallback<Unit> {
|
||||||
override fun onSuccess(info: Unit) {
|
override fun onSuccess(data: Unit) {
|
||||||
val deviceInfos = ArrayList<MXDeviceInfo>()
|
val deviceInfos = ArrayList<MXDeviceInfo>()
|
||||||
|
|
||||||
for (userId in userIds) {
|
for (userId in userIds) {
|
||||||
|
@ -95,11 +97,11 @@ internal class MXOlmEncryption : IMXEncrypting {
|
||||||
}
|
}
|
||||||
|
|
||||||
val messageMap = HashMap<String, Any>()
|
val messageMap = HashMap<String, Any>()
|
||||||
messageMap["room_id"] = mRoomId!!
|
messageMap["room_id"] = mRoomId
|
||||||
messageMap["type"] = eventType
|
messageMap["type"] = eventType
|
||||||
messageMap["content"] = eventContent
|
messageMap["content"] = eventContent
|
||||||
|
|
||||||
mCrypto!!.encryptMessage(messageMap, deviceInfos)
|
mCrypto.encryptMessage(messageMap, deviceInfos)
|
||||||
|
|
||||||
callback.onSuccess(messageMap.toContent()!!)
|
callback.onSuccess(messageMap.toContent()!!)
|
||||||
}
|
}
|
||||||
|
@ -116,7 +118,7 @@ internal class MXOlmEncryption : IMXEncrypting {
|
||||||
mDeviceListManager.downloadKeys(users, false, object : MatrixCallback<MXUsersDevicesMap<MXDeviceInfo>> {
|
mDeviceListManager.downloadKeys(users, false, object : MatrixCallback<MXUsersDevicesMap<MXDeviceInfo>> {
|
||||||
|
|
||||||
override fun onSuccess(data: MXUsersDevicesMap<MXDeviceInfo>) {
|
override fun onSuccess(data: MXUsersDevicesMap<MXDeviceInfo>) {
|
||||||
mCrypto!!.ensureOlmSessionsForUsers(users, object : MatrixCallback<MXUsersDevicesMap<MXOlmSessionResult>> {
|
mCrypto.ensureOlmSessionsForUsers(users, object : MatrixCallback<MXUsersDevicesMap<MXOlmSessionResult>> {
|
||||||
override fun onSuccess(data: MXUsersDevicesMap<MXOlmSessionResult>) {
|
override fun onSuccess(data: MXUsersDevicesMap<MXOlmSessionResult>) {
|
||||||
callback?.onSuccess(Unit)
|
callback?.onSuccess(Unit)
|
||||||
}
|
}
|
||||||
|
|
|
@ -201,7 +201,7 @@ internal class RealmCryptoStore(private val enableFileEncryption: Boolean = fals
|
||||||
.let { u ->
|
.let { u ->
|
||||||
// Add the devices
|
// Add the devices
|
||||||
// Ensure all other devices are deleted
|
// Ensure all other devices are deleted
|
||||||
u.devices.deleteAllFromRealm()
|
u.devices.deleteAllFromRealm() // Device is null!!
|
||||||
|
|
||||||
u.devices.addAll(
|
u.devices.addAll(
|
||||||
devices.map {
|
devices.map {
|
||||||
|
|
|
@ -16,25 +16,65 @@
|
||||||
|
|
||||||
package im.vector.matrix.android.internal.session.sync
|
package im.vector.matrix.android.internal.session.sync
|
||||||
|
|
||||||
|
import android.text.TextUtils
|
||||||
|
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.events.model.toModel
|
||||||
|
import im.vector.matrix.android.api.session.room.model.message.MessageContent
|
||||||
import im.vector.matrix.android.internal.crypto.CryptoManager
|
import im.vector.matrix.android.internal.crypto.CryptoManager
|
||||||
|
import im.vector.matrix.android.internal.crypto.MXDecryptionException
|
||||||
|
import im.vector.matrix.android.internal.crypto.MXEventDecryptionResult
|
||||||
import im.vector.matrix.android.internal.crypto.verification.DefaultSasVerificationService
|
import im.vector.matrix.android.internal.crypto.verification.DefaultSasVerificationService
|
||||||
import im.vector.matrix.android.internal.session.sync.model.SyncResponse
|
import im.vector.matrix.android.internal.session.sync.model.SyncResponse
|
||||||
import im.vector.matrix.android.internal.session.sync.model.ToDeviceSyncResponse
|
import im.vector.matrix.android.internal.session.sync.model.ToDeviceSyncResponse
|
||||||
|
import timber.log.Timber
|
||||||
|
|
||||||
|
|
||||||
internal class CryptoSyncHandler(private val cryptoManager: CryptoManager,
|
internal class CryptoSyncHandler(private val cryptoManager: CryptoManager,
|
||||||
private val sasVerificationService: DefaultSasVerificationService) {
|
private val sasVerificationService: DefaultSasVerificationService) {
|
||||||
|
|
||||||
fun handleToDevice(toDevice: ToDeviceSyncResponse) {
|
fun handleToDevice(toDevice: ToDeviceSyncResponse) {
|
||||||
toDevice.events?.forEach {
|
toDevice.events?.forEach { event ->
|
||||||
sasVerificationService.onToDeviceEvent(it)
|
// Decrypt event if necessary
|
||||||
cryptoManager.onToDeviceEvent(it)
|
decryptEvent(event, null)
|
||||||
}
|
|
||||||
|
|
||||||
|
if (TextUtils.equals(event.getClearType(), EventType.MESSAGE)
|
||||||
|
&& event.mClearEvent?.content?.toModel<MessageContent>()?.type == "m.bad.encrypted") {
|
||||||
|
Timber.e("## handleToDeviceEvent() : Warning: Unable to decrypt to-device event : " + event.content)
|
||||||
|
} else {
|
||||||
|
sasVerificationService.onToDeviceEvent(event)
|
||||||
|
cryptoManager.onToDeviceEvent(event)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onSyncCompleted(syncResponse: SyncResponse, fromToken: String?, catchingUp: Boolean) {
|
fun onSyncCompleted(syncResponse: SyncResponse, fromToken: String?, catchingUp: Boolean) {
|
||||||
cryptoManager.onSyncCompleted(syncResponse, fromToken, catchingUp)
|
cryptoManager.onSyncCompleted(syncResponse, fromToken, catchingUp)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decrypt an encrypted event
|
||||||
|
*
|
||||||
|
* @param event the event to decrypt
|
||||||
|
* @param timelineId the timeline identifier
|
||||||
|
* @return true if the event has been decrypted
|
||||||
|
*/
|
||||||
|
private fun decryptEvent(event: Event, timelineId: String?): Boolean {
|
||||||
|
if (event.type == EventType.ENCRYPTED) {
|
||||||
|
var result: MXEventDecryptionResult? = null
|
||||||
|
try {
|
||||||
|
result = cryptoManager.decryptEvent(event, timelineId ?: "")
|
||||||
|
} catch (exception: MXDecryptionException) {
|
||||||
|
event.setCryptoError(exception.cryptoError)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (null != result) {
|
||||||
|
event.setClearData(result)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
Reference in a new issue