mirror of
https://github.com/vector-im/element-android.git
synced 2024-11-15 01:35:07 +08:00
Crypto : WIP
This commit is contained in:
parent
bb39db3f42
commit
3519ad7c8d
@ -12,7 +12,7 @@ buildscript {
|
||||
}
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:3.4.0'
|
||||
classpath 'com.android.tools.build:gradle:3.4.1'
|
||||
classpath 'com.google.gms:google-services:4.2.0'
|
||||
classpath "com.airbnb.okreplay:gradle-plugin:1.4.0"
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||
|
@ -19,4 +19,4 @@ package im.vector.matrix.android
|
||||
import im.vector.matrix.android.internal.util.MatrixCoroutineDispatchers
|
||||
import kotlinx.coroutines.Dispatchers.Main
|
||||
|
||||
internal val testCoroutineDispatchers = MatrixCoroutineDispatchers(Main, Main, Main)
|
||||
internal val testCoroutineDispatchers = MatrixCoroutineDispatchers(Main, Main, Main, Main, Main)
|
@ -22,5 +22,5 @@ enum class RoomHistoryVisibility {
|
||||
@Json(name = "shared") SHARED,
|
||||
@Json(name = "invited") INVITED,
|
||||
@Json(name = "joined") JOINED,
|
||||
@Json(name = "word_readable") WORLD_READABLE
|
||||
@Json(name = "world_readable") WORLD_READABLE
|
||||
}
|
@ -35,8 +35,10 @@ 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.Room
|
||||
import im.vector.matrix.android.api.session.room.model.Membership
|
||||
import im.vector.matrix.android.api.session.room.model.RoomHistoryVisibility
|
||||
import im.vector.matrix.android.api.session.room.model.RoomHistoryVisibilityContent
|
||||
import im.vector.matrix.android.api.session.room.model.RoomMember
|
||||
import im.vector.matrix.android.internal.crypto.actions.EnsureOlmSessionsForDevicesAction
|
||||
import im.vector.matrix.android.internal.crypto.actions.MegolmSessionDataImporter
|
||||
import im.vector.matrix.android.internal.crypto.actions.SetDeviceVerificationAction
|
||||
@ -44,19 +46,29 @@ 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.keysbackup.KeysBackup
|
||||
import im.vector.matrix.android.internal.crypto.model.*
|
||||
import im.vector.matrix.android.internal.crypto.model.ImportRoomKeysResult
|
||||
import im.vector.matrix.android.internal.crypto.model.MXDeviceInfo
|
||||
import im.vector.matrix.android.internal.crypto.model.MXEncryptEventContentResult
|
||||
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.event.RoomKeyContent
|
||||
import im.vector.matrix.android.internal.crypto.model.rest.DevicesListResponse
|
||||
import im.vector.matrix.android.internal.crypto.model.rest.KeysUploadResponse
|
||||
import im.vector.matrix.android.internal.crypto.model.rest.RoomKeyRequestBody
|
||||
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.*
|
||||
import im.vector.matrix.android.internal.crypto.tasks.ClaimOneTimeKeysForUsersDeviceTask
|
||||
import im.vector.matrix.android.internal.crypto.tasks.DeleteDeviceTask
|
||||
import im.vector.matrix.android.internal.crypto.tasks.GetDevicesTask
|
||||
import im.vector.matrix.android.internal.crypto.tasks.GetKeyChangesTask
|
||||
import im.vector.matrix.android.internal.crypto.tasks.SendToDeviceTask
|
||||
import im.vector.matrix.android.internal.crypto.tasks.SetDeviceNameTask
|
||||
import im.vector.matrix.android.internal.crypto.tasks.UploadKeysTask
|
||||
import im.vector.matrix.android.internal.crypto.verification.DefaultSasVerificationService
|
||||
import im.vector.matrix.android.internal.di.MoshiProvider
|
||||
import im.vector.matrix.android.internal.session.room.members.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.TaskThread
|
||||
import im.vector.matrix.android.internal.task.configureWith
|
||||
import org.matrix.olm.OlmManager
|
||||
import timber.log.Timber
|
||||
@ -230,15 +242,8 @@ internal class CryptoManager(
|
||||
* devices.
|
||||
*
|
||||
* @param isInitialSync true if it starts from an initial sync
|
||||
* @param aCallback the asynchronous callback
|
||||
*/
|
||||
fun start(isInitialSync: Boolean, aCallback: MatrixCallback<Unit>?) {
|
||||
synchronized(mInitializationCallbacks) {
|
||||
if (null != aCallback && mInitializationCallbacks.indexOf(aCallback) < 0) {
|
||||
mInitializationCallbacks.add(aCallback)
|
||||
}
|
||||
}
|
||||
|
||||
fun start(isInitialSync: Boolean) {
|
||||
if (mIsStarting) {
|
||||
return
|
||||
}
|
||||
@ -260,11 +265,11 @@ internal class CryptoManager(
|
||||
uploadDeviceKeys(object : MatrixCallback<KeysUploadResponse> {
|
||||
private fun onError() {
|
||||
Handler().postDelayed({
|
||||
if (!isStarted()) {
|
||||
mIsStarting = false
|
||||
start(isInitialSync, null)
|
||||
}
|
||||
}, 1000)
|
||||
if (!isStarted()) {
|
||||
mIsStarting = false
|
||||
start(isInitialSync)
|
||||
}
|
||||
}, 1000)
|
||||
}
|
||||
|
||||
override fun onSuccess(data: KeysUploadResponse) {
|
||||
@ -290,13 +295,6 @@ internal class CryptoManager(
|
||||
|
||||
mKeysBackup.checkAndStartKeysBackup()
|
||||
|
||||
synchronized(mInitializationCallbacks) {
|
||||
for (callback in mInitializationCallbacks) {
|
||||
callback.onSuccess(Unit)
|
||||
}
|
||||
mInitializationCallbacks.clear()
|
||||
}
|
||||
|
||||
if (isInitialSync) {
|
||||
// refresh the devices list for each known room members
|
||||
deviceListManager.invalidateAllDeviceLists()
|
||||
@ -605,17 +603,7 @@ internal class CryptoManager(
|
||||
if (!isStarted()) {
|
||||
Timber.v("## encryptEventContent() : wait after e2e init")
|
||||
|
||||
start(false, object : MatrixCallback<Unit> {
|
||||
override fun onSuccess(data: Unit) {
|
||||
encryptEventContent(eventContent, eventType, room, callback)
|
||||
}
|
||||
|
||||
override fun onFailure(failure: Throwable) {
|
||||
Timber.e(failure, "## encryptEventContent() : onNetworkError while waiting to start e2e")
|
||||
|
||||
callback.onFailure(failure)
|
||||
}
|
||||
})
|
||||
start(false)
|
||||
|
||||
return
|
||||
}
|
||||
@ -669,11 +657,11 @@ internal class CryptoManager(
|
||||
} else {
|
||||
val algorithm = room.encryptionAlgorithm()
|
||||
val reason = String.format(MXCryptoError.UNABLE_TO_ENCRYPT_REASON,
|
||||
algorithm ?: MXCryptoError.NO_MORE_ALGORITHM_REASON)
|
||||
algorithm ?: MXCryptoError.NO_MORE_ALGORITHM_REASON)
|
||||
Timber.e("## encryptEventContent() : $reason")
|
||||
|
||||
callback.onFailure(Failure.CryptoError(MXCryptoError(MXCryptoError.UNABLE_TO_ENCRYPT_ERROR_CODE,
|
||||
MXCryptoError.UNABLE_TO_ENCRYPT, reason)))
|
||||
MXCryptoError.UNABLE_TO_ENCRYPT, reason)))
|
||||
}
|
||||
}
|
||||
|
||||
@ -703,7 +691,7 @@ internal class CryptoManager(
|
||||
val reason = String.format(MXCryptoError.UNABLE_TO_DECRYPT_REASON, event.eventId, eventContent["algorithm"] as String)
|
||||
Timber.e("## decryptEvent() : $reason")
|
||||
exceptions.add(MXDecryptionException(MXCryptoError(MXCryptoError.UNABLE_TO_DECRYPT_ERROR_CODE,
|
||||
MXCryptoError.UNABLE_TO_DECRYPT, reason)))
|
||||
MXCryptoError.UNABLE_TO_DECRYPT, reason)))
|
||||
} else {
|
||||
try {
|
||||
result = alg.decryptEvent(event, timeline)
|
||||
@ -796,23 +784,15 @@ internal class CryptoManager(
|
||||
// No encrypting in this room
|
||||
return
|
||||
}
|
||||
|
||||
val userId = event.stateKey!!
|
||||
|
||||
/* FIXME
|
||||
val room = mRoomService.getRoom(roomId)
|
||||
|
||||
val roomMember = room?.getRoomMember(userId)
|
||||
|
||||
if (null != roomMember) {
|
||||
val membership = roomMember.membership
|
||||
|
||||
event.stateKey?.let { userId ->
|
||||
val roomMember: RoomMember? = event.content.toModel()
|
||||
val membership = roomMember?.membership
|
||||
if (membership == Membership.JOIN) {
|
||||
// make sure we are tracking the deviceList for this user.
|
||||
deviceListManager.startTrackingDeviceList(Arrays.asList(userId))
|
||||
} else if (membership == Membership.INVITE
|
||||
&& shouldEncryptForInvitedMembers(roomId)
|
||||
&& mCryptoConfig.mEnableEncryptionForInvitedMembers) {
|
||||
&& shouldEncryptForInvitedMembers(roomId)
|
||||
&& mCryptoConfig.mEnableEncryptionForInvitedMembers) {
|
||||
// track the deviceList for this invited user.
|
||||
// Caution: there's a big edge case here in that federated servers do not
|
||||
// know what other servers are in the room at the time they've been invited.
|
||||
@ -821,7 +801,6 @@ internal class CryptoManager(
|
||||
deviceListManager.startTrackingDeviceList(Arrays.asList(userId))
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
private fun onRoomHistoryVisibilityEvent(roomId: String, event: Event) {
|
||||
@ -851,6 +830,7 @@ internal class CryptoManager(
|
||||
// same one as used in login.
|
||||
mUploadKeysTask
|
||||
.configureWith(UploadKeysTask.Params(getMyDevice().toDeviceKeys(), null, getMyDevice().deviceId))
|
||||
.executeOn(TaskThread.ENCRYPTION)
|
||||
.dispatchTo(callback)
|
||||
.executeBy(mTaskExecutor)
|
||||
}
|
||||
@ -980,7 +960,7 @@ internal class CryptoManager(
|
||||
// trigger an an unknown devices exception
|
||||
callback.onFailure(
|
||||
Failure.CryptoError(MXCryptoError(MXCryptoError.UNKNOWN_DEVICES_CODE,
|
||||
MXCryptoError.UNABLE_TO_ENCRYPT, MXCryptoError.UNKNOWN_DEVICES_REASON, unknownDevices)))
|
||||
MXCryptoError.UNABLE_TO_ENCRYPT, MXCryptoError.UNKNOWN_DEVICES_REASON, unknownDevices)))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -23,6 +23,7 @@ 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.task.TaskExecutor
|
||||
import im.vector.matrix.android.internal.task.TaskThread
|
||||
import im.vector.matrix.android.internal.task.configureWith
|
||||
import org.matrix.olm.OlmAccount
|
||||
import timber.log.Timber
|
||||
@ -95,6 +96,7 @@ internal class OneTimeKeysUploader(
|
||||
// ask the server how many keys we have
|
||||
mUploadKeysTask
|
||||
.configureWith(UploadKeysTask.Params(null, null, mCredentials.deviceId!!))
|
||||
.executeOn(TaskThread.ENCRYPTION)
|
||||
.dispatchTo(object : MatrixCallback<KeysUploadResponse> {
|
||||
|
||||
override fun onSuccess(data: KeysUploadResponse) {
|
||||
@ -192,6 +194,7 @@ internal class OneTimeKeysUploader(
|
||||
// same one as used in login.
|
||||
mUploadKeysTask
|
||||
.configureWith(UploadKeysTask.Params(null, oneTimeJson, mCredentials.deviceId!!))
|
||||
.executeOn(TaskThread.ENCRYPTION)
|
||||
.dispatchTo(object : MatrixCallback<KeysUploadResponse> {
|
||||
override fun onSuccess(data: KeysUploadResponse) {
|
||||
mLastPublishedOneTimeKeys = oneTimeKeys
|
||||
|
@ -21,6 +21,7 @@ import androidx.work.Worker
|
||||
import androidx.work.WorkerParameters
|
||||
import com.squareup.moshi.JsonClass
|
||||
import com.zhuinden.monarchy.Monarchy
|
||||
import im.vector.matrix.android.api.MatrixCallback
|
||||
import im.vector.matrix.android.internal.crypto.CryptoManager
|
||||
import im.vector.matrix.android.internal.database.mapper.asDomain
|
||||
import im.vector.matrix.android.internal.database.model.EventEntity
|
||||
@ -50,8 +51,8 @@ internal class EnableEncryptionWorker(context: Context,
|
||||
|
||||
|
||||
override fun doWork(): Result {
|
||||
val params = WorkerParamsFactory.fromData<EnableEncryptionWorker.Params>(inputData)
|
||||
?: return Result.failure()
|
||||
val params = WorkerParamsFactory.fromData<Params>(inputData)
|
||||
?: return Result.failure()
|
||||
|
||||
|
||||
val events = monarchy.fetchAllMappedSync(
|
||||
@ -62,9 +63,17 @@ internal class EnableEncryptionWorker(context: Context,
|
||||
events.forEach {
|
||||
val roomId = it.roomId!!
|
||||
|
||||
val callback = object : MatrixCallback<Boolean> {
|
||||
override fun onSuccess(data: Boolean) {
|
||||
super.onSuccess(data)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
loadRoomMembersTask
|
||||
.configureWith(LoadRoomMembersTask.Params(roomId))
|
||||
.executeOn(TaskThread.CALLER)
|
||||
.executeOn(TaskThread.ENCRYPTION)
|
||||
.dispatchTo(callback)
|
||||
.executeBy(taskExecutor)
|
||||
|
||||
var userIds: List<String> = emptyList()
|
||||
@ -72,7 +81,7 @@ internal class EnableEncryptionWorker(context: Context,
|
||||
monarchy.doWithRealm { realm ->
|
||||
// Check whether the event content must be encrypted for the invited members.
|
||||
val encryptForInvitedMembers = cryptoManager.isEncryptionEnabledForInvitedUser()
|
||||
&& cryptoManager.shouldEncryptForInvitedMembers(roomId)
|
||||
&& cryptoManager.shouldEncryptForInvitedMembers(roomId)
|
||||
|
||||
|
||||
userIds = if (encryptForInvitedMembers) {
|
||||
|
@ -21,7 +21,9 @@ import im.vector.matrix.android.internal.task.TaskExecutor
|
||||
import im.vector.matrix.android.internal.util.BackgroundDetectionObserver
|
||||
import im.vector.matrix.android.internal.util.MatrixCoroutineDispatchers
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.asCoroutineDispatcher
|
||||
import org.koin.dsl.module.module
|
||||
import java.util.concurrent.Executors
|
||||
|
||||
|
||||
class MatrixModule(private val context: Context) {
|
||||
@ -33,7 +35,12 @@ class MatrixModule(private val context: Context) {
|
||||
}
|
||||
|
||||
single {
|
||||
MatrixCoroutineDispatchers(io = Dispatchers.IO, computation = Dispatchers.IO, main = Dispatchers.Main)
|
||||
MatrixCoroutineDispatchers(io = Dispatchers.IO,
|
||||
computation = Dispatchers.IO,
|
||||
main = Dispatchers.Main,
|
||||
encryption = Executors.newSingleThreadExecutor().asCoroutineDispatcher(),
|
||||
decryption = Executors.newSingleThreadExecutor().asCoroutineDispatcher()
|
||||
)
|
||||
}
|
||||
|
||||
single {
|
||||
|
@ -103,18 +103,17 @@ internal class DefaultSession(override val sessionParams: SessionParams) : Sessi
|
||||
val contentModule = ContentModule().definition
|
||||
val cryptoModule = CryptoModule().definition
|
||||
MatrixKoinHolder.instance.loadModules(listOf(sessionModule,
|
||||
syncModule,
|
||||
roomModule,
|
||||
groupModule,
|
||||
userModule,
|
||||
signOutModule,
|
||||
contentModule,
|
||||
cryptoModule))
|
||||
syncModule,
|
||||
roomModule,
|
||||
groupModule,
|
||||
userModule,
|
||||
signOutModule,
|
||||
contentModule,
|
||||
cryptoModule))
|
||||
scope = getKoin().getOrCreateScope(SCOPE)
|
||||
if (!monarchy.isMonarchyThreadOpen) {
|
||||
monarchy.openManually()
|
||||
}
|
||||
cryptoService.start(false, null)
|
||||
liveEntityUpdaters.forEach { it.start() }
|
||||
}
|
||||
|
||||
|
@ -56,7 +56,7 @@ internal class SyncModule {
|
||||
}
|
||||
|
||||
scope(DefaultSession.SCOPE) {
|
||||
SyncResponseHandler(get(), get(), get(), get())
|
||||
SyncResponseHandler(get(), get(), get(), get(), get())
|
||||
}
|
||||
|
||||
scope(DefaultSession.SCOPE) {
|
||||
|
@ -17,6 +17,7 @@
|
||||
package im.vector.matrix.android.internal.session.sync
|
||||
|
||||
import arrow.core.Try
|
||||
import im.vector.matrix.android.internal.crypto.CryptoManager
|
||||
import im.vector.matrix.android.internal.session.sync.model.SyncResponse
|
||||
import timber.log.Timber
|
||||
import kotlin.system.measureTimeMillis
|
||||
@ -24,7 +25,8 @@ import kotlin.system.measureTimeMillis
|
||||
internal class SyncResponseHandler(private val roomSyncHandler: RoomSyncHandler,
|
||||
private val userAccountDataSyncHandler: UserAccountDataSyncHandler,
|
||||
private val groupSyncHandler: GroupSyncHandler,
|
||||
private val cryptoSyncHandler: CryptoSyncHandler) {
|
||||
private val cryptoSyncHandler: CryptoSyncHandler,
|
||||
private val cryptoManager: CryptoManager) {
|
||||
|
||||
fun handleResponse(syncResponse: SyncResponse, fromToken: String?, isCatchingUp: Boolean): Try<SyncResponse> {
|
||||
return Try {
|
||||
@ -44,9 +46,10 @@ internal class SyncResponseHandler(private val roomSyncHandler: RoomSyncHandler,
|
||||
if (syncResponse.accountData != null) {
|
||||
userAccountDataSyncHandler.handle(syncResponse.accountData)
|
||||
}
|
||||
|
||||
cryptoSyncHandler.onSyncCompleted(syncResponse, fromToken, isCatchingUp)
|
||||
}
|
||||
val isInitialSync = fromToken == null
|
||||
cryptoManager.start(isInitialSync)
|
||||
Timber.v("Finish handling sync in $measure ms")
|
||||
syncResponse
|
||||
}
|
||||
|
@ -68,6 +68,8 @@ internal class TaskExecutor(private val coroutineDispatchers: MatrixCoroutineDis
|
||||
TaskThread.COMPUTATION -> coroutineDispatchers.computation
|
||||
TaskThread.IO -> coroutineDispatchers.io
|
||||
TaskThread.CALLER -> EmptyCoroutineContext
|
||||
TaskThread.ENCRYPTION -> coroutineDispatchers.encryption
|
||||
TaskThread.DECRYPTION -> coroutineDispatchers.decryption
|
||||
}
|
||||
|
||||
|
||||
|
@ -20,5 +20,7 @@ internal enum class TaskThread {
|
||||
MAIN,
|
||||
COMPUTATION,
|
||||
IO,
|
||||
CALLER
|
||||
CALLER,
|
||||
ENCRYPTION,
|
||||
DECRYPTION
|
||||
}
|
@ -21,5 +21,7 @@ import kotlinx.coroutines.CoroutineDispatcher
|
||||
internal data class MatrixCoroutineDispatchers(
|
||||
val io: CoroutineDispatcher,
|
||||
val computation: CoroutineDispatcher,
|
||||
val main: CoroutineDispatcher
|
||||
val main: CoroutineDispatcher,
|
||||
val decryption: CoroutineDispatcher,
|
||||
val encryption: CoroutineDispatcher
|
||||
)
|
@ -30,6 +30,7 @@ import im.vector.matrix.android.api.session.room.model.message.*
|
||||
import im.vector.matrix.android.api.session.room.timeline.Timeline
|
||||
import im.vector.matrix.android.api.session.room.timeline.TimelineEvent
|
||||
import im.vector.riotredesign.core.epoxy.LoadingItemModel_
|
||||
import im.vector.riotredesign.core.epoxy.loadingItem
|
||||
import im.vector.riotredesign.core.extensions.localDateTime
|
||||
import im.vector.riotredesign.features.home.room.detail.timeline.factory.TimelineItemFactory
|
||||
import im.vector.riotredesign.features.home.room.detail.timeline.helper.*
|
||||
|
Loading…
Reference in New Issue
Block a user