mirror of
https://github.com/SchildiChat/SchildiChat-android.git
synced 2025-03-15 02:38:59 +03:00
Merge branch 'bca/rust_4s_verify_pass' into rust
This commit is contained in:
commit
5109f10833
41 changed files with 1208 additions and 2585 deletions
|
@ -36,8 +36,6 @@ import org.matrix.android.sdk.common.CommonTestHelper
|
|||
import org.matrix.android.sdk.common.CryptoTestHelper
|
||||
import org.matrix.android.sdk.common.SessionTestParams
|
||||
import org.matrix.android.sdk.common.TestConstants
|
||||
import org.matrix.android.sdk.internal.crypto.model.CryptoDeviceInfo
|
||||
import org.matrix.android.sdk.internal.crypto.model.MXUsersDevicesMap
|
||||
import kotlin.coroutines.Continuation
|
||||
import kotlin.coroutines.resume
|
||||
|
||||
|
@ -112,7 +110,7 @@ class XSigningTest : InstrumentedTest {
|
|||
}, it) }
|
||||
|
||||
// Check that alice can see bob keys
|
||||
mTestHelper.doSync<MXUsersDevicesMap<CryptoDeviceInfo>> { aliceSession.cryptoService().downloadKeys(listOf(bobSession.myUserId), true, it) }
|
||||
mTestHelper.runBlockingTest { aliceSession.cryptoService().downloadKeys(listOf(bobSession.myUserId), true) }
|
||||
|
||||
val bobKeysFromAlicePOV = aliceSession.cryptoService().crossSigningService().getUserCrossSigningKeys(bobSession.myUserId)
|
||||
assertNotNull("Alice can see bob Master key", bobKeysFromAlicePOV!!.masterKey())
|
||||
|
@ -157,7 +155,7 @@ class XSigningTest : InstrumentedTest {
|
|||
|
||||
// Check that alice can see bob keys
|
||||
val bobUserId = bobSession.myUserId
|
||||
mTestHelper.doSync<MXUsersDevicesMap<CryptoDeviceInfo>> { aliceSession.cryptoService().downloadKeys(listOf(bobUserId), true, it) }
|
||||
mTestHelper.runBlockingTest { aliceSession.cryptoService().downloadKeys(listOf(bobUserId), true) }
|
||||
|
||||
val bobKeysFromAlicePOV = aliceSession.cryptoService().crossSigningService().getUserCrossSigningKeys(bobUserId)
|
||||
assertTrue("Bob keys from alice pov should not be trusted", bobKeysFromAlicePOV?.isTrusted() == false)
|
||||
|
@ -171,8 +169,8 @@ class XSigningTest : InstrumentedTest {
|
|||
val bobSecondDeviceId = bobSession2.sessionParams.deviceId!!
|
||||
|
||||
// Check that bob first session sees the new login
|
||||
val data = mTestHelper.doSync<MXUsersDevicesMap<CryptoDeviceInfo>> {
|
||||
bobSession.cryptoService().downloadKeys(listOf(bobUserId), true, it)
|
||||
val data = mTestHelper.runBlockingTest {
|
||||
bobSession.cryptoService().downloadKeys(listOf(bobUserId), true)
|
||||
}
|
||||
|
||||
if (data.getUserDeviceIds(bobUserId)?.contains(bobSecondDeviceId) == false) {
|
||||
|
@ -183,13 +181,13 @@ class XSigningTest : InstrumentedTest {
|
|||
assertNotNull("Bob Second device should be known and persisted from first", bobSecondDevicePOVFirstDevice)
|
||||
|
||||
// Manually mark it as trusted from first session
|
||||
mTestHelper.doSync<Unit> {
|
||||
bobSession.cryptoService().crossSigningService().trustDevice(bobSecondDeviceId, it)
|
||||
mTestHelper.runBlockingTest {
|
||||
bobSession.cryptoService().crossSigningService().trustDevice(bobSecondDeviceId)
|
||||
}
|
||||
|
||||
// Now alice should cross trust bob's second device
|
||||
val data2 = mTestHelper.doSync<MXUsersDevicesMap<CryptoDeviceInfo>> {
|
||||
aliceSession.cryptoService().downloadKeys(listOf(bobUserId), true, it)
|
||||
val data2 = mTestHelper.runBlockingTest {
|
||||
aliceSession.cryptoService().downloadKeys(listOf(bobUserId), true)
|
||||
}
|
||||
|
||||
// check that the device is seen
|
||||
|
|
|
@ -50,10 +50,6 @@ import org.matrix.android.sdk.common.TestConstants
|
|||
import org.matrix.android.sdk.internal.crypto.GossipingRequestState
|
||||
import org.matrix.android.sdk.internal.crypto.OutgoingGossipingRequestState
|
||||
import org.matrix.android.sdk.internal.crypto.crosssigning.DeviceTrustLevel
|
||||
import org.matrix.android.sdk.internal.crypto.keysbackup.model.MegolmBackupCreationInfo
|
||||
import org.matrix.android.sdk.internal.crypto.keysbackup.model.rest.KeysVersion
|
||||
import org.matrix.android.sdk.internal.crypto.model.CryptoDeviceInfo
|
||||
import org.matrix.android.sdk.internal.crypto.model.MXUsersDevicesMap
|
||||
import org.matrix.android.sdk.internal.crypto.model.event.EncryptedEventContent
|
||||
import java.util.concurrent.CountDownLatch
|
||||
import kotlin.coroutines.Continuation
|
||||
|
@ -103,7 +99,7 @@ class KeyShareTests : InstrumentedTest {
|
|||
|
||||
val outgoingRequestsBefore = aliceSession2.cryptoService().getOutgoingRoomKeyRequests()
|
||||
// Try to request
|
||||
aliceSession2.cryptoService().requestRoomKeyForEvent(receivedEvent.root)
|
||||
aliceSession2.cryptoService().reRequestRoomKeyForEvent(receivedEvent.root)
|
||||
|
||||
val waitLatch = CountDownLatch(1)
|
||||
val eventMegolmSessionId = receivedEvent.root.content.toModel<EncryptedEventContent>()?.sessionId
|
||||
|
@ -218,11 +214,11 @@ class KeyShareTests : InstrumentedTest {
|
|||
}
|
||||
|
||||
// Also bootstrap keybackup on first session
|
||||
val creationInfo = mTestHelper.doSync<MegolmBackupCreationInfo> {
|
||||
aliceSession1.cryptoService().keysBackupService().prepareKeysBackupVersion(null, null, it)
|
||||
val creationInfo = mTestHelper.runBlockingTest {
|
||||
aliceSession1.cryptoService().keysBackupService().prepareKeysBackupVersion(null)
|
||||
}
|
||||
val version = mTestHelper.doSync<KeysVersion> {
|
||||
aliceSession1.cryptoService().keysBackupService().createKeysBackupVersion(creationInfo, it)
|
||||
val version = mTestHelper.runBlockingTest {
|
||||
aliceSession1.cryptoService().keysBackupService().createKeysBackupVersion(creationInfo)
|
||||
}
|
||||
// Save it for gossiping
|
||||
aliceSession1.cryptoService().keysBackupService().saveBackupRecoveryKey(creationInfo.recoveryKey, version = version.version)
|
||||
|
@ -233,11 +229,11 @@ class KeyShareTests : InstrumentedTest {
|
|||
val aliceVerificationService2 = aliceSession2.cryptoService().verificationService()
|
||||
|
||||
// force keys download
|
||||
mTestHelper.doSync<MXUsersDevicesMap<CryptoDeviceInfo>> {
|
||||
aliceSession1.cryptoService().downloadKeys(listOf(aliceSession1.myUserId), true, it)
|
||||
mTestHelper.runBlockingTest {
|
||||
aliceSession1.cryptoService().downloadKeys(listOf(aliceSession1.myUserId), true)
|
||||
}
|
||||
mTestHelper.doSync<MXUsersDevicesMap<CryptoDeviceInfo>> {
|
||||
aliceSession2.cryptoService().downloadKeys(listOf(aliceSession2.myUserId), true, it)
|
||||
mTestHelper.runBlockingTest {
|
||||
aliceSession2.cryptoService().downloadKeys(listOf(aliceSession2.myUserId), true)
|
||||
}
|
||||
|
||||
var session1ShortCode: String? = null
|
||||
|
|
|
@ -24,7 +24,6 @@ import org.junit.Test
|
|||
import org.junit.runner.RunWith
|
||||
import org.junit.runners.MethodSorters
|
||||
import org.matrix.android.sdk.InstrumentedTest
|
||||
import org.matrix.android.sdk.api.NoOpMatrixCallback
|
||||
import org.matrix.android.sdk.api.extensions.tryOrNull
|
||||
import org.matrix.android.sdk.api.session.crypto.MXCryptoError
|
||||
import org.matrix.android.sdk.api.session.events.model.EventType
|
||||
|
@ -217,8 +216,10 @@ class WithHeldTests : InstrumentedTest {
|
|||
mCryptoTestHelper.initializeCrossSigning(bobSecondSession)
|
||||
|
||||
// Trust bob second device from Alice POV
|
||||
aliceSession.cryptoService().crossSigningService().trustDevice(bobSecondSession.sessionParams.deviceId!!, NoOpMatrixCallback())
|
||||
bobSecondSession.cryptoService().crossSigningService().trustDevice(aliceSession.sessionParams.deviceId!!, NoOpMatrixCallback())
|
||||
mTestHelper.runBlockingTest {
|
||||
aliceSession.cryptoService().crossSigningService().trustDevice(bobSecondSession.sessionParams.deviceId!!)
|
||||
bobSecondSession.cryptoService().crossSigningService().trustDevice(aliceSession.sessionParams.deviceId!!)
|
||||
}
|
||||
|
||||
var sessionId: String? = null
|
||||
// Check that the
|
||||
|
|
|
@ -19,13 +19,12 @@ package org.matrix.android.sdk.internal.crypto.keysbackup
|
|||
import org.matrix.android.sdk.api.session.Session
|
||||
import org.matrix.android.sdk.common.CommonTestHelper
|
||||
import org.matrix.android.sdk.common.CryptoTestData
|
||||
import org.matrix.android.sdk.internal.crypto.model.OlmInboundGroupSessionWrapper2
|
||||
|
||||
/**
|
||||
* Data class to store result of [KeysBackupTestHelper.createKeysBackupScenarioWithPassword]
|
||||
*/
|
||||
data class KeysBackupScenarioData(val cryptoTestData: CryptoTestData,
|
||||
val aliceKeys: List<OlmInboundGroupSessionWrapper2>,
|
||||
val aliceKeys: Int,
|
||||
val prepareKeysBackupDataResult: PrepareKeysBackupDataResult,
|
||||
val aliceSession2: Session) {
|
||||
fun cleanUp(testHelper: CommonTestHelper) {
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
package org.matrix.android.sdk.internal.crypto.keysbackup
|
||||
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import kotlinx.coroutines.delay
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Assert.assertFalse
|
||||
import org.junit.Assert.assertNotNull
|
||||
|
@ -28,23 +29,16 @@ import org.junit.Test
|
|||
import org.junit.runner.RunWith
|
||||
import org.junit.runners.MethodSorters
|
||||
import org.matrix.android.sdk.InstrumentedTest
|
||||
import org.matrix.android.sdk.api.listeners.ProgressListener
|
||||
import org.matrix.android.sdk.api.listeners.StepProgressListener
|
||||
import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupState
|
||||
import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupStateListener
|
||||
import org.matrix.android.sdk.common.CommonTestHelper
|
||||
import org.matrix.android.sdk.common.CryptoTestHelper
|
||||
import org.matrix.android.sdk.common.TestConstants
|
||||
import org.matrix.android.sdk.common.TestMatrixCallback
|
||||
import org.matrix.android.sdk.internal.crypto.MXCRYPTO_ALGORITHM_MEGOLM_BACKUP
|
||||
import org.matrix.android.sdk.internal.crypto.crosssigning.DeviceTrustLevel
|
||||
import org.matrix.android.sdk.internal.crypto.keysbackup.model.KeysBackupVersionTrust
|
||||
import org.matrix.android.sdk.internal.crypto.keysbackup.model.MegolmBackupCreationInfo
|
||||
import org.matrix.android.sdk.internal.crypto.keysbackup.model.rest.KeysVersion
|
||||
import org.matrix.android.sdk.internal.crypto.keysbackup.model.rest.KeysVersionResult
|
||||
import org.matrix.android.sdk.internal.crypto.model.ImportRoomKeysResult
|
||||
import java.util.ArrayList
|
||||
import java.util.Collections
|
||||
import java.util.concurrent.CountDownLatch
|
||||
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
|
@ -60,40 +54,40 @@ class KeysBackupTest : InstrumentedTest {
|
|||
* - Check backup keys after having marked one as backed up
|
||||
* - Reset keys backup markers
|
||||
*/
|
||||
@Test
|
||||
fun roomKeysTest_testBackupStore_ok() {
|
||||
val cryptoTestData = mCryptoTestHelper.doE2ETestWithAliceAndBobInARoomWithEncryptedMessages()
|
||||
|
||||
// From doE2ETestWithAliceAndBobInARoomWithEncryptedMessages, we should have no backed up keys
|
||||
val cryptoStore = (cryptoTestData.firstSession.cryptoService().keysBackupService() as DefaultKeysBackupService).store
|
||||
val sessions = cryptoStore.inboundGroupSessionsToBackup(100)
|
||||
val sessionsCount = sessions.size
|
||||
|
||||
assertFalse(sessions.isEmpty())
|
||||
assertEquals(sessionsCount, cryptoTestData.firstSession.cryptoService().inboundGroupSessionsCount(false))
|
||||
assertEquals(0, cryptoTestData.firstSession.cryptoService().inboundGroupSessionsCount(true))
|
||||
|
||||
// - Check backup keys after having marked one as backed up
|
||||
val session = sessions[0]
|
||||
|
||||
cryptoStore.markBackupDoneForInboundGroupSessions(Collections.singletonList(session))
|
||||
|
||||
assertEquals(sessionsCount, cryptoTestData.firstSession.cryptoService().inboundGroupSessionsCount(false))
|
||||
assertEquals(1, cryptoTestData.firstSession.cryptoService().inboundGroupSessionsCount(true))
|
||||
|
||||
val sessions2 = cryptoStore.inboundGroupSessionsToBackup(100)
|
||||
assertEquals(sessionsCount - 1, sessions2.size)
|
||||
|
||||
// - Reset keys backup markers
|
||||
cryptoStore.resetBackupMarkers()
|
||||
|
||||
val sessions3 = cryptoStore.inboundGroupSessionsToBackup(100)
|
||||
assertEquals(sessionsCount, sessions3.size)
|
||||
assertEquals(sessionsCount, cryptoTestData.firstSession.cryptoService().inboundGroupSessionsCount(false))
|
||||
assertEquals(0, cryptoTestData.firstSession.cryptoService().inboundGroupSessionsCount(true))
|
||||
|
||||
cryptoTestData.cleanUp(mTestHelper)
|
||||
}
|
||||
// @Test
|
||||
// fun roomKeysTest_testBackupStore_ok() {
|
||||
// val cryptoTestData = mCryptoTestHelper.doE2ETestWithAliceAndBobInARoomWithEncryptedMessages()
|
||||
//
|
||||
// // From doE2ETestWithAliceAndBobInARoomWithEncryptedMessages, we should have no backed up keys
|
||||
// val cryptoStore = (cryptoTestData.firstSession.cryptoService().keysBackupService() as DefaultKeysBackupService).store
|
||||
// val sessions = cryptoStore.inboundGroupSessionsToBackup(100)
|
||||
// val sessionsCount = sessions.size
|
||||
//
|
||||
// assertFalse(sessions.isEmpty())
|
||||
// assertEquals(sessionsCount, cryptoTestData.firstSession.cryptoService().inboundGroupSessionsCount(false))
|
||||
// assertEquals(0, cryptoTestData.firstSession.cryptoService().inboundGroupSessionsCount(true))
|
||||
//
|
||||
// // - Check backup keys after having marked one as backed up
|
||||
// val session = sessions[0]
|
||||
//
|
||||
// cryptoStore.markBackupDoneForInboundGroupSessions(Collections.singletonList(session))
|
||||
//
|
||||
// assertEquals(sessionsCount, cryptoTestData.firstSession.cryptoService().inboundGroupSessionsCount(false))
|
||||
// assertEquals(1, cryptoTestData.firstSession.cryptoService().inboundGroupSessionsCount(true))
|
||||
//
|
||||
// val sessions2 = cryptoStore.inboundGroupSessionsToBackup(100)
|
||||
// assertEquals(sessionsCount - 1, sessions2.size)
|
||||
//
|
||||
// // - Reset keys backup markers
|
||||
// cryptoStore.resetBackupMarkers()
|
||||
//
|
||||
// val sessions3 = cryptoStore.inboundGroupSessionsToBackup(100)
|
||||
// assertEquals(sessionsCount, sessions3.size)
|
||||
// assertEquals(sessionsCount, cryptoTestData.firstSession.cryptoService().inboundGroupSessionsCount(false))
|
||||
// assertEquals(0, cryptoTestData.firstSession.cryptoService().inboundGroupSessionsCount(true))
|
||||
//
|
||||
// cryptoTestData.cleanUp(mTestHelper)
|
||||
// }
|
||||
|
||||
/**
|
||||
* Check that prepareKeysBackupVersionWithPassword returns valid data
|
||||
|
@ -110,8 +104,8 @@ class KeysBackupTest : InstrumentedTest {
|
|||
|
||||
assertFalse(keysBackup.isEnabled)
|
||||
|
||||
val megolmBackupCreationInfo = mTestHelper.doSync<MegolmBackupCreationInfo> {
|
||||
keysBackup.prepareKeysBackupVersion(null, null, it)
|
||||
val megolmBackupCreationInfo = mTestHelper.runBlockingTest {
|
||||
keysBackup.prepareKeysBackupVersion(null)
|
||||
}
|
||||
|
||||
assertEquals(MXCRYPTO_ALGORITHM_MEGOLM_BACKUP, megolmBackupCreationInfo.algorithm)
|
||||
|
@ -136,15 +130,15 @@ class KeysBackupTest : InstrumentedTest {
|
|||
|
||||
assertFalse(keysBackup.isEnabled)
|
||||
|
||||
val megolmBackupCreationInfo = mTestHelper.doSync<MegolmBackupCreationInfo> {
|
||||
keysBackup.prepareKeysBackupVersion(null, null, it)
|
||||
val megolmBackupCreationInfo = mTestHelper.runBlockingTest {
|
||||
keysBackup.prepareKeysBackupVersion(null)
|
||||
}
|
||||
|
||||
assertFalse(keysBackup.isEnabled)
|
||||
|
||||
// Create the version
|
||||
mTestHelper.doSync<KeysVersion> {
|
||||
keysBackup.createKeysBackupVersion(megolmBackupCreationInfo, it)
|
||||
mTestHelper.runBlockingTest {
|
||||
keysBackup.createKeysBackupVersion(megolmBackupCreationInfo)
|
||||
}
|
||||
|
||||
// Backup must be enable now
|
||||
|
@ -197,41 +191,41 @@ class KeysBackupTest : InstrumentedTest {
|
|||
/**
|
||||
* Check that backupAllGroupSessions() returns valid data
|
||||
*/
|
||||
@Test
|
||||
fun backupAllGroupSessionsTest() {
|
||||
val cryptoTestData = mCryptoTestHelper.doE2ETestWithAliceAndBobInARoomWithEncryptedMessages()
|
||||
|
||||
val keysBackup = cryptoTestData.firstSession.cryptoService().keysBackupService()
|
||||
|
||||
val stateObserver = StateObserver(keysBackup)
|
||||
|
||||
mKeysBackupTestHelper.prepareAndCreateKeysBackupData(keysBackup)
|
||||
|
||||
// Check that backupAllGroupSessions returns valid data
|
||||
val nbOfKeys = cryptoTestData.firstSession.cryptoService().inboundGroupSessionsCount(false)
|
||||
|
||||
assertEquals(2, nbOfKeys)
|
||||
|
||||
var lastBackedUpKeysProgress = 0
|
||||
|
||||
mTestHelper.doSync<Unit> {
|
||||
keysBackup.backupAllGroupSessions(object : ProgressListener {
|
||||
override fun onProgress(progress: Int, total: Int) {
|
||||
assertEquals(nbOfKeys, total)
|
||||
lastBackedUpKeysProgress = progress
|
||||
}
|
||||
}, it)
|
||||
}
|
||||
|
||||
assertEquals(nbOfKeys, lastBackedUpKeysProgress)
|
||||
|
||||
val backedUpKeys = cryptoTestData.firstSession.cryptoService().inboundGroupSessionsCount(true)
|
||||
|
||||
assertEquals("All keys must have been marked as backed up", nbOfKeys, backedUpKeys)
|
||||
|
||||
stateObserver.stopAndCheckStates(null)
|
||||
cryptoTestData.cleanUp(mTestHelper)
|
||||
}
|
||||
// @Test
|
||||
// fun backupAllGroupSessionsTest() {
|
||||
// val cryptoTestData = mCryptoTestHelper.doE2ETestWithAliceAndBobInARoomWithEncryptedMessages()
|
||||
//
|
||||
// val keysBackup = cryptoTestData.firstSession.cryptoService().keysBackupService()
|
||||
//
|
||||
// val stateObserver = StateObserver(keysBackup)
|
||||
//
|
||||
// mKeysBackupTestHelper.prepareAndCreateKeysBackupData(keysBackup)
|
||||
//
|
||||
// // Check that backupAllGroupSessions returns valid data
|
||||
// val nbOfKeys = cryptoTestData.firstSession.cryptoService().inboundGroupSessionsCount(false)
|
||||
//
|
||||
// assertEquals(2, nbOfKeys)
|
||||
//
|
||||
// var lastBackedUpKeysProgress = 0
|
||||
//
|
||||
// mTestHelper.doSync<Unit> {
|
||||
// keysBackup.backupAllGroupSessions(object : ProgressListener {
|
||||
// override fun onProgress(progress: Int, total: Int) {
|
||||
// assertEquals(nbOfKeys, total)
|
||||
// lastBackedUpKeysProgress = progress
|
||||
// }
|
||||
// }, it)
|
||||
// }
|
||||
//
|
||||
// assertEquals(nbOfKeys, lastBackedUpKeysProgress)
|
||||
//
|
||||
// val backedUpKeys = cryptoTestData.firstSession.cryptoService().inboundGroupSessionsCount(true)
|
||||
//
|
||||
// assertEquals("All keys must have been marked as backed up", nbOfKeys, backedUpKeys)
|
||||
//
|
||||
// stateObserver.stopAndCheckStates(null)
|
||||
// cryptoTestData.cleanUp(mTestHelper)
|
||||
// }
|
||||
|
||||
/**
|
||||
* Check encryption and decryption of megolm keys in the backup.
|
||||
|
@ -241,40 +235,40 @@ class KeysBackupTest : InstrumentedTest {
|
|||
* - Check [MXKeyBackup decryptKeyBackupData] returns stg
|
||||
* - Compare the decrypted megolm key with the original one
|
||||
*/
|
||||
@Test
|
||||
fun testEncryptAndDecryptKeysBackupData() {
|
||||
val cryptoTestData = mCryptoTestHelper.doE2ETestWithAliceAndBobInARoomWithEncryptedMessages()
|
||||
|
||||
val keysBackup = cryptoTestData.firstSession.cryptoService().keysBackupService() as DefaultKeysBackupService
|
||||
|
||||
val stateObserver = StateObserver(keysBackup)
|
||||
|
||||
// - Pick a megolm key
|
||||
val session = keysBackup.store.inboundGroupSessionsToBackup(1)[0]
|
||||
|
||||
val keyBackupCreationInfo = mKeysBackupTestHelper.prepareAndCreateKeysBackupData(keysBackup).megolmBackupCreationInfo
|
||||
|
||||
// - Check encryptGroupSession() returns stg
|
||||
val keyBackupData = keysBackup.encryptGroupSession(session)
|
||||
assertNotNull(keyBackupData)
|
||||
assertNotNull(keyBackupData!!.sessionData)
|
||||
|
||||
// - Check pkDecryptionFromRecoveryKey() is able to create a OlmPkDecryption
|
||||
val decryption = keysBackup.pkDecryptionFromRecoveryKey(keyBackupCreationInfo.recoveryKey)
|
||||
assertNotNull(decryption)
|
||||
// - Check decryptKeyBackupData() returns stg
|
||||
val sessionData = keysBackup
|
||||
.decryptKeyBackupData(keyBackupData,
|
||||
session.olmInboundGroupSession!!.sessionIdentifier(),
|
||||
cryptoTestData.roomId,
|
||||
decryption!!)
|
||||
assertNotNull(sessionData)
|
||||
// - Compare the decrypted megolm key with the original one
|
||||
mKeysBackupTestHelper.assertKeysEquals(session.exportKeys(), sessionData)
|
||||
|
||||
stateObserver.stopAndCheckStates(null)
|
||||
cryptoTestData.cleanUp(mTestHelper)
|
||||
}
|
||||
// @Test
|
||||
// fun testEncryptAndDecryptKeysBackupData() {
|
||||
// val cryptoTestData = mCryptoTestHelper.doE2ETestWithAliceAndBobInARoomWithEncryptedMessages()
|
||||
//
|
||||
// val keysBackup = cryptoTestData.firstSession.cryptoService().keysBackupService() as DefaultKeysBackupService
|
||||
//
|
||||
// val stateObserver = StateObserver(keysBackup)
|
||||
//
|
||||
// // - Pick a megolm key
|
||||
// val session = keysBackup.store.inboundGroupSessionsToBackup(1)[0]
|
||||
//
|
||||
// val keyBackupCreationInfo = mKeysBackupTestHelper.prepareAndCreateKeysBackupData(keysBackup).megolmBackupCreationInfo
|
||||
//
|
||||
// // - Check encryptGroupSession() returns stg
|
||||
// val keyBackupData = keysBackup.encryptGroupSession(session)
|
||||
// assertNotNull(keyBackupData)
|
||||
// assertNotNull(keyBackupData!!.sessionData)
|
||||
//
|
||||
// // - Check pkDecryptionFromRecoveryKey() is able to create a OlmPkDecryption
|
||||
// val decryption = keysBackup.pkDecryptionFromRecoveryKey(keyBackupCreationInfo.recoveryKey)
|
||||
// assertNotNull(decryption)
|
||||
// // - Check decryptKeyBackupData() returns stg
|
||||
// val sessionData = keysBackup
|
||||
// .decryptKeyBackupData(keyBackupData,
|
||||
// session.olmInboundGroupSession!!.sessionIdentifier(),
|
||||
// cryptoTestData.roomId,
|
||||
// decryption!!)
|
||||
// assertNotNull(sessionData)
|
||||
// // - Compare the decrypted megolm key with the original one
|
||||
// mKeysBackupTestHelper.assertKeysEquals(session.exportKeys(), sessionData)
|
||||
//
|
||||
// stateObserver.stopAndCheckStates(null)
|
||||
// cryptoTestData.cleanUp(mTestHelper)
|
||||
// }
|
||||
|
||||
/**
|
||||
* - Do an e2e backup to the homeserver with a recovery key
|
||||
|
@ -287,13 +281,12 @@ class KeysBackupTest : InstrumentedTest {
|
|||
val testData = mKeysBackupTestHelper.createKeysBackupScenarioWithPassword(null)
|
||||
|
||||
// - Restore the e2e backup from the homeserver
|
||||
val importRoomKeysResult = mTestHelper.doSync<ImportRoomKeysResult> {
|
||||
val importRoomKeysResult = mTestHelper.runBlockingTest {
|
||||
testData.aliceSession2.cryptoService().keysBackupService().restoreKeysWithRecoveryKey(testData.aliceSession2.cryptoService().keysBackupService().keysBackupVersion!!,
|
||||
testData.prepareKeysBackupDataResult.megolmBackupCreationInfo.recoveryKey,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
it
|
||||
null
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -379,11 +372,10 @@ class KeysBackupTest : InstrumentedTest {
|
|||
assertEquals(KeysBackupState.NotTrusted, testData.aliceSession2.cryptoService().keysBackupService().state)
|
||||
|
||||
// - Trust the backup from the new device
|
||||
mTestHelper.doSync<Unit> {
|
||||
mTestHelper.runBlockingTest {
|
||||
testData.aliceSession2.cryptoService().keysBackupService().trustKeysBackupVersion(
|
||||
testData.aliceSession2.cryptoService().keysBackupService().keysBackupVersion!!,
|
||||
true,
|
||||
it
|
||||
true
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -395,15 +387,15 @@ class KeysBackupTest : InstrumentedTest {
|
|||
assertTrue(testData.aliceSession2.cryptoService().keysBackupService().isEnabled)
|
||||
|
||||
// - Retrieve the last version from the server
|
||||
val keysVersionResult = mTestHelper.doSync<KeysVersionResult?> {
|
||||
testData.aliceSession2.cryptoService().keysBackupService().getCurrentVersion(it)
|
||||
val keysVersionResult = mTestHelper.runBlockingTest {
|
||||
testData.aliceSession2.cryptoService().keysBackupService().getCurrentVersion()
|
||||
}
|
||||
|
||||
// - It must be the same
|
||||
assertEquals(testData.prepareKeysBackupDataResult.version, keysVersionResult!!.version)
|
||||
|
||||
val keysBackupVersionTrust = mTestHelper.doSync<KeysBackupVersionTrust> {
|
||||
testData.aliceSession2.cryptoService().keysBackupService().getKeysBackupTrust(keysVersionResult, it)
|
||||
val keysBackupVersionTrust = mTestHelper.runBlockingTest {
|
||||
testData.aliceSession2.cryptoService().keysBackupService().getKeysBackupTrust(keysVersionResult)
|
||||
}
|
||||
|
||||
// - It must be trusted and must have 2 signatures now
|
||||
|
@ -438,11 +430,10 @@ class KeysBackupTest : InstrumentedTest {
|
|||
assertEquals(KeysBackupState.NotTrusted, testData.aliceSession2.cryptoService().keysBackupService().state)
|
||||
|
||||
// - Trust the backup from the new device with the recovery key
|
||||
mTestHelper.doSync<Unit> {
|
||||
mTestHelper.runBlockingTest {
|
||||
testData.aliceSession2.cryptoService().keysBackupService().trustKeysBackupVersionWithRecoveryKey(
|
||||
testData.aliceSession2.cryptoService().keysBackupService().keysBackupVersion!!,
|
||||
testData.prepareKeysBackupDataResult.megolmBackupCreationInfo.recoveryKey,
|
||||
it
|
||||
testData.prepareKeysBackupDataResult.megolmBackupCreationInfo.recoveryKey
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -454,15 +445,15 @@ class KeysBackupTest : InstrumentedTest {
|
|||
assertTrue(testData.aliceSession2.cryptoService().keysBackupService().isEnabled)
|
||||
|
||||
// - Retrieve the last version from the server
|
||||
val keysVersionResult = mTestHelper.doSync<KeysVersionResult?> {
|
||||
testData.aliceSession2.cryptoService().keysBackupService().getCurrentVersion(it)
|
||||
val keysVersionResult = mTestHelper.runBlockingTest {
|
||||
testData.aliceSession2.cryptoService().keysBackupService().getCurrentVersion()
|
||||
}
|
||||
|
||||
// - It must be the same
|
||||
assertEquals(testData.prepareKeysBackupDataResult.version, keysVersionResult!!.version)
|
||||
|
||||
val keysBackupVersionTrust = mTestHelper.doSync<KeysBackupVersionTrust> {
|
||||
testData.aliceSession2.cryptoService().keysBackupService().getKeysBackupTrust(keysVersionResult, it)
|
||||
val keysBackupVersionTrust = mTestHelper.runBlockingTest {
|
||||
testData.aliceSession2.cryptoService().keysBackupService().getKeysBackupTrust(keysVersionResult)
|
||||
}
|
||||
|
||||
// - It must be trusted and must have 2 signatures now
|
||||
|
@ -495,13 +486,16 @@ class KeysBackupTest : InstrumentedTest {
|
|||
assertEquals(KeysBackupState.NotTrusted, testData.aliceSession2.cryptoService().keysBackupService().state)
|
||||
|
||||
// - Try to trust the backup from the new device with a wrong recovery key
|
||||
val latch = CountDownLatch(1)
|
||||
testData.aliceSession2.cryptoService().keysBackupService().trustKeysBackupVersionWithRecoveryKey(
|
||||
testData.aliceSession2.cryptoService().keysBackupService().keysBackupVersion!!,
|
||||
"Bad recovery key",
|
||||
TestMatrixCallback(latch, false)
|
||||
)
|
||||
mTestHelper.await(latch)
|
||||
mTestHelper.runBlockingTest {
|
||||
try {
|
||||
testData.aliceSession2.cryptoService().keysBackupService().trustKeysBackupVersionWithRecoveryKey(
|
||||
testData.aliceSession2.cryptoService().keysBackupService().keysBackupVersion!!,
|
||||
"Bad recovery key"
|
||||
)
|
||||
fail("Should have failed to trust")
|
||||
} catch (failure: Throwable) {
|
||||
}
|
||||
}
|
||||
|
||||
// - The new device must still see the previous backup as not trusted
|
||||
assertNotNull(testData.aliceSession2.cryptoService().keysBackupService().keysBackupVersion)
|
||||
|
@ -538,11 +532,10 @@ class KeysBackupTest : InstrumentedTest {
|
|||
assertEquals(KeysBackupState.NotTrusted, testData.aliceSession2.cryptoService().keysBackupService().state)
|
||||
|
||||
// - Trust the backup from the new device with the password
|
||||
mTestHelper.doSync<Unit> {
|
||||
mTestHelper.runBlockingTest {
|
||||
testData.aliceSession2.cryptoService().keysBackupService().trustKeysBackupVersionWithPassphrase(
|
||||
testData.aliceSession2.cryptoService().keysBackupService().keysBackupVersion!!,
|
||||
password,
|
||||
it
|
||||
password
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -554,15 +547,15 @@ class KeysBackupTest : InstrumentedTest {
|
|||
assertTrue(testData.aliceSession2.cryptoService().keysBackupService().isEnabled)
|
||||
|
||||
// - Retrieve the last version from the server
|
||||
val keysVersionResult = mTestHelper.doSync<KeysVersionResult?> {
|
||||
testData.aliceSession2.cryptoService().keysBackupService().getCurrentVersion(it)
|
||||
val keysVersionResult = mTestHelper.runBlockingTest {
|
||||
testData.aliceSession2.cryptoService().keysBackupService().getCurrentVersion()
|
||||
}
|
||||
|
||||
// - It must be the same
|
||||
assertEquals(testData.prepareKeysBackupDataResult.version, keysVersionResult!!.version)
|
||||
|
||||
val keysBackupVersionTrust = mTestHelper.doSync<KeysBackupVersionTrust> {
|
||||
testData.aliceSession2.cryptoService().keysBackupService().getKeysBackupTrust(keysVersionResult, it)
|
||||
val keysBackupVersionTrust = mTestHelper.runBlockingTest {
|
||||
testData.aliceSession2.cryptoService().keysBackupService().getKeysBackupTrust(keysVersionResult)
|
||||
}
|
||||
|
||||
// - It must be trusted and must have 2 signatures now
|
||||
|
@ -599,11 +592,16 @@ class KeysBackupTest : InstrumentedTest {
|
|||
|
||||
// - Try to trust the backup from the new device with a wrong password
|
||||
val latch = CountDownLatch(1)
|
||||
testData.aliceSession2.cryptoService().keysBackupService().trustKeysBackupVersionWithPassphrase(
|
||||
testData.aliceSession2.cryptoService().keysBackupService().keysBackupVersion!!,
|
||||
badPassword,
|
||||
TestMatrixCallback(latch, false)
|
||||
)
|
||||
mTestHelper.runBlockingTest {
|
||||
try {
|
||||
testData.aliceSession2.cryptoService().keysBackupService().trustKeysBackupVersionWithPassphrase(
|
||||
testData.aliceSession2.cryptoService().keysBackupService().keysBackupVersion!!,
|
||||
badPassword
|
||||
)
|
||||
fail("Should have fail to trust")
|
||||
} catch (failure: Throwable) {
|
||||
}
|
||||
}
|
||||
mTestHelper.await(latch)
|
||||
|
||||
// - The new device must still see the previous backup as not trusted
|
||||
|
@ -626,21 +624,17 @@ class KeysBackupTest : InstrumentedTest {
|
|||
val testData = mKeysBackupTestHelper.createKeysBackupScenarioWithPassword(null)
|
||||
|
||||
// - Try to restore the e2e backup with a wrong recovery key
|
||||
val latch2 = CountDownLatch(1)
|
||||
var importRoomKeysResult: ImportRoomKeysResult? = null
|
||||
testData.aliceSession2.cryptoService().keysBackupService().restoreKeysWithRecoveryKey(testData.aliceSession2.cryptoService().keysBackupService().keysBackupVersion!!,
|
||||
"EsTc LW2K PGiF wKEA 3As5 g5c4 BXwk qeeJ ZJV8 Q9fu gUMN UE4d",
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
object : TestMatrixCallback<ImportRoomKeysResult>(latch2, false) {
|
||||
override fun onSuccess(data: ImportRoomKeysResult) {
|
||||
importRoomKeysResult = data
|
||||
super.onSuccess(data)
|
||||
}
|
||||
}
|
||||
)
|
||||
mTestHelper.await(latch2)
|
||||
mTestHelper.runBlockingTest {
|
||||
testData.aliceSession2.cryptoService().keysBackupService().restoreKeysWithRecoveryKey(testData.aliceSession2.cryptoService().keysBackupService().keysBackupVersion!!,
|
||||
"EsTc LW2K PGiF wKEA 3As5 g5c4 BXwk qeeJ ZJV8 Q9fu gUMN UE4d",
|
||||
null,
|
||||
null,
|
||||
null
|
||||
).let { data ->
|
||||
importRoomKeysResult = data
|
||||
}
|
||||
}
|
||||
|
||||
// onSuccess may not have been called
|
||||
assertNull(importRoomKeysResult)
|
||||
|
@ -663,7 +657,7 @@ class KeysBackupTest : InstrumentedTest {
|
|||
// - Restore the e2e backup with the password
|
||||
val steps = ArrayList<StepProgressListener.Step>()
|
||||
|
||||
val importRoomKeysResult = mTestHelper.doSync<ImportRoomKeysResult> {
|
||||
val importRoomKeysResult = mTestHelper.runBlockingTest {
|
||||
testData.aliceSession2.cryptoService().keysBackupService().restoreKeyBackupWithPassword(testData.aliceSession2.cryptoService().keysBackupService().keysBackupVersion!!,
|
||||
password,
|
||||
null,
|
||||
|
@ -672,8 +666,7 @@ class KeysBackupTest : InstrumentedTest {
|
|||
override fun onStepProgress(step: StepProgressListener.Step) {
|
||||
steps.add(step)
|
||||
}
|
||||
},
|
||||
it
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -719,20 +712,16 @@ class KeysBackupTest : InstrumentedTest {
|
|||
// - Try to restore the e2e backup with a wrong password
|
||||
val latch2 = CountDownLatch(1)
|
||||
var importRoomKeysResult: ImportRoomKeysResult? = null
|
||||
testData.aliceSession2.cryptoService().keysBackupService().restoreKeyBackupWithPassword(testData.aliceSession2.cryptoService().keysBackupService().keysBackupVersion!!,
|
||||
wrongPassword,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
object : TestMatrixCallback<ImportRoomKeysResult>(latch2, false) {
|
||||
override fun onSuccess(data: ImportRoomKeysResult) {
|
||||
importRoomKeysResult = data
|
||||
super.onSuccess(data)
|
||||
}
|
||||
}
|
||||
)
|
||||
mTestHelper.await(latch2)
|
||||
|
||||
mTestHelper.runBlockingTest {
|
||||
testData.aliceSession2.cryptoService().keysBackupService().restoreKeyBackupWithPassword(testData.aliceSession2.cryptoService().keysBackupService().keysBackupVersion!!,
|
||||
wrongPassword,
|
||||
null,
|
||||
null,
|
||||
null
|
||||
).let {
|
||||
importRoomKeysResult = it
|
||||
}
|
||||
}
|
||||
// onSuccess may not have been called
|
||||
assertNull(importRoomKeysResult)
|
||||
|
||||
|
@ -752,13 +741,12 @@ class KeysBackupTest : InstrumentedTest {
|
|||
val testData = mKeysBackupTestHelper.createKeysBackupScenarioWithPassword(password)
|
||||
|
||||
// - Restore the e2e backup with the recovery key.
|
||||
val importRoomKeysResult = mTestHelper.doSync<ImportRoomKeysResult> {
|
||||
val importRoomKeysResult = mTestHelper.runBlockingTest {
|
||||
testData.aliceSession2.cryptoService().keysBackupService().restoreKeysWithRecoveryKey(testData.aliceSession2.cryptoService().keysBackupService().keysBackupVersion!!,
|
||||
testData.prepareKeysBackupDataResult.megolmBackupCreationInfo.recoveryKey,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
it
|
||||
null
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -780,18 +768,16 @@ class KeysBackupTest : InstrumentedTest {
|
|||
// - Try to restore the e2e backup with a password
|
||||
val latch2 = CountDownLatch(1)
|
||||
var importRoomKeysResult: ImportRoomKeysResult? = null
|
||||
testData.aliceSession2.cryptoService().keysBackupService().restoreKeyBackupWithPassword(testData.aliceSession2.cryptoService().keysBackupService().keysBackupVersion!!,
|
||||
"password",
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
object : TestMatrixCallback<ImportRoomKeysResult>(latch2, false) {
|
||||
override fun onSuccess(data: ImportRoomKeysResult) {
|
||||
importRoomKeysResult = data
|
||||
super.onSuccess(data)
|
||||
}
|
||||
}
|
||||
)
|
||||
mTestHelper.runBlockingTest {
|
||||
testData.aliceSession2.cryptoService().keysBackupService().restoreKeyBackupWithPassword(testData.aliceSession2.cryptoService().keysBackupService().keysBackupVersion!!,
|
||||
"password",
|
||||
null,
|
||||
null,
|
||||
null
|
||||
).let {
|
||||
importRoomKeysResult = it
|
||||
}
|
||||
}
|
||||
mTestHelper.await(latch2)
|
||||
|
||||
// onSuccess may not have been called
|
||||
|
@ -817,13 +803,13 @@ class KeysBackupTest : InstrumentedTest {
|
|||
mKeysBackupTestHelper.prepareAndCreateKeysBackupData(keysBackup)
|
||||
|
||||
// Get key backup version from the homeserver
|
||||
val keysVersionResult = mTestHelper.doSync<KeysVersionResult?> {
|
||||
keysBackup.getCurrentVersion(it)
|
||||
val keysVersionResult = mTestHelper.runBlockingTest {
|
||||
keysBackup.getCurrentVersion()
|
||||
}
|
||||
|
||||
// - Check the returned KeyBackupVersion is trusted
|
||||
val keysBackupVersionTrust = mTestHelper.doSync<KeysBackupVersionTrust> {
|
||||
keysBackup.getKeysBackupTrust(keysVersionResult!!, it)
|
||||
val keysBackupVersionTrust = mTestHelper.runBlockingTest {
|
||||
keysBackup.getKeysBackupTrust(keysVersionResult!!)
|
||||
}
|
||||
|
||||
assertNotNull(keysBackupVersionTrust)
|
||||
|
@ -908,64 +894,64 @@ class KeysBackupTest : InstrumentedTest {
|
|||
* - Make alice back up all her keys again
|
||||
* -> That must fail and her backup state must be WrongBackUpVersion
|
||||
*/
|
||||
@Test
|
||||
fun testBackupWhenAnotherBackupWasCreated() {
|
||||
// - Create a backup version
|
||||
val cryptoTestData = mCryptoTestHelper.doE2ETestWithAliceAndBobInARoomWithEncryptedMessages()
|
||||
|
||||
val keysBackup = cryptoTestData.firstSession.cryptoService().keysBackupService()
|
||||
|
||||
val stateObserver = StateObserver(keysBackup)
|
||||
|
||||
assertFalse(keysBackup.isEnabled)
|
||||
|
||||
// Wait for keys backup to be finished
|
||||
val latch0 = CountDownLatch(1)
|
||||
var count = 0
|
||||
keysBackup.addListener(object : KeysBackupStateListener {
|
||||
override fun onStateChange(newState: KeysBackupState) {
|
||||
// Check the backup completes
|
||||
if (newState == KeysBackupState.ReadyToBackUp) {
|
||||
count++
|
||||
|
||||
if (count == 2) {
|
||||
// Remove itself from the list of listeners
|
||||
keysBackup.removeListener(this)
|
||||
|
||||
latch0.countDown()
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
// - Make alice back up her keys to her homeserver
|
||||
mKeysBackupTestHelper.prepareAndCreateKeysBackupData(keysBackup)
|
||||
|
||||
assertTrue(keysBackup.isEnabled)
|
||||
|
||||
mTestHelper.await(latch0)
|
||||
|
||||
// - Create a new backup with fake data on the homeserver, directly using the rest client
|
||||
val megolmBackupCreationInfo = mCryptoTestHelper.createFakeMegolmBackupCreationInfo()
|
||||
mTestHelper.doSync<KeysVersion> {
|
||||
(keysBackup as DefaultKeysBackupService).createFakeKeysBackupVersion(megolmBackupCreationInfo, it)
|
||||
}
|
||||
|
||||
// Reset the store backup status for keys
|
||||
(cryptoTestData.firstSession.cryptoService().keysBackupService() as DefaultKeysBackupService).store.resetBackupMarkers()
|
||||
|
||||
// - Make alice back up all her keys again
|
||||
val latch2 = CountDownLatch(1)
|
||||
keysBackup.backupAllGroupSessions(null, TestMatrixCallback(latch2, false))
|
||||
mTestHelper.await(latch2)
|
||||
|
||||
// -> That must fail and her backup state must be WrongBackUpVersion
|
||||
assertEquals(KeysBackupState.WrongBackUpVersion, keysBackup.state)
|
||||
assertFalse(keysBackup.isEnabled)
|
||||
|
||||
stateObserver.stopAndCheckStates(null)
|
||||
cryptoTestData.cleanUp(mTestHelper)
|
||||
}
|
||||
// @Test
|
||||
// fun testBackupWhenAnotherBackupWasCreated() {
|
||||
// // - Create a backup version
|
||||
// val cryptoTestData = mCryptoTestHelper.doE2ETestWithAliceAndBobInARoomWithEncryptedMessages()
|
||||
//
|
||||
// val keysBackup = cryptoTestData.firstSession.cryptoService().keysBackupService()
|
||||
//
|
||||
// val stateObserver = StateObserver(keysBackup)
|
||||
//
|
||||
// assertFalse(keysBackup.isEnabled)
|
||||
//
|
||||
// // Wait for keys backup to be finished
|
||||
// val latch0 = CountDownLatch(1)
|
||||
// var count = 0
|
||||
// keysBackup.addListener(object : KeysBackupStateListener {
|
||||
// override fun onStateChange(newState: KeysBackupState) {
|
||||
// // Check the backup completes
|
||||
// if (newState == KeysBackupState.ReadyToBackUp) {
|
||||
// count++
|
||||
//
|
||||
// if (count == 2) {
|
||||
// // Remove itself from the list of listeners
|
||||
// keysBackup.removeListener(this)
|
||||
//
|
||||
// latch0.countDown()
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// })
|
||||
//
|
||||
// // - Make alice back up her keys to her homeserver
|
||||
// mKeysBackupTestHelper.prepareAndCreateKeysBackupData(keysBackup)
|
||||
//
|
||||
// assertTrue(keysBackup.isEnabled)
|
||||
//
|
||||
// mTestHelper.await(latch0)
|
||||
//
|
||||
// // - Create a new backup with fake data on the homeserver, directly using the rest client
|
||||
// val megolmBackupCreationInfo = mCryptoTestHelper.createFakeMegolmBackupCreationInfo()
|
||||
// mTestHelper.doSync<KeysVersion> {
|
||||
// (keysBackup as DefaultKeysBackupService).createFakeKeysBackupVersion(megolmBackupCreationInfo, it)
|
||||
// }
|
||||
//
|
||||
// // Reset the store backup status for keys
|
||||
// (cryptoTestData.firstSession.cryptoService().keysBackupService() as DefaultKeysBackupService).store.resetBackupMarkers()
|
||||
//
|
||||
// // - Make alice back up all her keys again
|
||||
// val latch2 = CountDownLatch(1)
|
||||
// keysBackup.backupAllGroupSessions(null, TestMatrixCallback(latch2, false))
|
||||
// mTestHelper.await(latch2)
|
||||
//
|
||||
// // -> That must fail and her backup state must be WrongBackUpVersion
|
||||
// assertEquals(KeysBackupState.WrongBackUpVersion, keysBackup.state)
|
||||
// assertFalse(keysBackup.isEnabled)
|
||||
//
|
||||
// stateObserver.stopAndCheckStates(null)
|
||||
// cryptoTestData.cleanUp(mTestHelper)
|
||||
// }
|
||||
|
||||
/**
|
||||
* - Do an e2e backup to the homeserver
|
||||
|
@ -992,9 +978,18 @@ class KeysBackupTest : InstrumentedTest {
|
|||
mKeysBackupTestHelper.prepareAndCreateKeysBackupData(keysBackup)
|
||||
|
||||
// Wait for keys backup to finish by asking again to backup keys.
|
||||
mTestHelper.doSync<Unit> {
|
||||
keysBackup.backupAllGroupSessions(null, it)
|
||||
mTestHelper.runBlockingTest {
|
||||
keysBackup.checkAndStartKeysBackup()
|
||||
delay(1000)
|
||||
}
|
||||
mTestHelper.waitWithLatch {
|
||||
mTestHelper.retryPeriodicallyWithLatch(it) {
|
||||
keysBackup.state == KeysBackupState.ReadyToBackUp
|
||||
}
|
||||
}
|
||||
// mTestHelper.doSync<Unit> {
|
||||
// keysBackup.backupAllGroupSessions(null, it)
|
||||
// }
|
||||
|
||||
val oldDeviceId = cryptoTestData.firstSession.sessionParams.deviceId!!
|
||||
val oldKeyBackupVersion = keysBackup.currentBackupVersion
|
||||
|
@ -1016,16 +1011,26 @@ class KeysBackupTest : InstrumentedTest {
|
|||
val stateObserver2 = StateObserver(keysBackup2)
|
||||
|
||||
var isSuccessful = false
|
||||
val latch2 = CountDownLatch(1)
|
||||
keysBackup2.backupAllGroupSessions(
|
||||
null,
|
||||
object : TestMatrixCallback<Unit>(latch2, false) {
|
||||
override fun onSuccess(data: Unit) {
|
||||
isSuccessful = true
|
||||
super.onSuccess(data)
|
||||
}
|
||||
})
|
||||
mTestHelper.await(latch2)
|
||||
// val latch2 = CountDownLatch(1)
|
||||
mTestHelper.runBlockingTest {
|
||||
keysBackup2.checkAndStartKeysBackup()
|
||||
delay(1000)
|
||||
}
|
||||
mTestHelper.waitWithLatch {
|
||||
mTestHelper.retryPeriodicallyWithLatch(it) {
|
||||
keysBackup2.state == KeysBackupState.ReadyToBackUp
|
||||
}
|
||||
}
|
||||
|
||||
// keysBackup2.backupAllGroupSessions(
|
||||
// null,
|
||||
// object : TestMatrixCallback<Unit>(latch2, false) {
|
||||
// override fun onSuccess(data: Unit) {
|
||||
// isSuccessful = true
|
||||
// super.onSuccess(data)
|
||||
// }
|
||||
// })
|
||||
// mTestHelper.await(latch2)
|
||||
|
||||
assertFalse(isSuccessful)
|
||||
|
||||
|
@ -1054,8 +1059,17 @@ class KeysBackupTest : InstrumentedTest {
|
|||
// -> It must use the same backup version
|
||||
assertEquals(oldKeyBackupVersion, aliceSession2.cryptoService().keysBackupService().currentBackupVersion)
|
||||
|
||||
mTestHelper.doSync<Unit> {
|
||||
aliceSession2.cryptoService().keysBackupService().backupAllGroupSessions(null, it)
|
||||
// mTestHelper.doSync<Unit> {
|
||||
// aliceSession2.cryptoService().keysBackupService().backupAllGroupSessions(null, it)
|
||||
// }
|
||||
mTestHelper.runBlockingTest {
|
||||
aliceSession2.cryptoService().keysBackupService().checkAndStartKeysBackup()
|
||||
delay(1000)
|
||||
}
|
||||
mTestHelper.waitWithLatch {
|
||||
mTestHelper.retryPeriodicallyWithLatch(it) {
|
||||
aliceSession2.cryptoService().keysBackupService().state == KeysBackupState.ReadyToBackUp
|
||||
}
|
||||
}
|
||||
|
||||
// -> It must success
|
||||
|
@ -1087,7 +1101,7 @@ class KeysBackupTest : InstrumentedTest {
|
|||
assertTrue(keysBackup.isEnabled)
|
||||
|
||||
// Delete the backup
|
||||
mTestHelper.doSync<Unit> { keysBackup.deleteBackup(keyBackupCreationInfo.version, it) }
|
||||
mTestHelper.runBlockingTest { keysBackup.deleteBackup(keyBackupCreationInfo.version) }
|
||||
|
||||
// Backup is now disabled
|
||||
assertFalse(keysBackup.isEnabled)
|
||||
|
|
|
@ -16,8 +16,8 @@
|
|||
|
||||
package org.matrix.android.sdk.internal.crypto.keysbackup
|
||||
|
||||
import kotlinx.coroutines.delay
|
||||
import org.junit.Assert
|
||||
import org.matrix.android.sdk.api.listeners.ProgressListener
|
||||
import org.matrix.android.sdk.api.session.Session
|
||||
import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupService
|
||||
import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupState
|
||||
|
@ -27,8 +27,6 @@ import org.matrix.android.sdk.common.CryptoTestHelper
|
|||
import org.matrix.android.sdk.common.assertDictEquals
|
||||
import org.matrix.android.sdk.common.assertListEquals
|
||||
import org.matrix.android.sdk.internal.crypto.MegolmSessionData
|
||||
import org.matrix.android.sdk.internal.crypto.keysbackup.model.MegolmBackupCreationInfo
|
||||
import org.matrix.android.sdk.internal.crypto.keysbackup.model.rest.KeysVersion
|
||||
import java.util.concurrent.CountDownLatch
|
||||
|
||||
class KeysBackupTestHelper(
|
||||
|
@ -45,29 +43,38 @@ class KeysBackupTestHelper(
|
|||
fun createKeysBackupScenarioWithPassword(password: String?): KeysBackupScenarioData {
|
||||
val cryptoTestData = mCryptoTestHelper.doE2ETestWithAliceAndBobInARoomWithEncryptedMessages()
|
||||
|
||||
val cryptoStore = (cryptoTestData.firstSession.cryptoService().keysBackupService() as DefaultKeysBackupService).store
|
||||
// val cryptoStore = (cryptoTestData.firstSession.cryptoService().keysBackupService() as DefaultKeysBackupService).store
|
||||
val keysBackup = cryptoTestData.firstSession.cryptoService().keysBackupService()
|
||||
|
||||
val stateObserver = StateObserver(keysBackup)
|
||||
|
||||
val aliceKeys = cryptoStore.inboundGroupSessionsToBackup(100)
|
||||
// val aliceKeys = cryptoStore.inboundGroupSessionsToBackup(100)
|
||||
|
||||
// - Do an e2e backup to the homeserver
|
||||
val prepareKeysBackupDataResult = prepareAndCreateKeysBackupData(keysBackup, password)
|
||||
|
||||
var lastProgress = 0
|
||||
var lastTotal = 0
|
||||
mTestHelper.doSync<Unit> {
|
||||
keysBackup.backupAllGroupSessions(object : ProgressListener {
|
||||
override fun onProgress(progress: Int, total: Int) {
|
||||
lastProgress = progress
|
||||
lastTotal = total
|
||||
}
|
||||
}, it)
|
||||
// var lastProgress = 0
|
||||
// var lastTotal = 0
|
||||
// mTestHelper.doSync<Unit> {
|
||||
// keysBackup.backupAllGroupSessions(object : ProgressListener {
|
||||
// override fun onProgress(progress: Int, total: Int) {
|
||||
// lastProgress = progress
|
||||
// lastTotal = total
|
||||
// }
|
||||
// }, it)
|
||||
// }
|
||||
|
||||
mTestHelper.runBlockingTest {
|
||||
keysBackup.checkAndStartKeysBackup()
|
||||
delay(1000)
|
||||
}
|
||||
mTestHelper.waitWithLatch {
|
||||
mTestHelper.retryPeriodicallyWithLatch(it) {
|
||||
keysBackup.state == KeysBackupState.ReadyToBackUp
|
||||
}
|
||||
}
|
||||
|
||||
Assert.assertEquals(2, lastProgress)
|
||||
Assert.assertEquals(2, lastTotal)
|
||||
Assert.assertEquals(2, cryptoTestData.firstSession.cryptoService().keysBackupService().getTotalNumbersOfBackedUpKeys())
|
||||
|
||||
val aliceUserId = cryptoTestData.firstSession.myUserId
|
||||
|
||||
|
@ -83,7 +90,7 @@ class KeysBackupTestHelper(
|
|||
stateObserver.stopAndCheckStates(null)
|
||||
|
||||
return KeysBackupScenarioData(cryptoTestData,
|
||||
aliceKeys,
|
||||
aliceSession2.cryptoService().keysBackupService().getTotalNumbersOfBackedUpKeys(),
|
||||
prepareKeysBackupDataResult,
|
||||
aliceSession2)
|
||||
}
|
||||
|
@ -92,8 +99,8 @@ class KeysBackupTestHelper(
|
|||
password: String? = null): PrepareKeysBackupDataResult {
|
||||
val stateObserver = StateObserver(keysBackup)
|
||||
|
||||
val megolmBackupCreationInfo = mTestHelper.doSync<MegolmBackupCreationInfo> {
|
||||
keysBackup.prepareKeysBackupVersion(password, null, it)
|
||||
val megolmBackupCreationInfo = mTestHelper.runBlockingTest {
|
||||
keysBackup.prepareKeysBackupVersion(password)
|
||||
}
|
||||
|
||||
Assert.assertNotNull(megolmBackupCreationInfo)
|
||||
|
@ -101,8 +108,8 @@ class KeysBackupTestHelper(
|
|||
Assert.assertFalse(keysBackup.isEnabled)
|
||||
|
||||
// Create the version
|
||||
val keysVersion = mTestHelper.doSync<KeysVersion> {
|
||||
keysBackup.createKeysBackupVersion(megolmBackupCreationInfo, it)
|
||||
val keysVersion = mTestHelper.runBlockingTest {
|
||||
keysBackup.createKeysBackupVersion(megolmBackupCreationInfo)
|
||||
}
|
||||
|
||||
Assert.assertNotNull(keysVersion.version)
|
||||
|
@ -165,18 +172,19 @@ class KeysBackupTestHelper(
|
|||
total: Int,
|
||||
imported: Int) {
|
||||
// - Imported keys number must be correct
|
||||
Assert.assertEquals(testData.aliceKeys.size, total)
|
||||
Assert.assertEquals(testData.aliceKeys, total)
|
||||
Assert.assertEquals(total, imported)
|
||||
|
||||
// - The new device must have the same count of megolm keys
|
||||
Assert.assertEquals(testData.aliceKeys.size, testData.aliceSession2.cryptoService().inboundGroupSessionsCount(false))
|
||||
Assert.assertEquals(testData.aliceKeys, testData.aliceSession2.cryptoService().inboundGroupSessionsCount(false))
|
||||
|
||||
// - Alice must have the same keys on both devices
|
||||
for (aliceKey1 in testData.aliceKeys) {
|
||||
val aliceKey2 = (testData.aliceSession2.cryptoService().keysBackupService() as DefaultKeysBackupService).store
|
||||
.getInboundGroupSession(aliceKey1.olmInboundGroupSession!!.sessionIdentifier(), aliceKey1.senderKey!!)
|
||||
Assert.assertNotNull(aliceKey2)
|
||||
assertKeysEquals(aliceKey1.exportKeys(), aliceKey2!!.exportKeys())
|
||||
}
|
||||
//
|
||||
// for (aliceKey1 in testData.aliceKeys) {
|
||||
// val aliceKey2 = (testData.aliceSession2.cryptoService().keysBackupService() as DefaultKeysBackupService).store
|
||||
// .getInboundGroupSession(aliceKey1.olmInboundGroupSession!!.sessionIdentifier(), aliceKey1.senderKey!!)
|
||||
// Assert.assertNotNull(aliceKey2)
|
||||
// assertKeysEquals(aliceKey1.exportKeys(), aliceKey2!!.exportKeys())
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@ interface StepProgressListener {
|
|||
sealed class Step {
|
||||
data class ComputingKey(val progress: Int, val total: Int) : Step()
|
||||
object DownloadingKey : Step()
|
||||
data class DecryptingKey(val progress: Int, val total: Int) : Step()
|
||||
data class ImportingKey(val progress: Int, val total: Int) : Step()
|
||||
}
|
||||
|
||||
|
|
|
@ -61,7 +61,7 @@ interface CrossSigningService {
|
|||
* This will check if the injected private cross signing keys match the public ones provided
|
||||
* by the server and if they do so
|
||||
*/
|
||||
fun checkTrustFromPrivateKeys(masterKeyPrivateKey: String?,
|
||||
suspend fun checkTrustFromPrivateKeys(masterKeyPrivateKey: String?,
|
||||
uskKeyPrivateKey: String?,
|
||||
sskPrivateKey: String?): UserTrustResult
|
||||
|
||||
|
@ -102,8 +102,8 @@ interface CrossSigningService {
|
|||
/**
|
||||
* Sign one of your devices and upload the signature
|
||||
*/
|
||||
fun trustDevice(deviceId: String,
|
||||
callback: MatrixCallback<Unit>)
|
||||
@Throws
|
||||
suspend fun trustDevice(deviceId: String)
|
||||
|
||||
suspend fun shieldForGroup(userIds: List<String>): RoomEncryptionTrustLevel
|
||||
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
|
||||
package org.matrix.android.sdk.api.session.crypto.keysbackup
|
||||
|
||||
import org.matrix.android.sdk.api.MatrixCallback
|
||||
import org.matrix.android.sdk.api.listeners.ProgressListener
|
||||
import org.matrix.android.sdk.api.listeners.StepProgressListener
|
||||
import org.matrix.android.sdk.internal.crypto.keysbackup.model.KeysBackupVersionTrust
|
||||
|
@ -31,18 +30,17 @@ interface KeysBackupService {
|
|||
* Retrieve the current version of the backup from the homeserver
|
||||
*
|
||||
* It can be different than keysBackupVersion.
|
||||
* @param callback onSuccess(null) will be called if there is no backup on the server
|
||||
*/
|
||||
fun getCurrentVersion(callback: MatrixCallback<KeysVersionResult?>)
|
||||
suspend fun getCurrentVersion(): KeysVersionResult?
|
||||
|
||||
/**
|
||||
* Create a new keys backup version and enable it, using the information return from [prepareKeysBackupVersion].
|
||||
*
|
||||
* @param keysBackupCreationInfo the info object from [prepareKeysBackupVersion].
|
||||
* @param callback Asynchronous callback
|
||||
* @return KeysVersion
|
||||
*/
|
||||
fun createKeysBackupVersion(keysBackupCreationInfo: MegolmBackupCreationInfo,
|
||||
callback: MatrixCallback<KeysVersion>)
|
||||
@Throws
|
||||
suspend fun createKeysBackupVersion(keysBackupCreationInfo: MegolmBackupCreationInfo): KeysVersion
|
||||
|
||||
/**
|
||||
* Facility method to get the total number of locally stored keys
|
||||
|
@ -54,23 +52,21 @@ interface KeysBackupService {
|
|||
*/
|
||||
fun getTotalNumbersOfBackedUpKeys(): Int
|
||||
|
||||
/**
|
||||
* Start to back up keys immediately.
|
||||
*
|
||||
* @param progressListener the callback to follow the progress
|
||||
* @param callback the main callback
|
||||
*/
|
||||
fun backupAllGroupSessions(progressListener: ProgressListener?,
|
||||
callback: MatrixCallback<Unit>?)
|
||||
// /**
|
||||
// * Start to back up keys immediately.
|
||||
// *
|
||||
// * @param progressListener the callback to follow the progress
|
||||
// * @param callback the main callback
|
||||
// */
|
||||
// fun backupAllGroupSessions(progressListener: ProgressListener?,
|
||||
// callback: MatrixCallback<Unit>?)
|
||||
|
||||
/**
|
||||
* Check trust on a key backup version.
|
||||
*
|
||||
* @param keysBackupVersion the backup version to check.
|
||||
* @param callback block called when the operations completes.
|
||||
*/
|
||||
fun getKeysBackupTrust(keysBackupVersion: KeysVersionResult,
|
||||
callback: MatrixCallback<KeysBackupVersionTrust>)
|
||||
suspend fun getKeysBackupTrust(keysBackupVersion: KeysVersionResult): KeysBackupVersionTrust
|
||||
|
||||
/**
|
||||
* Return the current progress of the backup
|
||||
|
@ -82,18 +78,16 @@ interface KeysBackupService {
|
|||
*
|
||||
* It can be different than keysBackupVersion.
|
||||
* @param version the backup version
|
||||
* @param callback
|
||||
*/
|
||||
fun getVersion(version: String,
|
||||
callback: MatrixCallback<KeysVersionResult?>)
|
||||
suspend fun getVersion(version: String): KeysVersionResult?
|
||||
|
||||
/**
|
||||
* This method fetches the last backup version on the server, then compare to the currently backup version use.
|
||||
* If versions are not the same, the current backup is deleted (on server or locally), then the backup may be started again, using the last version.
|
||||
*
|
||||
* @param callback true if backup is already using the last version, and false if it is not the case
|
||||
* @return true if backup is already using the last version, and false if it is not the case
|
||||
*/
|
||||
fun forceUsingLastVersion(callback: MatrixCallback<Boolean>)
|
||||
suspend fun forceUsingLastVersion(): Boolean
|
||||
|
||||
/**
|
||||
* Check the server for an active key backup.
|
||||
|
@ -101,7 +95,7 @@ interface KeysBackupService {
|
|||
* If one is present and has a valid signature from one of the user's verified
|
||||
* devices, start backing up to it.
|
||||
*/
|
||||
fun checkAndStartKeysBackup()
|
||||
suspend fun checkAndStartKeysBackup()
|
||||
|
||||
fun addListener(listener: KeysBackupStateListener)
|
||||
|
||||
|
@ -119,19 +113,16 @@ interface KeysBackupService {
|
|||
* @param progressListener a progress listener, as generating private key from password may take a while
|
||||
* @param callback Asynchronous callback
|
||||
*/
|
||||
fun prepareKeysBackupVersion(password: String?,
|
||||
progressListener: ProgressListener?,
|
||||
callback: MatrixCallback<MegolmBackupCreationInfo>)
|
||||
suspend fun prepareKeysBackupVersion(password: String?): MegolmBackupCreationInfo
|
||||
|
||||
/**
|
||||
* Delete a keys backup version. It will delete all backed up keys on the server, and the backup itself.
|
||||
* If we are backing up to this version. Backup will be stopped.
|
||||
*
|
||||
* @param version the backup version to delete.
|
||||
* @param callback Asynchronous callback
|
||||
*/
|
||||
fun deleteBackup(version: String,
|
||||
callback: MatrixCallback<Unit>?)
|
||||
@Throws
|
||||
suspend fun deleteBackup(version: String)
|
||||
|
||||
/**
|
||||
* Ask if the backup on the server contains keys that we may do not have locally.
|
||||
|
@ -145,35 +136,29 @@ interface KeysBackupService {
|
|||
*
|
||||
* @param keysBackupVersion the backup version to check.
|
||||
* @param trust the trust to set to the keys backup.
|
||||
* @param callback block called when the operations completes.
|
||||
*/
|
||||
fun trustKeysBackupVersion(keysBackupVersion: KeysVersionResult,
|
||||
trust: Boolean,
|
||||
callback: MatrixCallback<Unit>)
|
||||
@Throws
|
||||
suspend fun trustKeysBackupVersion(keysBackupVersion: KeysVersionResult, trust: Boolean)
|
||||
|
||||
/**
|
||||
* Set trust on a keys backup version.
|
||||
*
|
||||
* @param keysBackupVersion the backup version to check.
|
||||
* @param recoveryKey the recovery key to challenge with the key backup public key.
|
||||
* @param callback block called when the operations completes.
|
||||
*/
|
||||
fun trustKeysBackupVersionWithRecoveryKey(keysBackupVersion: KeysVersionResult,
|
||||
recoveryKey: String,
|
||||
callback: MatrixCallback<Unit>)
|
||||
suspend fun trustKeysBackupVersionWithRecoveryKey(keysBackupVersion: KeysVersionResult,
|
||||
recoveryKey: String)
|
||||
|
||||
/**
|
||||
* Set trust on a keys backup version.
|
||||
*
|
||||
* @param keysBackupVersion the backup version to check.
|
||||
* @param password the pass phrase to challenge with the keyBackupVersion public key.
|
||||
* @param callback block called when the operations completes.
|
||||
*/
|
||||
fun trustKeysBackupVersionWithPassphrase(keysBackupVersion: KeysVersionResult,
|
||||
password: String,
|
||||
callback: MatrixCallback<Unit>)
|
||||
suspend fun trustKeysBackupVersionWithPassphrase(keysBackupVersion: KeysVersionResult,
|
||||
password: String)
|
||||
|
||||
fun onSecretKeyGossip(secret: String)
|
||||
suspend fun onSecretKeyGossip(secret: String)
|
||||
|
||||
/**
|
||||
* Restore a backup with a recovery key from a given backup version stored on the homeserver.
|
||||
|
@ -185,11 +170,10 @@ interface KeysBackupService {
|
|||
* @param stepProgressListener the step progress listener
|
||||
* @param callback Callback. It provides the number of found keys and the number of successfully imported keys.
|
||||
*/
|
||||
fun restoreKeysWithRecoveryKey(keysVersionResult: KeysVersionResult,
|
||||
suspend fun restoreKeysWithRecoveryKey(keysVersionResult: KeysVersionResult,
|
||||
recoveryKey: String, roomId: String?,
|
||||
sessionId: String?,
|
||||
stepProgressListener: StepProgressListener?,
|
||||
callback: MatrixCallback<ImportRoomKeysResult>)
|
||||
stepProgressListener: StepProgressListener?): ImportRoomKeysResult
|
||||
|
||||
/**
|
||||
* Restore a backup with a password from a given backup version stored on the homeserver.
|
||||
|
@ -201,12 +185,11 @@ interface KeysBackupService {
|
|||
* @param stepProgressListener the step progress listener
|
||||
* @param callback Callback. It provides the number of found keys and the number of successfully imported keys.
|
||||
*/
|
||||
fun restoreKeyBackupWithPassword(keysBackupVersion: KeysVersionResult,
|
||||
suspend fun restoreKeyBackupWithPassword(keysBackupVersion: KeysVersionResult,
|
||||
password: String,
|
||||
roomId: String?,
|
||||
sessionId: String?,
|
||||
stepProgressListener: StepProgressListener?,
|
||||
callback: MatrixCallback<ImportRoomKeysResult>)
|
||||
stepProgressListener: StepProgressListener?): ImportRoomKeysResult
|
||||
|
||||
val keysBackupVersion: KeysVersionResult?
|
||||
val currentBackupVersion: String?
|
||||
|
@ -218,5 +201,5 @@ interface KeysBackupService {
|
|||
fun saveBackupRecoveryKey(recoveryKey: String?, version: String?)
|
||||
fun getKeyBackupRecoveryKeyInfo(): SavedKeyBackupKeyInfo?
|
||||
|
||||
fun isValidRecoveryKeyForCurrentVersion(recoveryKey: String, callback: MatrixCallback<Boolean>)
|
||||
suspend fun isValidRecoveryKeyForCurrentVersion(recoveryKey: String): Boolean
|
||||
}
|
||||
|
|
|
@ -90,6 +90,7 @@ import java.util.concurrent.ConcurrentHashMap
|
|||
import java.util.concurrent.atomic.AtomicBoolean
|
||||
import javax.inject.Inject
|
||||
import kotlin.math.max
|
||||
import kotlin.system.measureTimeMillis
|
||||
|
||||
/**
|
||||
* A `CryptoService` class instance manages the end-to-end crypto for a session.
|
||||
|
@ -134,6 +135,7 @@ internal class DefaultCryptoService @Inject constructor(
|
|||
private val crossSigningService: CrossSigningService,
|
||||
private val verificationService: RustVerificationService,
|
||||
private val keysBackupService: RustKeyBackupService,
|
||||
private val megolmSessionImportManager: MegolmSessionImportManager,
|
||||
private val olmMachineProvider: OlmMachineProvider
|
||||
) : CryptoService {
|
||||
|
||||
|
@ -152,9 +154,6 @@ internal class DefaultCryptoService @Inject constructor(
|
|||
private val outgoingRequestsLock: Mutex = Mutex()
|
||||
private val roomKeyShareLocks: ConcurrentHashMap<String, Mutex> = ConcurrentHashMap()
|
||||
|
||||
// TODO does this need to be concurrent?
|
||||
private val newSessionListeners = ArrayList<NewSessionListener>()
|
||||
|
||||
fun onStateEvent(roomId: String, event: Event) {
|
||||
when (event.getClearType()) {
|
||||
EventType.STATE_ROOM_ENCRYPTION -> onRoomEncryptionEvent(roomId, event)
|
||||
|
@ -256,7 +255,12 @@ internal class DefaultCryptoService @Inject constructor(
|
|||
}
|
||||
|
||||
override fun inboundGroupSessionsCount(onlyBackedUp: Boolean): Int {
|
||||
return cryptoStore.inboundGroupSessionsCount(onlyBackedUp)
|
||||
return if (onlyBackedUp) {
|
||||
keysBackupService.getTotalNumbersOfBackedUpKeys()
|
||||
} else {
|
||||
keysBackupService.getTotalNumbersOfKeys()
|
||||
}
|
||||
// return cryptoStore.inboundGroupSessionsCount(onlyBackedUp)
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -331,8 +335,10 @@ internal class DefaultCryptoService @Inject constructor(
|
|||
|
||||
// We try to enable key backups, if the backup version on the server is trusted,
|
||||
// we're gonna continue backing up.
|
||||
tryOrNull {
|
||||
keysBackupService.checkAndStartKeysBackup()
|
||||
cryptoCoroutineScope.launch {
|
||||
tryOrNull {
|
||||
keysBackupService.checkAndStartKeysBackup()
|
||||
}
|
||||
}
|
||||
|
||||
// Open the store
|
||||
|
@ -537,7 +543,11 @@ internal class DefaultCryptoService @Inject constructor(
|
|||
val t0 = System.currentTimeMillis()
|
||||
Timber.tag(loggerTag.value).v("encryptEventContent() starts")
|
||||
runCatching {
|
||||
preshareRoomKey(roomId, userIds)
|
||||
measureTimeMillis {
|
||||
preshareRoomKey(roomId, userIds)
|
||||
}.also {
|
||||
Timber.d("Shared room key in room $roomId took $it ms")
|
||||
}
|
||||
val content = encrypt(roomId, eventType, eventContent)
|
||||
Timber.tag(loggerTag.value).v("## CRYPTO | encryptEventContent() : succeeds after ${System.currentTimeMillis() - t0} ms")
|
||||
MXEncryptEventContentResult(content, EventType.ENCRYPTED)
|
||||
|
@ -668,17 +678,7 @@ internal class DefaultCryptoService @Inject constructor(
|
|||
roomId: String,
|
||||
sessionId: String,
|
||||
) {
|
||||
// The sender key is actually unused since it's unimportant for megolm
|
||||
// Our events don't contain the info so pass an empty string until we
|
||||
// change the listener definition
|
||||
val senderKey = ""
|
||||
|
||||
newSessionListeners.forEach {
|
||||
try {
|
||||
it.onNewSession(roomId, senderKey, sessionId)
|
||||
} catch (e: Throwable) {
|
||||
}
|
||||
}
|
||||
megolmSessionImportManager.dispatchNewSession(roomId, sessionId)
|
||||
}
|
||||
|
||||
suspend fun receiveSyncChanges(
|
||||
|
@ -879,7 +879,9 @@ internal class DefaultCryptoService @Inject constructor(
|
|||
override suspend fun importRoomKeys(roomKeysAsArray: ByteArray,
|
||||
password: String,
|
||||
progressListener: ProgressListener?): ImportRoomKeysResult {
|
||||
val result = olmMachine.importKeys(roomKeysAsArray, password, progressListener)
|
||||
val result = olmMachine.importKeys(roomKeysAsArray, password, progressListener).also {
|
||||
megolmSessionImportManager.dispatchKeyImportResults(it)
|
||||
}
|
||||
keysBackupService.maybeBackupKeys()
|
||||
|
||||
return result
|
||||
|
@ -1023,11 +1025,11 @@ internal class DefaultCryptoService @Inject constructor(
|
|||
}
|
||||
|
||||
override fun addNewSessionListener(newSessionListener: NewSessionListener) {
|
||||
if (!newSessionListeners.contains(newSessionListener)) newSessionListeners.add(newSessionListener)
|
||||
megolmSessionImportManager.addListener(newSessionListener)
|
||||
}
|
||||
|
||||
override fun removeSessionListener(listener: NewSessionListener) {
|
||||
newSessionListeners.remove(listener)
|
||||
megolmSessionImportManager.removeListener(listener)
|
||||
}
|
||||
/* ==========================================================================================
|
||||
* DEBUG INFO
|
||||
|
|
|
@ -44,6 +44,7 @@ import timber.log.Timber
|
|||
import java.util.concurrent.Executors
|
||||
import javax.inject.Inject
|
||||
|
||||
@Deprecated("rust")
|
||||
@SessionScope
|
||||
internal class IncomingGossipingRequestManager @Inject constructor(
|
||||
@SessionId private val sessionId: String,
|
||||
|
|
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
* Copyright 2021 The Matrix.org Foundation C.I.C.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.matrix.android.sdk.internal.crypto
|
||||
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.launch
|
||||
import org.matrix.android.sdk.api.MatrixCoroutineDispatchers
|
||||
import org.matrix.android.sdk.api.extensions.tryOrNull
|
||||
import org.matrix.android.sdk.internal.crypto.model.ImportRoomKeysResult
|
||||
import org.matrix.android.sdk.internal.session.SessionScope
|
||||
import javax.inject.Inject
|
||||
|
||||
/**
|
||||
* Helper that allows listeners to be notified when a new megolm session
|
||||
* has been added to the crypto layer (could be via room keys or forward keys via sync
|
||||
* or after importing keys from key backup or manual import).
|
||||
* Can be used to refresh display when the keys are received after the message
|
||||
*/
|
||||
@SessionScope
|
||||
internal class MegolmSessionImportManager @Inject constructor(
|
||||
private val coroutineDispatchers: MatrixCoroutineDispatchers,
|
||||
private val cryptoCoroutineScope: CoroutineScope
|
||||
) {
|
||||
|
||||
private val newSessionsListeners = mutableListOf<NewSessionListener>()
|
||||
|
||||
fun addListener(listener: NewSessionListener) {
|
||||
synchronized(newSessionsListeners) {
|
||||
if (!newSessionsListeners.contains(listener)) {
|
||||
newSessionsListeners.add(listener)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun removeListener(listener: NewSessionListener) {
|
||||
synchronized(newSessionsListeners) {
|
||||
newSessionsListeners.remove(listener)
|
||||
}
|
||||
}
|
||||
|
||||
fun dispatchNewSession(roomId: String?, sessionId: String) {
|
||||
val copy = synchronized(newSessionsListeners) {
|
||||
newSessionsListeners.toList()
|
||||
}
|
||||
cryptoCoroutineScope.launch(coroutineDispatchers.computation) {
|
||||
copy.forEach {
|
||||
tryOrNull("Failed to dispatch new session import") {
|
||||
it.onNewSession(roomId, sessionId)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun dispatchKeyImportResults(result: ImportRoomKeysResult) {
|
||||
result.importedSessionInfo.forEach { (roomId, senderToSessionIdMap) ->
|
||||
senderToSessionIdMap.values.forEach { sessionList ->
|
||||
sessionList.forEach { sessionId ->
|
||||
dispatchNewSession(roomId, sessionId)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -16,5 +16,5 @@
|
|||
package org.matrix.android.sdk.internal.crypto
|
||||
|
||||
interface NewSessionListener {
|
||||
fun onNewSession(roomId: String?, senderKey: String, sessionId: String)
|
||||
fun onNewSession(roomId: String?, sessionId: String)
|
||||
}
|
||||
|
|
|
@ -75,13 +75,9 @@ class CryptoLogger : Logger {
|
|||
}
|
||||
}
|
||||
|
||||
private class CryptoProgressListener(listener: ProgressListener?) : RustProgressListener {
|
||||
private val inner: ProgressListener? = listener
|
||||
|
||||
private class CryptoProgressListener(private val listener: ProgressListener?) : RustProgressListener {
|
||||
override fun onProgress(progress: Int, total: Int) {
|
||||
if (this.inner != null) {
|
||||
this.inner.onProgress(progress, total)
|
||||
}
|
||||
listener?.onProgress(progress, total)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -514,8 +510,7 @@ internal class OlmMachine(
|
|||
|
||||
val result = inner.importKeys(decodedKeys, passphrase, rustListener)
|
||||
|
||||
// TODO do we want to remove the cast here?
|
||||
ImportRoomKeysResult(result.total.toInt(), result.imported.toInt())
|
||||
ImportRoomKeysResult.fromOlm(result)
|
||||
}
|
||||
|
||||
@Throws(CryptoStoreException::class)
|
||||
|
@ -525,13 +520,30 @@ internal class OlmMachine(
|
|||
): ImportRoomKeysResult =
|
||||
withContext(Dispatchers.IO) {
|
||||
val adapter = MoshiProvider.providesMoshi().adapter(List::class.java)
|
||||
val encodedKeys = adapter.toJson(keys)
|
||||
|
||||
val rustListener = CryptoProgressListener(listener)
|
||||
// If the key backup is too big we take the risk of causing OOM
|
||||
// when serializing to json
|
||||
// so let's chunk to avoid it
|
||||
var totalImported = 0L
|
||||
var accTotal = 0L
|
||||
val details = mutableMapOf<String, Map<String, List<String>>>()
|
||||
keys.chunked(500)
|
||||
.forEach { keysSlice ->
|
||||
val encodedKeys = adapter.toJson(keysSlice)
|
||||
val rustListener = object : RustProgressListener {
|
||||
override fun onProgress(progress: Int, total: Int) {
|
||||
val accProgress = (accTotal + progress).toInt()
|
||||
listener?.onProgress(accProgress, keys.size)
|
||||
}
|
||||
}
|
||||
|
||||
val result = inner.importDecryptedKeys(encodedKeys, rustListener)
|
||||
|
||||
ImportRoomKeysResult(result.total.toInt(), result.imported.toInt())
|
||||
inner.importDecryptedKeys(encodedKeys, rustListener).let {
|
||||
totalImported += it.imported
|
||||
accTotal += it.total
|
||||
details.putAll(it.keys)
|
||||
}
|
||||
}
|
||||
ImportRoomKeysResult(totalImported.toInt(), accTotal.toInt(), details)
|
||||
}
|
||||
|
||||
@Throws(CryptoStoreException::class)
|
||||
|
@ -554,8 +566,14 @@ internal class OlmMachine(
|
|||
UserIdentity(identity.userId, masterKey, selfSigningKey, this, this.requestSender)
|
||||
}
|
||||
is RustUserIdentity.Own -> {
|
||||
val masterKey = adapter.fromJson(identity.masterKey)!!.toCryptoModel()
|
||||
val selfSigningKey = adapter.fromJson(identity.selfSigningKey)!!.toCryptoModel()
|
||||
val verified = this.inner().isIdentityVerified(userId)
|
||||
|
||||
val masterKey = adapter.fromJson(identity.masterKey)!!.toCryptoModel().apply {
|
||||
trustLevel = DeviceTrustLevel(verified, verified)
|
||||
}
|
||||
val selfSigningKey = adapter.fromJson(identity.selfSigningKey)!!.toCryptoModel().apply {
|
||||
trustLevel = DeviceTrustLevel(verified, verified)
|
||||
}
|
||||
val userSigningKey = adapter.fromJson(identity.userSigningKey)!!.toCryptoModel()
|
||||
|
||||
OwnUserIdentity(
|
||||
|
@ -823,13 +841,28 @@ internal class OlmMachine(
|
|||
suspend fun importCrossSigningKeys(export: PrivateKeysInfo): UserTrustResult {
|
||||
val rustExport = CrossSigningKeyExport(export.master, export.selfSigned, export.user)
|
||||
|
||||
var result: UserTrustResult
|
||||
withContext(Dispatchers.IO) {
|
||||
inner.importCrossSigningKeys(rustExport)
|
||||
}
|
||||
result = try {
|
||||
inner.importCrossSigningKeys(rustExport)
|
||||
|
||||
this.updateLivePrivateKeys()
|
||||
// TODO map the errors from importCrossSigningKeys to the UserTrustResult
|
||||
return UserTrustResult.Success
|
||||
// Sign the cross signing keys with our device
|
||||
// Fail silently if signature upload fails??
|
||||
try {
|
||||
getIdentity(userId())?.verify()
|
||||
} catch (failure: Throwable) {
|
||||
Timber.e(failure, "Failed to sign x-keys with own device")
|
||||
}
|
||||
UserTrustResult.Success
|
||||
} catch (failure: Exception) {
|
||||
// KeyImportError?
|
||||
UserTrustResult.Failure(failure.localizedMessage)
|
||||
}
|
||||
}
|
||||
withContext(Dispatchers.Main) {
|
||||
this@OlmMachine.updateLivePrivateKeys()
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
suspend fun sign(message: String): Map<String, Map<String, String>> {
|
||||
|
|
|
@ -213,13 +213,14 @@ internal class RequestSender @Inject constructor(
|
|||
suspend fun getKeyBackupVersion(version: String? = null): KeysVersionResult? {
|
||||
return try {
|
||||
if (version != null) {
|
||||
getKeysBackupVersionTask.execute(version)
|
||||
getKeysBackupVersionTask.executeRetry(version, 3)
|
||||
} else {
|
||||
getKeysBackupLastVersionTask.execute(Unit)
|
||||
getKeysBackupLastVersionTask.executeRetry(Unit, 3)
|
||||
}
|
||||
} catch (failure: Throwable) {
|
||||
if (failure is Failure.ServerError &&
|
||||
failure.error.code == MatrixError.M_NOT_FOUND) {
|
||||
// Workaround because the homeserver currently returns M_NOT_FOUND when there is no key backup
|
||||
null
|
||||
} else {
|
||||
throw failure
|
||||
|
|
|
@ -72,11 +72,11 @@ internal class RoomDecryptorProvider @Inject constructor(
|
|||
val alg = when (algorithm) {
|
||||
MXCRYPTO_ALGORITHM_MEGOLM -> megolmDecryptionFactory.create().apply {
|
||||
this.newSessionListener = object : NewSessionListener {
|
||||
override fun onNewSession(roomId: String?, senderKey: String, sessionId: String) {
|
||||
override fun onNewSession(roomId: String?, sessionId: String) {
|
||||
// PR reviewer: the parameter has been renamed so is now in conflict with the parameter of getOrCreateRoomDecryptor
|
||||
newSessionListeners.forEach {
|
||||
try {
|
||||
it.onNewSession(roomId, senderKey, sessionId)
|
||||
it.onNewSession(roomId, sessionId)
|
||||
} catch (e: Throwable) {
|
||||
}
|
||||
}
|
||||
|
|
|
@ -73,7 +73,7 @@ internal class RustCrossSigningService @Inject constructor(
|
|||
if (verified) {
|
||||
UserTrustResult.Success
|
||||
} else {
|
||||
UserTrustResult.UnknownCrossSignatureInfo(otherUserId)
|
||||
UserTrustResult.Failure("failed to verify $otherUserId")
|
||||
}
|
||||
} else {
|
||||
UserTrustResult.CrossSigningNotConfigured(otherUserId)
|
||||
|
@ -94,15 +94,13 @@ internal class RustCrossSigningService @Inject constructor(
|
|||
* This will check if the injected private cross signing keys match the public ones provided
|
||||
* by the server and if they do so
|
||||
*/
|
||||
override fun checkTrustFromPrivateKeys(
|
||||
override suspend fun checkTrustFromPrivateKeys(
|
||||
masterKeyPrivateKey: String?,
|
||||
uskKeyPrivateKey: String?,
|
||||
sskPrivateKey: String?
|
||||
): UserTrustResult {
|
||||
val export = PrivateKeysInfo(masterKeyPrivateKey, sskPrivateKey, uskKeyPrivateKey)
|
||||
return runBlocking {
|
||||
olmMachineProvider.olmMachine.importCrossSigningKeys(export)
|
||||
}
|
||||
return olmMachine.importCrossSigningKeys(export)
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -171,19 +169,19 @@ internal class RustCrossSigningService @Inject constructor(
|
|||
/**
|
||||
* Sign one of your devices and upload the signature
|
||||
*/
|
||||
override fun trustDevice(deviceId: String, callback: MatrixCallback<Unit>) {
|
||||
val device = runBlocking { olmMachine.getDevice(olmMachine.userId(), deviceId) }
|
||||
override suspend fun trustDevice(deviceId: String) {
|
||||
val device = olmMachine.getDevice(olmMachine.userId(), deviceId)
|
||||
|
||||
return if (device != null) {
|
||||
val verified = runBlocking { device.verify() }
|
||||
val verified = device.verify()
|
||||
|
||||
if (verified) {
|
||||
callback.onSuccess(Unit)
|
||||
return
|
||||
} else {
|
||||
callback.onFailure(IllegalArgumentException("This device [$deviceId] is not known, or not yours"))
|
||||
throw IllegalArgumentException("This device [$deviceId] is not known, or not yours")
|
||||
}
|
||||
} else {
|
||||
callback.onFailure(IllegalArgumentException("This device [$deviceId] is not known"))
|
||||
throw IllegalArgumentException("This device [$deviceId] is not known")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -103,6 +103,6 @@ internal class MegolmSessionDataImporter @Inject constructor(private val olmDevi
|
|||
|
||||
Timber.v("## importMegolmSessionsData : sessions import " + (t1 - t0) + " ms (" + megolmSessionsData.size + " sessions)")
|
||||
|
||||
return ImportRoomKeysResult(totalNumbersOfKeys, totalNumbersOfImportedKeys)
|
||||
return ImportRoomKeysResult(totalNumbersOfKeys, totalNumbersOfImportedKeys, emptyMap())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,7 +21,6 @@ import org.matrix.android.sdk.api.session.events.model.Event
|
|||
import org.matrix.android.sdk.internal.crypto.IncomingRoomKeyRequest
|
||||
import org.matrix.android.sdk.internal.crypto.IncomingSecretShareRequest
|
||||
import org.matrix.android.sdk.internal.crypto.MXEventDecryptionResult
|
||||
import org.matrix.android.sdk.internal.crypto.keysbackup.DefaultKeysBackupService
|
||||
|
||||
/**
|
||||
* An interface for decrypting data
|
||||
|
@ -44,7 +43,7 @@ internal interface IMXDecrypting {
|
|||
*
|
||||
* @param event the key event.
|
||||
*/
|
||||
fun onRoomKeyEvent(event: Event, defaultKeysBackupService: DefaultKeysBackupService) {}
|
||||
fun onRoomKeyEvent(event: Event/*, defaultKeysBackupService: DefaultKeysBackupService*/) {}
|
||||
|
||||
/**
|
||||
* Check if the some messages can be decrypted with a new session
|
||||
|
|
|
@ -34,7 +34,6 @@ import org.matrix.android.sdk.internal.crypto.actions.EnsureOlmSessionsForDevice
|
|||
import org.matrix.android.sdk.internal.crypto.actions.MessageEncrypter
|
||||
import org.matrix.android.sdk.internal.crypto.algorithms.IMXDecrypting
|
||||
import org.matrix.android.sdk.internal.crypto.algorithms.IMXWithHeldExtension
|
||||
import org.matrix.android.sdk.internal.crypto.keysbackup.DefaultKeysBackupService
|
||||
import org.matrix.android.sdk.internal.crypto.model.MXUsersDevicesMap
|
||||
import org.matrix.android.sdk.internal.crypto.model.event.EncryptedEventContent
|
||||
import org.matrix.android.sdk.internal.crypto.model.event.RoomKeyContent
|
||||
|
@ -232,7 +231,7 @@ internal class MXMegolmDecryption(private val userId: String,
|
|||
*
|
||||
* @param event the key event.
|
||||
*/
|
||||
override fun onRoomKeyEvent(event: Event, defaultKeysBackupService: DefaultKeysBackupService) {
|
||||
override fun onRoomKeyEvent(event: Event/*, defaultKeysBackupService: DefaultKeysBackupService*/) {
|
||||
Timber.tag(loggerTag.value).v("onRoomKeyEvent()")
|
||||
var exportFormat = false
|
||||
val roomKeyContent = event.getClearContent().toModel<RoomKeyContent>() ?: return
|
||||
|
@ -295,7 +294,7 @@ internal class MXMegolmDecryption(private val userId: String,
|
|||
exportFormat)
|
||||
|
||||
if (added) {
|
||||
defaultKeysBackupService.maybeBackupKeys()
|
||||
// defaultKeysBackupService.maybeBackupKeys()
|
||||
|
||||
val content = RoomKeyRequestBody(
|
||||
algorithm = roomKeyContent.algorithm,
|
||||
|
@ -318,7 +317,7 @@ internal class MXMegolmDecryption(private val userId: String,
|
|||
*/
|
||||
override fun onNewSession(senderKey: String, sessionId: String) {
|
||||
Timber.tag(loggerTag.value).v("ON NEW SESSION $sessionId - $senderKey")
|
||||
newSessionListener?.onNewSession(null, senderKey, sessionId)
|
||||
newSessionListener?.onNewSession(null, sessionId)
|
||||
}
|
||||
|
||||
override fun hasKeysForKeyRequest(request: IncomingRoomKeyRequest): Boolean {
|
||||
|
|
|
@ -31,7 +31,7 @@ import org.matrix.android.sdk.internal.crypto.actions.EnsureOlmSessionsForDevice
|
|||
import org.matrix.android.sdk.internal.crypto.actions.MessageEncrypter
|
||||
import org.matrix.android.sdk.internal.crypto.algorithms.IMXEncrypting
|
||||
import org.matrix.android.sdk.internal.crypto.algorithms.IMXGroupEncryption
|
||||
import org.matrix.android.sdk.internal.crypto.keysbackup.DefaultKeysBackupService
|
||||
// import org.matrix.android.sdk.internal.crypto.keysbackup.DefaultKeysBackupService
|
||||
import org.matrix.android.sdk.internal.crypto.model.CryptoDeviceInfo
|
||||
import org.matrix.android.sdk.internal.crypto.model.MXUsersDevicesMap
|
||||
import org.matrix.android.sdk.internal.crypto.model.event.RoomKeyWithHeldContent
|
||||
|
@ -53,7 +53,7 @@ internal class MXMegolmEncryption(
|
|||
// The id of the room we will be sending to.
|
||||
private val roomId: String,
|
||||
private val olmDevice: MXOlmDevice,
|
||||
private val defaultKeysBackupService: DefaultKeysBackupService,
|
||||
// private val defaultKeysBackupService: DefaultKeysBackupService,
|
||||
private val cryptoStore: IMXCryptoStore,
|
||||
private val deviceListManager: DeviceListManager,
|
||||
private val ensureOlmSessionsForDevicesAction: EnsureOlmSessionsForDevicesAction,
|
||||
|
@ -149,7 +149,7 @@ internal class MXMegolmEncryption(
|
|||
olmDevice.addInboundGroupSession(sessionId!!, olmDevice.getSessionKey(sessionId)!!, roomId, olmDevice.deviceCurve25519Key!!,
|
||||
emptyList(), keysClaimedMap, false)
|
||||
|
||||
defaultKeysBackupService.maybeBackupKeys()
|
||||
// defaultKeysBackupService.maybeBackupKeys()
|
||||
|
||||
return MXOutboundSessionInfo(sessionId, SharedWithHelper(roomId, sessionId, cryptoStore))
|
||||
}
|
||||
|
|
|
@ -22,7 +22,6 @@ import org.matrix.android.sdk.internal.crypto.DeviceListManager
|
|||
import org.matrix.android.sdk.internal.crypto.MXOlmDevice
|
||||
import org.matrix.android.sdk.internal.crypto.actions.EnsureOlmSessionsForDevicesAction
|
||||
import org.matrix.android.sdk.internal.crypto.actions.MessageEncrypter
|
||||
import org.matrix.android.sdk.internal.crypto.keysbackup.DefaultKeysBackupService
|
||||
import org.matrix.android.sdk.internal.crypto.repository.WarnOnUnknownDeviceRepository
|
||||
import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore
|
||||
import org.matrix.android.sdk.internal.crypto.tasks.SendToDeviceTask
|
||||
|
@ -32,7 +31,7 @@ import javax.inject.Inject
|
|||
|
||||
internal class MXMegolmEncryptionFactory @Inject constructor(
|
||||
private val olmDevice: MXOlmDevice,
|
||||
private val defaultKeysBackupService: DefaultKeysBackupService,
|
||||
// private val defaultKeysBackupService: DefaultKeysBackupService,
|
||||
private val cryptoStore: IMXCryptoStore,
|
||||
private val deviceListManager: DeviceListManager,
|
||||
private val ensureOlmSessionsForDevicesAction: EnsureOlmSessionsForDevicesAction,
|
||||
|
@ -48,7 +47,7 @@ internal class MXMegolmEncryptionFactory @Inject constructor(
|
|||
return MXMegolmEncryption(
|
||||
roomId = roomId,
|
||||
olmDevice = olmDevice,
|
||||
defaultKeysBackupService = defaultKeysBackupService,
|
||||
// defaultKeysBackupService = defaultKeysBackupService,
|
||||
cryptoStore = cryptoStore,
|
||||
deviceListManager = deviceListManager,
|
||||
ensureOlmSessionsForDevicesAction = ensureOlmSessionsForDevicesAction,
|
||||
|
|
|
@ -16,9 +16,6 @@
|
|||
|
||||
package org.matrix.android.sdk.internal.crypto.crosssigning
|
||||
|
||||
import org.matrix.android.sdk.api.session.crypto.crosssigning.MXCrossSigningInfo
|
||||
import org.matrix.android.sdk.internal.crypto.model.CryptoCrossSigningKey
|
||||
|
||||
sealed class UserTrustResult {
|
||||
object Success : UserTrustResult()
|
||||
|
||||
|
@ -26,10 +23,11 @@ sealed class UserTrustResult {
|
|||
// data class UnknownDevice(val deviceID: String) : UserTrustResult()
|
||||
data class CrossSigningNotConfigured(val userID: String) : UserTrustResult()
|
||||
|
||||
data class UnknownCrossSignatureInfo(val userID: String) : UserTrustResult()
|
||||
data class KeysNotTrusted(val key: MXCrossSigningInfo) : UserTrustResult()
|
||||
data class KeyNotSigned(val key: CryptoCrossSigningKey) : UserTrustResult()
|
||||
data class InvalidSignature(val key: CryptoCrossSigningKey, val signature: String) : UserTrustResult()
|
||||
data class Failure(val message: String) : UserTrustResult()
|
||||
// data class UnknownCrossSignatureInfo(val userID: String) : UserTrustResult()
|
||||
// data class KeysNotTrusted(val key: MXCrossSigningInfo) : UserTrustResult()
|
||||
// data class KeyNotSigned(val key: CryptoCrossSigningKey) : UserTrustResult()
|
||||
// data class InvalidSignature(val key: CryptoCrossSigningKey, val signature: String) : UserTrustResult()
|
||||
}
|
||||
|
||||
fun UserTrustResult.isVerified() = this is UserTrustResult.Success
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -17,6 +17,7 @@
|
|||
package org.matrix.android.sdk.internal.crypto.keysbackup
|
||||
|
||||
import android.os.Handler
|
||||
import org.matrix.android.sdk.api.extensions.tryOrNull
|
||||
import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupState
|
||||
import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupStateListener
|
||||
import timber.log.Timber
|
||||
|
@ -33,11 +34,13 @@ internal class KeysBackupStateManager(private val uiHandler: Handler) {
|
|||
field = newState
|
||||
|
||||
// Notify listeners about the state change, on the ui thread
|
||||
uiHandler.post {
|
||||
synchronized(listeners) {
|
||||
listeners.forEach {
|
||||
synchronized(listeners) {
|
||||
listeners.forEach {
|
||||
uiHandler.post {
|
||||
// Use newState because state may have already changed again
|
||||
it.onStateChange(newState)
|
||||
tryOrNull {
|
||||
it.onStateChange(newState)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -16,5 +16,21 @@
|
|||
|
||||
package org.matrix.android.sdk.internal.crypto.model
|
||||
|
||||
import uniffi.olm.KeysImportResult
|
||||
|
||||
data class ImportRoomKeysResult(val totalNumberOfKeys: Int,
|
||||
val successfullyNumberOfImportedKeys: Int)
|
||||
val successfullyNumberOfImportedKeys: Int,
|
||||
/**It's a map from room id to a map of the sender key to a list of session*/
|
||||
val importedSessionInfo: Map<String, Map<String, List<String>>>
|
||||
) {
|
||||
|
||||
companion object {
|
||||
fun fromOlm(result: KeysImportResult): ImportRoomKeysResult {
|
||||
return ImportRoomKeysResult(
|
||||
result.total.toInt(),
|
||||
result.imported.toInt(),
|
||||
result.keys
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -60,6 +60,7 @@ internal class DefaultSendEventTask @Inject constructor(
|
|||
eventType = event.type ?: ""
|
||||
)
|
||||
}
|
||||
Timber.d("Event sent to ${event.roomId} with event id ${response.eventId}")
|
||||
localEchoRepository.updateSendState(localId, params.event.roomId, SendState.SENT)
|
||||
return response.eventId.also {
|
||||
Timber.d("Event: $it just sent in ${params.event.roomId}")
|
||||
|
|
|
@ -40,7 +40,7 @@ internal class TimelineEventDecryptor @Inject constructor(
|
|||
) {
|
||||
|
||||
private val newSessionListener = object : NewSessionListener {
|
||||
override fun onNewSession(roomId: String?, senderKey: String, sessionId: String) {
|
||||
override fun onNewSession(roomId: String?, sessionId: String) {
|
||||
synchronized(unknownSessionsFailure) {
|
||||
unknownSessionsFailure[sessionId]
|
||||
?.toList()
|
||||
|
|
|
@ -83,11 +83,6 @@ class KeysBackupRestoreActivity : SimpleFragmentActivity() {
|
|||
.show()
|
||||
}
|
||||
|
||||
if (viewModel.keyVersionResult.value == null) {
|
||||
// We need to fetch from API
|
||||
viewModel.getLatestVersion()
|
||||
}
|
||||
|
||||
viewModel.navigateEvent.observeEvent(this) { uxStateEvent ->
|
||||
when (uxStateEvent) {
|
||||
KeysBackupRestoreSharedViewModel.NAVIGATE_TO_RECOVER_WITH_KEY -> {
|
||||
|
|
|
@ -23,9 +23,11 @@ import im.vector.app.R
|
|||
import im.vector.app.core.platform.WaitingViewData
|
||||
import im.vector.app.core.resources.StringProvider
|
||||
import im.vector.app.core.utils.LiveEvent
|
||||
import im.vector.app.features.session.coroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import org.matrix.android.sdk.api.MatrixCallback
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.matrix.android.sdk.api.extensions.tryOrNull
|
||||
import org.matrix.android.sdk.api.listeners.StepProgressListener
|
||||
import org.matrix.android.sdk.api.session.Session
|
||||
import org.matrix.android.sdk.api.session.crypto.crosssigning.KEYBACKUP_SECRET_SSSS_NAME
|
||||
|
@ -35,7 +37,6 @@ import org.matrix.android.sdk.internal.crypto.crosssigning.fromBase64
|
|||
import org.matrix.android.sdk.internal.crypto.keysbackup.model.rest.KeysVersionResult
|
||||
import org.matrix.android.sdk.internal.crypto.keysbackup.util.computeRecoveryKey
|
||||
import org.matrix.android.sdk.internal.crypto.model.ImportRoomKeysResult
|
||||
import org.matrix.android.sdk.internal.util.awaitCallback
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
|
@ -75,10 +76,15 @@ class KeysBackupRestoreSharedViewModel @Inject constructor(
|
|||
var importRoomKeysFinishWithResult: MutableLiveData<LiveEvent<ImportRoomKeysResult>> = MutableLiveData()
|
||||
|
||||
fun initSession(session: Session) {
|
||||
this.session = session
|
||||
if (!this::session.isInitialized) {
|
||||
this.session = session
|
||||
viewModelScope.launch {
|
||||
getLatestVersion()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val progressObserver = object : StepProgressListener {
|
||||
private val progressObserver = object : StepProgressListener {
|
||||
override fun onStepProgress(step: StepProgressListener.Step) {
|
||||
when (step) {
|
||||
is StepProgressListener.Step.ComputingKey -> {
|
||||
|
@ -106,62 +112,71 @@ class KeysBackupRestoreSharedViewModel @Inject constructor(
|
|||
step.total))
|
||||
}
|
||||
}
|
||||
is StepProgressListener.Step.DecryptingKey -> {
|
||||
if (step.progress == 0) {
|
||||
loadingEvent.postValue(WaitingViewData(stringProvider.getString(R.string.keys_backup_restoring_waiting_message) +
|
||||
"\n" + stringProvider.getString(R.string.keys_backup_restoring_decrypting_keys_waiting_message),
|
||||
isIndeterminate = true))
|
||||
} else {
|
||||
loadingEvent.postValue(WaitingViewData(stringProvider.getString(R.string.keys_backup_restoring_waiting_message) +
|
||||
"\n" + stringProvider.getString(R.string.keys_backup_restoring_decrypting_keys_waiting_message),
|
||||
step.progress,
|
||||
step.total))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun getLatestVersion() {
|
||||
private suspend fun getLatestVersion() {
|
||||
val keysBackup = session.cryptoService().keysBackupService()
|
||||
|
||||
loadingEvent.value = WaitingViewData(stringProvider.getString(R.string.keys_backup_restore_is_getting_backup_version))
|
||||
loadingEvent.postValue(WaitingViewData(stringProvider.getString(R.string.keys_backup_restore_is_getting_backup_version)))
|
||||
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
try {
|
||||
val version = awaitCallback<KeysVersionResult?> {
|
||||
keysBackup.getCurrentVersion(it)
|
||||
}
|
||||
if (version?.version == null) {
|
||||
loadingEvent.postValue(null)
|
||||
_keyVersionResultError.postValue(LiveEvent(stringProvider.getString(R.string.keys_backup_get_version_error, "")))
|
||||
return@launch
|
||||
}
|
||||
try {
|
||||
val version = keysBackup.getCurrentVersion()
|
||||
if (version?.version == null) {
|
||||
loadingEvent.postValue(null)
|
||||
_keyVersionResultError.postValue(LiveEvent(stringProvider.getString(R.string.keys_backup_get_version_error, "")))
|
||||
return
|
||||
}
|
||||
|
||||
keyVersionResult.postValue(version)
|
||||
// Let's check if there is quads
|
||||
val isBackupKeyInQuadS = isBackupKeyInQuadS()
|
||||
keyVersionResult.postValue(version)
|
||||
// Let's check if there is quads
|
||||
val isBackupKeyInQuadS = isBackupKeyInQuadS()
|
||||
|
||||
val savedSecret = session.cryptoService().keysBackupService().getKeyBackupRecoveryKeyInfo()
|
||||
if (savedSecret != null && savedSecret.version == version.version) {
|
||||
// key is in memory!
|
||||
keySourceModel.postValue(
|
||||
KeySource(isInMemory = true, isInQuadS = true)
|
||||
)
|
||||
// Go and use it!!
|
||||
try {
|
||||
recoverUsingBackupRecoveryKey(savedSecret.recoveryKey)
|
||||
} catch (failure: Throwable) {
|
||||
keySourceModel.postValue(
|
||||
KeySource(isInMemory = false, isInQuadS = true)
|
||||
)
|
||||
}
|
||||
} else if (isBackupKeyInQuadS) {
|
||||
// key is in QuadS!
|
||||
val savedSecret = session.cryptoService().keysBackupService().getKeyBackupRecoveryKeyInfo()
|
||||
if (savedSecret != null && savedSecret.version == version.version) {
|
||||
// key is in memory!
|
||||
keySourceModel.postValue(
|
||||
KeySource(isInMemory = true, isInQuadS = true)
|
||||
)
|
||||
// Go and use it!!
|
||||
try {
|
||||
recoverUsingBackupRecoveryKey(computeRecoveryKey(savedSecret.recoveryKey.fromBase64()), version)
|
||||
} catch (failure: Throwable) {
|
||||
Timber.e(failure, "## recoverUsingBackupRecoveryKey FAILED")
|
||||
keySourceModel.postValue(
|
||||
KeySource(isInMemory = false, isInQuadS = true)
|
||||
)
|
||||
_navigateEvent.postValue(LiveEvent(NAVIGATE_TO_4S))
|
||||
} else {
|
||||
// we need to restore directly
|
||||
keySourceModel.postValue(
|
||||
KeySource(isInMemory = false, isInQuadS = false)
|
||||
)
|
||||
}
|
||||
|
||||
loadingEvent.postValue(null)
|
||||
} catch (failure: Throwable) {
|
||||
loadingEvent.postValue(null)
|
||||
_keyVersionResultError.postValue(LiveEvent(stringProvider.getString(R.string.keys_backup_get_version_error, failure.localizedMessage)))
|
||||
} else if (isBackupKeyInQuadS) {
|
||||
// key is in QuadS!
|
||||
keySourceModel.postValue(
|
||||
KeySource(isInMemory = false, isInQuadS = true)
|
||||
)
|
||||
_navigateEvent.postValue(LiveEvent(NAVIGATE_TO_4S))
|
||||
} else {
|
||||
// we need to restore directly
|
||||
keySourceModel.postValue(
|
||||
KeySource(isInMemory = false, isInQuadS = false)
|
||||
)
|
||||
}
|
||||
|
||||
loadingEvent.postValue(null)
|
||||
} catch (failure: Throwable) {
|
||||
loadingEvent.postValue(null)
|
||||
_keyVersionResultError.postValue(LiveEvent(stringProvider.getString(R.string.keys_backup_get_version_error, failure.localizedMessage)))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -176,7 +191,7 @@ class KeysBackupRestoreSharedViewModel @Inject constructor(
|
|||
)
|
||||
return
|
||||
}
|
||||
loadingEvent.value = WaitingViewData(stringProvider.getString(R.string.keys_backup_restore_is_getting_backup_version))
|
||||
loadingEvent.postValue(WaitingViewData(stringProvider.getString(R.string.keys_backup_restore_is_getting_backup_version)))
|
||||
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
try {
|
||||
|
@ -202,15 +217,12 @@ class KeysBackupRestoreSharedViewModel @Inject constructor(
|
|||
loadingEvent.postValue(WaitingViewData(stringProvider.getString(R.string.loading)))
|
||||
|
||||
try {
|
||||
val result = awaitCallback<ImportRoomKeysResult> {
|
||||
keysBackup.restoreKeyBackupWithPassword(keyVersion,
|
||||
passphrase,
|
||||
null,
|
||||
session.myUserId,
|
||||
progressObserver,
|
||||
it
|
||||
)
|
||||
}
|
||||
val result = keysBackup.restoreKeyBackupWithPassword(keyVersion,
|
||||
passphrase,
|
||||
null,
|
||||
session.myUserId,
|
||||
progressObserver
|
||||
)
|
||||
loadingEvent.postValue(null)
|
||||
didRecoverSucceed(result)
|
||||
trustOnDecrypt(keysBackup, keyVersion)
|
||||
|
@ -220,26 +232,27 @@ class KeysBackupRestoreSharedViewModel @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
suspend fun recoverUsingBackupRecoveryKey(recoveryKey: String) {
|
||||
suspend fun recoverUsingBackupRecoveryKey(recoveryKey: String, keyVersion: KeysVersionResult? = null) {
|
||||
val keysBackup = session.cryptoService().keysBackupService()
|
||||
val keyVersion = keyVersionResult.value ?: return
|
||||
// This is badddddd
|
||||
val version = keyVersion ?: keyVersionResult.value ?: return
|
||||
|
||||
loadingEvent.postValue(WaitingViewData(stringProvider.getString(R.string.loading)))
|
||||
|
||||
try {
|
||||
val result = awaitCallback<ImportRoomKeysResult> {
|
||||
keysBackup.restoreKeysWithRecoveryKey(keyVersion,
|
||||
recoveryKey,
|
||||
null,
|
||||
session.myUserId,
|
||||
progressObserver,
|
||||
it
|
||||
)
|
||||
}
|
||||
val result = keysBackup.restoreKeysWithRecoveryKey(version,
|
||||
recoveryKey,
|
||||
null,
|
||||
session.myUserId,
|
||||
progressObserver
|
||||
)
|
||||
loadingEvent.postValue(null)
|
||||
didRecoverSucceed(result)
|
||||
trustOnDecrypt(keysBackup, keyVersion)
|
||||
withContext(Dispatchers.Main) {
|
||||
didRecoverSucceed(result)
|
||||
trustOnDecrypt(keysBackup, version)
|
||||
}
|
||||
} catch (failure: Throwable) {
|
||||
Timber.e(failure, "## restoreKeysWithRecoveryKey failure")
|
||||
loadingEvent.postValue(null)
|
||||
throw failure
|
||||
}
|
||||
|
@ -258,19 +271,19 @@ class KeysBackupRestoreSharedViewModel @Inject constructor(
|
|||
}
|
||||
|
||||
private fun trustOnDecrypt(keysBackup: KeysBackupService, keysVersionResult: KeysVersionResult) {
|
||||
keysBackup.trustKeysBackupVersion(keysVersionResult, true,
|
||||
object : MatrixCallback<Unit> {
|
||||
override fun onSuccess(data: Unit) {
|
||||
Timber.v("##### trustKeysBackupVersion onSuccess")
|
||||
}
|
||||
})
|
||||
// do that on session scope because could happen outside of view model lifecycle
|
||||
session.coroutineScope.launch {
|
||||
tryOrNull("## Failed to trustKeysBackupVersion") {
|
||||
keysBackup.trustKeysBackupVersion(keysVersionResult, true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun moveToRecoverWithKey() {
|
||||
_navigateEvent.value = LiveEvent(NAVIGATE_TO_RECOVER_WITH_KEY)
|
||||
_navigateEvent.postValue(LiveEvent(NAVIGATE_TO_RECOVER_WITH_KEY))
|
||||
}
|
||||
|
||||
fun didRecoverSucceed(result: ImportRoomKeysResult) {
|
||||
private fun didRecoverSucceed(result: ImportRoomKeysResult) {
|
||||
importKeyResult = result
|
||||
_navigateEvent.postValue(LiveEvent(NAVIGATE_TO_SUCCESS))
|
||||
}
|
||||
|
|
|
@ -27,13 +27,11 @@ import im.vector.app.core.di.MavericksAssistedViewModelFactory
|
|||
import im.vector.app.core.di.hiltMavericksViewModelFactory
|
||||
import im.vector.app.core.platform.EmptyViewEvents
|
||||
import im.vector.app.core.platform.VectorViewModel
|
||||
import org.matrix.android.sdk.api.MatrixCallback
|
||||
import org.matrix.android.sdk.api.NoOpMatrixCallback
|
||||
import kotlinx.coroutines.launch
|
||||
import org.matrix.android.sdk.api.session.Session
|
||||
import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupService
|
||||
import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupState
|
||||
import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupStateListener
|
||||
import org.matrix.android.sdk.internal.crypto.keysbackup.model.KeysBackupVersionTrust
|
||||
import timber.log.Timber
|
||||
|
||||
class KeysBackupSettingsViewModel @AssistedInject constructor(@Assisted initialState: KeysBackupSettingViewState,
|
||||
|
@ -70,7 +68,9 @@ class KeysBackupSettingsViewModel @AssistedInject constructor(@Assisted initialS
|
|||
}
|
||||
|
||||
private fun init() {
|
||||
keysBackupService.forceUsingLastVersion(NoOpMatrixCallback())
|
||||
viewModelScope.launch {
|
||||
keysBackupService.forceUsingLastVersion()
|
||||
}
|
||||
}
|
||||
|
||||
private fun getKeysBackupTrust() = withState { state ->
|
||||
|
@ -86,26 +86,24 @@ class KeysBackupSettingsViewModel @AssistedInject constructor(@Assisted initialS
|
|||
}
|
||||
Timber.d("BACKUP: HEEEEEEE TWO")
|
||||
|
||||
keysBackupService
|
||||
.getKeysBackupTrust(versionResult, object : MatrixCallback<KeysBackupVersionTrust> {
|
||||
override fun onSuccess(data: KeysBackupVersionTrust) {
|
||||
Timber.d("BACKUP: HEEEE suceeeded $data")
|
||||
setState {
|
||||
copy(
|
||||
keysBackupVersionTrust = Success(data)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onFailure(failure: Throwable) {
|
||||
Timber.d("BACKUP: HEEEE FAILED $failure")
|
||||
setState {
|
||||
copy(
|
||||
keysBackupVersionTrust = Fail(failure)
|
||||
)
|
||||
}
|
||||
}
|
||||
})
|
||||
viewModelScope.launch {
|
||||
try {
|
||||
val data = keysBackupService.getKeysBackupTrust(versionResult)
|
||||
Timber.d("BACKUP: HEEEE suceeeded $data")
|
||||
setState {
|
||||
copy(
|
||||
keysBackupVersionTrust = Success(data)
|
||||
)
|
||||
}
|
||||
} catch (failure: Throwable) {
|
||||
Timber.d("BACKUP: HEEEE FAILED $failure")
|
||||
setState {
|
||||
copy(
|
||||
keysBackupVersionTrust = Fail(failure)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -128,15 +126,16 @@ class KeysBackupSettingsViewModel @AssistedInject constructor(@Assisted initialS
|
|||
private fun deleteCurrentBackup() {
|
||||
val keysBackupService = keysBackupService
|
||||
|
||||
if (keysBackupService.currentBackupVersion != null) {
|
||||
val currentBackupVersion = keysBackupService.currentBackupVersion
|
||||
if (currentBackupVersion != null) {
|
||||
setState {
|
||||
copy(
|
||||
deleteBackupRequest = Loading()
|
||||
)
|
||||
}
|
||||
|
||||
keysBackupService.deleteBackup(keysBackupService.currentBackupVersion!!, object : MatrixCallback<Unit> {
|
||||
override fun onSuccess(data: Unit) {
|
||||
viewModelScope.launch {
|
||||
try {
|
||||
keysBackupService.deleteBackup(currentBackupVersion)
|
||||
setState {
|
||||
copy(
|
||||
keysBackupVersion = null,
|
||||
|
@ -145,16 +144,14 @@ class KeysBackupSettingsViewModel @AssistedInject constructor(@Assisted initialS
|
|||
deleteBackupRequest = Uninitialized
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onFailure(failure: Throwable) {
|
||||
} catch (failure: Throwable) {
|
||||
setState {
|
||||
copy(
|
||||
deleteBackupRequest = Fail(failure)
|
||||
)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -19,17 +19,16 @@ package im.vector.app.features.crypto.keysbackup.setup
|
|||
import android.content.Context
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.nulabinc.zxcvbn.Strength
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.platform.WaitingViewData
|
||||
import im.vector.app.core.utils.LiveEvent
|
||||
import org.matrix.android.sdk.api.MatrixCallback
|
||||
import org.matrix.android.sdk.api.listeners.ProgressListener
|
||||
import kotlinx.coroutines.launch
|
||||
import org.matrix.android.sdk.api.session.Session
|
||||
import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupService
|
||||
import org.matrix.android.sdk.internal.crypto.keysbackup.model.MegolmBackupCreationInfo
|
||||
import org.matrix.android.sdk.internal.crypto.keysbackup.model.rest.KeysVersion
|
||||
import org.matrix.android.sdk.internal.crypto.keysbackup.model.rest.KeysVersionResult
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
|
@ -89,48 +88,30 @@ class KeysBackupSetupSharedViewModel @Inject constructor() : ViewModel() {
|
|||
|
||||
recoveryKey.value = null
|
||||
prepareRecoverFailError.value = null
|
||||
session.let { mxSession ->
|
||||
val requestedId = currentRequestId.value!!
|
||||
val requestedId = currentRequestId.value!!
|
||||
viewModelScope.launch {
|
||||
try {
|
||||
val data = session.cryptoService().keysBackupService().prepareKeysBackupVersion(withPassphrase)
|
||||
if (requestedId != currentRequestId.value) {
|
||||
// this is an old request, we can't cancel but we can ignore
|
||||
return@launch
|
||||
}
|
||||
recoveryKey.postValue(data.recoveryKey)
|
||||
megolmBackupCreationInfo = data
|
||||
copyHasBeenMade = false
|
||||
|
||||
mxSession.cryptoService().keysBackupService().prepareKeysBackupVersion(withPassphrase,
|
||||
object : ProgressListener {
|
||||
override fun onProgress(progress: Int, total: Int) {
|
||||
if (requestedId != currentRequestId.value) {
|
||||
// this is an old request, we can't cancel but we can ignore
|
||||
return
|
||||
}
|
||||
val keyBackup = session.cryptoService().keysBackupService()
|
||||
createKeysBackup(context, keyBackup)
|
||||
} catch (failure: Throwable) {
|
||||
if (requestedId != currentRequestId.value) {
|
||||
// this is an old request, we can't cancel but we can ignore
|
||||
return@launch
|
||||
}
|
||||
|
||||
loadingStatus.value = WaitingViewData(context.getString(R.string.keys_backup_setup_step3_generating_key_status),
|
||||
progress,
|
||||
total)
|
||||
}
|
||||
},
|
||||
object : MatrixCallback<MegolmBackupCreationInfo> {
|
||||
override fun onSuccess(data: MegolmBackupCreationInfo) {
|
||||
if (requestedId != currentRequestId.value) {
|
||||
// this is an old request, we can't cancel but we can ignore
|
||||
return
|
||||
}
|
||||
recoveryKey.value = data.recoveryKey
|
||||
megolmBackupCreationInfo = data
|
||||
copyHasBeenMade = false
|
||||
|
||||
val keyBackup = session.cryptoService().keysBackupService()
|
||||
createKeysBackup(context, keyBackup)
|
||||
}
|
||||
|
||||
override fun onFailure(failure: Throwable) {
|
||||
if (requestedId != currentRequestId.value) {
|
||||
// this is an old request, we can't cancel but we can ignore
|
||||
return
|
||||
}
|
||||
|
||||
loadingStatus.value = null
|
||||
|
||||
isCreatingBackupVersion.value = false
|
||||
prepareRecoverFailError.value = failure
|
||||
}
|
||||
})
|
||||
loadingStatus.postValue(null)
|
||||
isCreatingBackupVersion.postValue(false)
|
||||
prepareRecoverFailError.postValue(failure)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -140,9 +121,11 @@ class KeysBackupSetupSharedViewModel @Inject constructor() : ViewModel() {
|
|||
}
|
||||
|
||||
fun stopAndKeepAfterDetectingExistingOnServer() {
|
||||
loadingStatus.value = null
|
||||
navigateEvent.value = LiveEvent(NAVIGATE_FINISH)
|
||||
session.cryptoService().keysBackupService().checkAndStartKeysBackup()
|
||||
loadingStatus.postValue(null)
|
||||
navigateEvent.postValue(LiveEvent(NAVIGATE_FINISH))
|
||||
viewModelScope.launch {
|
||||
session.cryptoService().keysBackupService().checkAndStartKeysBackup()
|
||||
}
|
||||
}
|
||||
|
||||
private fun createKeysBackup(context: Context, keysBackup: KeysBackupService, forceOverride: Boolean = false) {
|
||||
|
@ -150,45 +133,35 @@ class KeysBackupSetupSharedViewModel @Inject constructor() : ViewModel() {
|
|||
|
||||
creatingBackupError.value = null
|
||||
|
||||
keysBackup.getCurrentVersion(object : MatrixCallback<KeysVersionResult?> {
|
||||
override fun onSuccess(data: KeysVersionResult?) {
|
||||
viewModelScope.launch {
|
||||
try {
|
||||
val data = keysBackup.getCurrentVersion()
|
||||
if (data?.version.isNullOrBlank() || forceOverride) {
|
||||
processOnCreate()
|
||||
processOnCreate(keysBackup)
|
||||
} else {
|
||||
loadingStatus.value = null
|
||||
loadingStatus.postValue(null)
|
||||
// we should prompt
|
||||
isCreatingBackupVersion.value = false
|
||||
navigateEvent.value = LiveEvent(NAVIGATE_PROMPT_REPLACE)
|
||||
isCreatingBackupVersion.postValue(false)
|
||||
navigateEvent.postValue(LiveEvent(NAVIGATE_PROMPT_REPLACE))
|
||||
}
|
||||
} catch (failure: Throwable) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onFailure(failure: Throwable) {
|
||||
Timber.e(failure, "## createKeyBackupVersion")
|
||||
loadingStatus.value = null
|
||||
suspend fun processOnCreate(keysBackup: KeysBackupService) {
|
||||
try {
|
||||
loadingStatus.postValue(null)
|
||||
val created = keysBackup.createKeysBackupVersion(megolmBackupCreationInfo!!)
|
||||
isCreatingBackupVersion.postValue(false)
|
||||
keysVersion.postValue(created)
|
||||
navigateEvent.value = LiveEvent(NAVIGATE_TO_STEP_3)
|
||||
} catch (failure: Throwable) {
|
||||
Timber.e(failure, "## createKeyBackupVersion")
|
||||
loadingStatus.postValue(null)
|
||||
|
||||
isCreatingBackupVersion.value = false
|
||||
creatingBackupError.value = failure
|
||||
}
|
||||
|
||||
fun processOnCreate() {
|
||||
keysBackup.createKeysBackupVersion(megolmBackupCreationInfo!!, object : MatrixCallback<KeysVersion> {
|
||||
override fun onSuccess(data: KeysVersion) {
|
||||
loadingStatus.value = null
|
||||
|
||||
isCreatingBackupVersion.value = false
|
||||
keysVersion.value = data
|
||||
navigateEvent.value = LiveEvent(NAVIGATE_TO_STEP_3)
|
||||
}
|
||||
|
||||
override fun onFailure(failure: Throwable) {
|
||||
Timber.e(failure, "## createKeyBackupVersion")
|
||||
loadingStatus.value = null
|
||||
|
||||
isCreatingBackupVersion.value = false
|
||||
creatingBackupError.value = failure
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
isCreatingBackupVersion.postValue(false)
|
||||
creatingBackupError.postValue(failure)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,7 +20,9 @@ import im.vector.app.R
|
|||
import im.vector.app.core.platform.ViewModelTask
|
||||
import im.vector.app.core.platform.WaitingViewData
|
||||
import im.vector.app.core.resources.StringProvider
|
||||
import org.matrix.android.sdk.api.NoOpMatrixCallback
|
||||
import im.vector.app.features.session.coroutineScope
|
||||
import kotlinx.coroutines.launch
|
||||
import org.matrix.android.sdk.api.extensions.tryOrNull
|
||||
import org.matrix.android.sdk.api.listeners.ProgressListener
|
||||
import org.matrix.android.sdk.api.session.Session
|
||||
import org.matrix.android.sdk.api.session.crypto.crosssigning.KEYBACKUP_SECRET_SSSS_NAME
|
||||
|
@ -32,7 +34,6 @@ import org.matrix.android.sdk.internal.crypto.crosssigning.toBase64NoPadding
|
|||
import org.matrix.android.sdk.internal.crypto.keysbackup.deriveKey
|
||||
import org.matrix.android.sdk.internal.crypto.keysbackup.util.computeRecoveryKey
|
||||
import org.matrix.android.sdk.internal.crypto.keysbackup.util.extractCurveKeyFromRecoveryKey
|
||||
import org.matrix.android.sdk.internal.util.awaitCallback
|
||||
import timber.log.Timber
|
||||
import java.util.UUID
|
||||
import javax.inject.Inject
|
||||
|
@ -87,9 +88,7 @@ class BackupToQuadSMigrationTask @Inject constructor(
|
|||
reportProgress(params, R.string.bootstrap_progress_compute_curve_key)
|
||||
val recoveryKey = computeRecoveryKey(curveKey)
|
||||
|
||||
val isValid = awaitCallback<Boolean> {
|
||||
keysBackupService.isValidRecoveryKeyForCurrentVersion(recoveryKey, it)
|
||||
}
|
||||
val isValid = keysBackupService.isValidRecoveryKeyForCurrentVersion(recoveryKey)
|
||||
|
||||
if (!isValid) return Result.InvalidRecoverySecret
|
||||
|
||||
|
@ -141,14 +140,17 @@ class BackupToQuadSMigrationTask @Inject constructor(
|
|||
keysBackupService.saveBackupRecoveryKey(recoveryKey, version.version)
|
||||
|
||||
// while we are there let's restore, but do not block
|
||||
session.cryptoService().keysBackupService().restoreKeysWithRecoveryKey(
|
||||
version,
|
||||
recoveryKey,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
NoOpMatrixCallback()
|
||||
)
|
||||
session.coroutineScope.launch {
|
||||
tryOrNull {
|
||||
session.cryptoService().keysBackupService().restoreKeysWithRecoveryKey(
|
||||
version,
|
||||
recoveryKey,
|
||||
null,
|
||||
null,
|
||||
null
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
return Result.Success
|
||||
} catch (failure: Throwable) {
|
||||
|
|
|
@ -33,9 +33,6 @@ import org.matrix.android.sdk.api.session.securestorage.SharedSecretStorageServi
|
|||
import org.matrix.android.sdk.api.session.securestorage.SsssKeyCreationInfo
|
||||
import org.matrix.android.sdk.api.session.securestorage.SsssKeySpec
|
||||
import org.matrix.android.sdk.internal.crypto.crosssigning.toBase64NoPadding
|
||||
import org.matrix.android.sdk.internal.crypto.keysbackup.model.MegolmBackupCreationInfo
|
||||
import org.matrix.android.sdk.internal.crypto.keysbackup.model.rest.KeysVersion
|
||||
import org.matrix.android.sdk.internal.crypto.keysbackup.model.rest.KeysVersionResult
|
||||
import org.matrix.android.sdk.internal.crypto.keysbackup.util.extractCurveKeyFromRecoveryKey
|
||||
import org.matrix.android.sdk.internal.util.awaitCallback
|
||||
import timber.log.Timber
|
||||
|
@ -221,9 +218,7 @@ class BootstrapCrossSigningTask @Inject constructor(
|
|||
Timber.d("## BootstrapCrossSigningTask: Creating 4S - Checking megolm backup")
|
||||
|
||||
// First ensure that in sync
|
||||
var serverVersion = awaitCallback<KeysVersionResult?> {
|
||||
session.cryptoService().keysBackupService().getCurrentVersion(it)
|
||||
}
|
||||
var serverVersion = session.cryptoService().keysBackupService().getCurrentVersion()
|
||||
|
||||
val knownMegolmSecret = session.cryptoService().keysBackupService().getKeyBackupRecoveryKeyInfo()
|
||||
val isMegolmBackupSecretKnown = knownMegolmSecret != null && knownMegolmSecret.version == serverVersion?.version
|
||||
|
@ -233,21 +228,14 @@ class BootstrapCrossSigningTask @Inject constructor(
|
|||
if (shouldCreateKeyBackup) {
|
||||
// clear all existing backups
|
||||
while (serverVersion != null) {
|
||||
awaitCallback<Unit> {
|
||||
session.cryptoService().keysBackupService().deleteBackup(serverVersion!!.version, it)
|
||||
}
|
||||
serverVersion = awaitCallback {
|
||||
session.cryptoService().keysBackupService().getCurrentVersion(it)
|
||||
}
|
||||
session.cryptoService().keysBackupService().deleteBackup(serverVersion.version)
|
||||
serverVersion = session.cryptoService().keysBackupService().getCurrentVersion()
|
||||
}
|
||||
|
||||
Timber.d("## BootstrapCrossSigningTask: Creating 4S - Create megolm backup")
|
||||
val creationInfo = awaitCallback<MegolmBackupCreationInfo> {
|
||||
session.cryptoService().keysBackupService().prepareKeysBackupVersion(null, null, it)
|
||||
}
|
||||
val version = awaitCallback<KeysVersion> {
|
||||
session.cryptoService().keysBackupService().createKeysBackupVersion(creationInfo, it)
|
||||
}
|
||||
val creationInfo = session.cryptoService().keysBackupService().prepareKeysBackupVersion(null)
|
||||
val version = session.cryptoService().keysBackupService().createKeysBackupVersion(creationInfo)
|
||||
|
||||
// Save it for gossiping
|
||||
Timber.d("## BootstrapCrossSigningTask: Creating 4S - Save megolm backup key for gossiping")
|
||||
session.cryptoService().keysBackupService().saveBackupRecoveryKey(creationInfo.recoveryKey, version = version.version)
|
||||
|
@ -264,12 +252,10 @@ class BootstrapCrossSigningTask @Inject constructor(
|
|||
// ensure we store existing backup secret if we have it!
|
||||
if (isMegolmBackupSecretKnown) {
|
||||
// check it matches
|
||||
val isValid = awaitCallback<Boolean> {
|
||||
session.cryptoService().keysBackupService().isValidRecoveryKeyForCurrentVersion(knownMegolmSecret!!.recoveryKey, it)
|
||||
}
|
||||
val isValid = session.cryptoService().keysBackupService().isValidRecoveryKeyForCurrentVersion(knownMegolmSecret!!.recoveryKey)
|
||||
if (isValid) {
|
||||
Timber.d("## BootstrapCrossSigningTask: Creating 4S - Megolm key valid and known")
|
||||
extractCurveKeyFromRecoveryKey(knownMegolmSecret!!.recoveryKey)?.toBase64NoPadding()?.let { secret ->
|
||||
extractCurveKeyFromRecoveryKey(knownMegolmSecret.recoveryKey)?.toBase64NoPadding()?.let { secret ->
|
||||
ssssService.storeSecret(
|
||||
KEYBACKUP_SECRET_SSSS_NAME,
|
||||
secret,
|
||||
|
|
|
@ -42,14 +42,13 @@ import org.matrix.android.sdk.api.auth.UserPasswordAuth
|
|||
import org.matrix.android.sdk.api.auth.data.LoginFlowTypes
|
||||
import org.matrix.android.sdk.api.auth.registration.RegistrationFlowResponse
|
||||
import org.matrix.android.sdk.api.auth.registration.nextUncompletedStage
|
||||
import org.matrix.android.sdk.api.extensions.tryOrNull
|
||||
import org.matrix.android.sdk.api.failure.Failure
|
||||
import org.matrix.android.sdk.api.session.Session
|
||||
import org.matrix.android.sdk.api.session.securestorage.RawBytesKeySpec
|
||||
import org.matrix.android.sdk.internal.crypto.crosssigning.fromBase64
|
||||
import org.matrix.android.sdk.internal.crypto.keysbackup.model.rest.KeysVersionResult
|
||||
import org.matrix.android.sdk.internal.crypto.keysbackup.util.extractCurveKeyFromRecoveryKey
|
||||
import org.matrix.android.sdk.internal.crypto.model.rest.DefaultBaseAuth
|
||||
import org.matrix.android.sdk.internal.util.awaitCallback
|
||||
import java.io.OutputStream
|
||||
import kotlin.coroutines.Continuation
|
||||
import kotlin.coroutines.resume
|
||||
|
@ -104,9 +103,8 @@ class BootstrapSharedViewModel @AssistedInject constructor(
|
|||
|
||||
// We need to check if there is an existing backup
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
val version = awaitCallback<KeysVersionResult?> {
|
||||
session.cryptoService().keysBackupService().getCurrentVersion(it)
|
||||
}
|
||||
val version = tryOrNull { session.cryptoService().keysBackupService().getCurrentVersion() }
|
||||
|
||||
if (version == null) {
|
||||
// we just resume plain bootstrap
|
||||
doesKeyBackupExist = false
|
||||
|
@ -115,8 +113,8 @@ class BootstrapSharedViewModel @AssistedInject constructor(
|
|||
}
|
||||
} else {
|
||||
// we need to get existing backup passphrase/key and convert to SSSS
|
||||
val keyVersion = awaitCallback<KeysVersionResult?> {
|
||||
session.cryptoService().keysBackupService().getVersion(version.version, it)
|
||||
val keyVersion = tryOrNull {
|
||||
session.cryptoService().keysBackupService().getVersion(version.version)
|
||||
}
|
||||
if (keyVersion == null) {
|
||||
// strange case... just finish?
|
||||
|
|
|
@ -31,9 +31,10 @@ import im.vector.app.core.di.hiltMavericksViewModelFactory
|
|||
import im.vector.app.core.extensions.exhaustive
|
||||
import im.vector.app.core.platform.VectorViewModel
|
||||
import im.vector.app.core.resources.StringProvider
|
||||
import im.vector.app.features.session.coroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import org.matrix.android.sdk.api.MatrixCallback
|
||||
import org.matrix.android.sdk.api.extensions.tryOrNull
|
||||
import org.matrix.android.sdk.api.session.Session
|
||||
import org.matrix.android.sdk.api.session.crypto.crosssigning.KEYBACKUP_SECRET_SSSS_NAME
|
||||
import org.matrix.android.sdk.api.session.crypto.crosssigning.MASTER_KEY_SSSS_NAME
|
||||
|
@ -52,10 +53,7 @@ import org.matrix.android.sdk.api.util.MatrixItem
|
|||
import org.matrix.android.sdk.api.util.toMatrixItem
|
||||
import org.matrix.android.sdk.internal.crypto.crosssigning.fromBase64
|
||||
import org.matrix.android.sdk.internal.crypto.crosssigning.isVerified
|
||||
import org.matrix.android.sdk.internal.crypto.keysbackup.model.rest.KeysVersionResult
|
||||
import org.matrix.android.sdk.internal.crypto.keysbackup.util.computeRecoveryKey
|
||||
import org.matrix.android.sdk.internal.crypto.model.ImportRoomKeysResult
|
||||
import org.matrix.android.sdk.internal.util.awaitCallback
|
||||
import timber.log.Timber
|
||||
|
||||
data class VerificationBottomSheetViewState(
|
||||
|
@ -372,7 +370,8 @@ class VerificationBottomSheetViewModel @AssistedInject constructor(
|
|||
try {
|
||||
action.cypherData.fromBase64().inputStream().use { ins ->
|
||||
val res = session.loadSecureSecret<Map<String, String>>(ins, action.alias)
|
||||
val trustResult = session.cryptoService().crossSigningService().checkTrustFromPrivateKeys(
|
||||
val crossSigningService = session.cryptoService().crossSigningService()
|
||||
val trustResult = crossSigningService.checkTrustFromPrivateKeys(
|
||||
res?.get(MASTER_KEY_SSSS_NAME),
|
||||
res?.get(USER_SIGNING_KEY_SSSS_NAME),
|
||||
res?.get(SELF_SIGNING_KEY_SSSS_NAME)
|
||||
|
@ -380,12 +379,11 @@ class VerificationBottomSheetViewModel @AssistedInject constructor(
|
|||
if (trustResult.isVerified()) {
|
||||
// Sign this device and upload the signature
|
||||
session.sessionParams.deviceId?.let { deviceId ->
|
||||
session.cryptoService()
|
||||
.crossSigningService().trustDevice(deviceId, object : MatrixCallback<Unit> {
|
||||
override fun onFailure(failure: Throwable) {
|
||||
Timber.w(failure, "Failed to sign my device after recovery")
|
||||
}
|
||||
})
|
||||
try {
|
||||
crossSigningService.trustDevice(deviceId)
|
||||
} catch (failure: Exception) {
|
||||
Timber.w(failure, "Failed to sign my device after recovery")
|
||||
}
|
||||
}
|
||||
|
||||
setState {
|
||||
|
@ -420,30 +418,27 @@ class VerificationBottomSheetViewModel @AssistedInject constructor(
|
|||
}
|
||||
|
||||
private fun tentativeRestoreBackup(res: Map<String, String>?) {
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
// on session scope because will happen after viewmodel is cleared
|
||||
session.coroutineScope.launch {
|
||||
try {
|
||||
val secret = res?.get(KEYBACKUP_SECRET_SSSS_NAME) ?: return@launch Unit.also {
|
||||
Timber.v("## Keybackup secret not restored from SSSS")
|
||||
}
|
||||
|
||||
val version = awaitCallback<KeysVersionResult?> {
|
||||
session.cryptoService().keysBackupService().getCurrentVersion(it)
|
||||
} ?: return@launch
|
||||
val version = tryOrNull { session.cryptoService().keysBackupService().getCurrentVersion() }
|
||||
?: return@launch
|
||||
|
||||
awaitCallback<ImportRoomKeysResult> {
|
||||
session.cryptoService().keysBackupService().restoreKeysWithRecoveryKey(
|
||||
version,
|
||||
computeRecoveryKey(secret.fromBase64()),
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
it
|
||||
)
|
||||
}
|
||||
// TODO maybe mark as trusted earlier by checking recovery key early, then download?
|
||||
|
||||
awaitCallback<Unit> {
|
||||
session.cryptoService().keysBackupService().trustKeysBackupVersion(version, true, it)
|
||||
}
|
||||
session.cryptoService().keysBackupService().restoreKeysWithRecoveryKey(
|
||||
version,
|
||||
computeRecoveryKey(secret.fromBase64()),
|
||||
null,
|
||||
null,
|
||||
null
|
||||
)
|
||||
|
||||
session.cryptoService().keysBackupService().trustKeysBackupVersion(version, true)
|
||||
} catch (failure: Throwable) {
|
||||
// Just ignore for now
|
||||
Timber.e(failure, "## Failed to restore backup after SSSS recovery")
|
||||
|
|
|
@ -261,9 +261,7 @@ class DevicesViewModel @AssistedInject constructor(
|
|||
viewModelScope.launch {
|
||||
if (state.hasAccountCrossSigning) {
|
||||
try {
|
||||
awaitCallback<Unit> {
|
||||
session.cryptoService().crossSigningService().trustDevice(action.cryptoDeviceInfo.deviceId, it)
|
||||
}
|
||||
session.cryptoService().crossSigningService().trustDevice(action.cryptoDeviceInfo.deviceId)
|
||||
} catch (failure: Throwable) {
|
||||
Timber.e("Failed to manually cross sign device ${action.cryptoDeviceInfo.deviceId} : ${failure.localizedMessage}")
|
||||
_viewEvents.post(DevicesViewEvents.Failure(failure))
|
||||
|
|
|
@ -155,7 +155,9 @@ class ServerBackupStatusViewModel @AssistedInject constructor(@Assisted initialS
|
|||
|
||||
fun refreshRemoteStateIfNeeded() {
|
||||
if (keysBackupState.value == KeysBackupState.Disabled) {
|
||||
session.cryptoService().keysBackupService().checkAndStartKeysBackup()
|
||||
viewModelScope.launch {
|
||||
session.cryptoService().keysBackupService().checkAndStartKeysBackup()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -73,7 +73,9 @@ class SignoutCheckViewModel @AssistedInject constructor(
|
|||
|
||||
init {
|
||||
session.cryptoService().keysBackupService().addListener(this)
|
||||
session.cryptoService().keysBackupService().checkAndStartKeysBackup()
|
||||
viewModelScope.launch {
|
||||
session.cryptoService().keysBackupService().checkAndStartKeysBackup()
|
||||
}
|
||||
|
||||
val quad4SIsSetup = session.sharedSecretStorageService.isRecoverySetup()
|
||||
val allKeysKnown = session.cryptoService().crossSigningService().allPrivateKeysKnown()
|
||||
|
@ -112,7 +114,9 @@ class SignoutCheckViewModel @AssistedInject constructor(
|
|||
|
||||
fun refreshRemoteStateIfNeeded() = withState { state ->
|
||||
if (state.keysBackupState == KeysBackupState.Disabled) {
|
||||
session.cryptoService().keysBackupService().checkAndStartKeysBackup()
|
||||
viewModelScope.launch {
|
||||
session.cryptoService().keysBackupService().checkAndStartKeysBackup()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2041,6 +2041,7 @@
|
|||
<string name="keys_backup_restoring_computing_key_waiting_message">Computing recovery key…</string>
|
||||
<string name="keys_backup_restoring_downloading_backup_waiting_message">Downloading keys…</string>
|
||||
<string name="keys_backup_restoring_importing_keys_waiting_message">Importing keys…</string>
|
||||
<string name="keys_backup_restoring_decrypting_keys_waiting_message">Decrypting keys…</string>
|
||||
<string name="keys_backup_unlock_button">Unlock History</string>
|
||||
<string name="keys_backup_recovery_code_empty_error_message">Please enter a recovery key</string>
|
||||
<string name="keys_backup_recovery_code_error_decrypt">Backup could not be decrypted with this recovery key: please verify that you entered the correct recovery key.</string>
|
||||
|
@ -3442,6 +3443,7 @@
|
|||
<string name="command_description_join_space">Join the Space with the given id</string>
|
||||
<string name="command_description_leave_room">Leave room with given id (or current room if null)</string>
|
||||
<string name="command_description_upgrade_room">Upgrades a room to a new version</string>
|
||||
<string name="command_description_gen_keys">Gen keys</string>
|
||||
|
||||
<string name="event_status_a11y_sending">Sending</string>
|
||||
<string name="event_status_a11y_sent">Sent</string>
|
||||
|
|
Loading…
Add table
Reference in a new issue