From b0aae8472704a0004d12e204e0f3152340dd1249 Mon Sep 17 00:00:00 2001 From: ganfra Date: Wed, 25 May 2022 14:45:31 +0200 Subject: [PATCH] Use BackupRecoveryKey instead of plain string --- .../android/sdk/common/CryptoTestHelper.kt | 5 +- .../crypto/keysbackup/KeysBackupTest.kt | 5 +- .../crypto/keysbackup/KeysBackupService.kt | 9 ++- .../keysbackup/MegolmBackupCreationInfo.kt | 4 +- .../keysbackup/SavedKeyBackupKeyInfo.kt | 2 +- .../PerSessionBackupQueryRateLimiter.kt | 7 +-- .../crypto/keysbackup/RustKeyBackupService.kt | 57 ++++++++++--------- .../crypto/store/db/RealmCryptoStore.kt | 4 +- .../sync/handler/room/RoomSyncHandler.kt | 3 +- .../KeysBackupRestoreFromKeyViewModel.kt | 3 +- .../KeysBackupRestoreSharedViewModel.kt | 41 ++++++++----- .../setup/KeysBackupSetupSharedViewModel.kt | 3 +- .../setup/KeysBackupSetupStep3Fragment.kt | 13 +++-- .../recover/BackupToQuadSMigrationTask.kt | 7 ++- .../recover/BootstrapCrossSigningTask.kt | 4 +- .../VerificationBottomSheetViewModel.kt | 9 ++- 16 files changed, 101 insertions(+), 75 deletions(-) diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CryptoTestHelper.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CryptoTestHelper.kt index ef190f5a2e..ad8963c00d 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CryptoTestHelper.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CryptoTestHelper.kt @@ -38,6 +38,7 @@ import org.matrix.android.sdk.api.session.crypto.crosssigning.KEYBACKUP_SECRET_S import org.matrix.android.sdk.api.session.crypto.crosssigning.MASTER_KEY_SSSS_NAME import org.matrix.android.sdk.api.session.crypto.crosssigning.SELF_SIGNING_KEY_SSSS_NAME import org.matrix.android.sdk.api.session.crypto.crosssigning.USER_SIGNING_KEY_SSSS_NAME +import org.matrix.android.sdk.api.session.crypto.keysbackup.BackupRecoveryKey import org.matrix.android.sdk.api.session.crypto.keysbackup.MegolmBackupAuthData import org.matrix.android.sdk.api.session.crypto.keysbackup.MegolmBackupCreationInfo import org.matrix.android.sdk.api.session.crypto.keysbackup.extractCurveKeyFromRecoveryKey @@ -250,7 +251,7 @@ class CryptoTestHelper(private val testHelper: CommonTestHelper) { return MegolmBackupCreationInfo( algorithm = MXCRYPTO_ALGORITHM_MEGOLM_BACKUP, authData = createFakeMegolmBackupAuthData(), - recoveryKey = "fake" + recoveryKey = BackupRecoveryKey.fromBase58("3cnTdW") ) } @@ -445,7 +446,7 @@ class CryptoTestHelper(private val testHelper: CommonTestHelper) { // Save it for gossiping session.cryptoService().keysBackupService().saveBackupRecoveryKey(creationInfo.recoveryKey, version = version.version) - extractCurveKeyFromRecoveryKey(creationInfo.recoveryKey)?.toBase64NoPadding()?.let { secret -> + extractCurveKeyFromRecoveryKey(creationInfo.recoveryKey.toBase58())?.toBase64NoPadding()?.let { secret -> ssssService.storeSecret( KEYBACKUP_SECRET_SSSS_NAME, secret, diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/keysbackup/KeysBackupTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/keysbackup/KeysBackupTest.kt index 1e600c7588..ecca618158 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/keysbackup/KeysBackupTest.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/keysbackup/KeysBackupTest.kt @@ -34,6 +34,7 @@ import org.junit.runners.MethodSorters import org.matrix.android.sdk.InstrumentedTest import org.matrix.android.sdk.api.crypto.MXCRYPTO_ALGORITHM_MEGOLM_BACKUP import org.matrix.android.sdk.api.listeners.StepProgressListener +import org.matrix.android.sdk.api.session.crypto.keysbackup.BackupRecoveryKey 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.api.session.crypto.keysbackup.toKeysVersionResult @@ -505,7 +506,7 @@ class KeysBackupTest : InstrumentedTest { try { testData.aliceSession2.cryptoService().keysBackupService().trustKeysBackupVersionWithRecoveryKey( testData.aliceSession2.cryptoService().keysBackupService().keysBackupVersion!!, - "Bad recovery key" + BackupRecoveryKey.fromBase58("Bad recovery key") ) fail("Should have failed to trust") } catch (failure: Throwable) { @@ -645,7 +646,7 @@ class KeysBackupTest : InstrumentedTest { var importRoomKeysResult: ImportRoomKeysResult? = null testHelper.runBlockingTest { testData.aliceSession2.cryptoService().keysBackupService().restoreKeysWithRecoveryKey(testData.aliceSession2.cryptoService().keysBackupService().keysBackupVersion!!, - "EsTc LW2K PGiF wKEA 3As5 g5c4 BXwk qeeJ ZJV8 Q9fu gUMN UE4d", + BackupRecoveryKey.fromBase58("EsTc LW2K PGiF wKEA 3As5 g5c4 BXwk qeeJ ZJV8 Q9fu gUMN UE4d"), null, null, null diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keysbackup/KeysBackupService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keysbackup/KeysBackupService.kt index eea0c60451..bd684dd90d 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keysbackup/KeysBackupService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keysbackup/KeysBackupService.kt @@ -142,8 +142,7 @@ interface KeysBackupService { * @param keysBackupVersion the backup version to check. * @param recoveryKey the recovery key to challenge with the key backup public key. */ - suspend fun trustKeysBackupVersionWithRecoveryKey(keysBackupVersion: KeysVersionResult, - recoveryKey: String) + suspend fun trustKeysBackupVersionWithRecoveryKey(keysBackupVersion: KeysVersionResult, recoveryKey: BackupRecoveryKey) /** * Set trust on a keys backup version. @@ -167,7 +166,7 @@ interface KeysBackupService { * @param callback Callback. It provides the number of found keys and the number of successfully imported keys. */ suspend fun restoreKeysWithRecoveryKey(keysVersionResult: KeysVersionResult, - recoveryKey: String, roomId: String?, + recoveryKey: BackupRecoveryKey, roomId: String?, sessionId: String?, stepProgressListener: StepProgressListener?): ImportRoomKeysResult @@ -194,10 +193,10 @@ interface KeysBackupService { val state: KeysBackupState // For gossiping - fun saveBackupRecoveryKey(recoveryKey: String?, version: String?) + fun saveBackupRecoveryKey(recoveryKey: BackupRecoveryKey?, version: String?) suspend fun getKeyBackupRecoveryKeyInfo(): SavedKeyBackupKeyInfo? - suspend fun isValidRecoveryKeyForCurrentVersion(recoveryKey: String): Boolean + suspend fun isValidRecoveryKeyForCurrentVersion(recoveryKey: BackupRecoveryKey): Boolean fun computePrivateKey(passphrase: String, privateKeySalt: String, diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keysbackup/MegolmBackupCreationInfo.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keysbackup/MegolmBackupCreationInfo.kt index 0d708b8d73..8761665c6e 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keysbackup/MegolmBackupCreationInfo.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keysbackup/MegolmBackupCreationInfo.kt @@ -31,7 +31,7 @@ data class MegolmBackupCreationInfo( val authData: MegolmBackupAuthData, /** - * The Base58 recovery key. + * The recovery key. */ - val recoveryKey: String + val recoveryKey: BackupRecoveryKey ) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keysbackup/SavedKeyBackupKeyInfo.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keysbackup/SavedKeyBackupKeyInfo.kt index 7f90fea9af..ee063eda51 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keysbackup/SavedKeyBackupKeyInfo.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keysbackup/SavedKeyBackupKeyInfo.kt @@ -17,6 +17,6 @@ package org.matrix.android.sdk.api.session.crypto.keysbackup data class SavedKeyBackupKeyInfo( - val recoveryKey: String, + val recoveryKey: BackupRecoveryKey, val version: String ) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/PerSessionBackupQueryRateLimiter.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/PerSessionBackupQueryRateLimiter.kt index 8fcdb4168b..10ac0cced0 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/PerSessionBackupQueryRateLimiter.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/PerSessionBackupQueryRateLimiter.kt @@ -20,10 +20,9 @@ import dagger.Lazy import kotlinx.coroutines.withContext import org.matrix.android.sdk.api.MatrixCoroutineDispatchers import org.matrix.android.sdk.api.logger.LoggerTag +import org.matrix.android.sdk.api.session.crypto.keysbackup.BackupRecoveryKey import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysVersionResult import org.matrix.android.sdk.api.session.crypto.keysbackup.SavedKeyBackupKeyInfo -import org.matrix.android.sdk.api.session.crypto.model.ImportRoomKeysResult -import org.matrix.android.sdk.api.util.awaitCallback import org.matrix.android.sdk.internal.crypto.keysbackup.RustKeyBackupService import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore import org.matrix.android.sdk.internal.util.time.Clock @@ -101,12 +100,12 @@ internal class PerSessionBackupQueryRateLimiter @Inject constructor( (now - lastTry.timestamp) > MIN_TRY_BACKUP_PERIOD_MILLIS if (!shouldQuery) return false - + val recoveryKey = savedKeyBackupKeyInfo?.recoveryKey ?: return false val successfullyImported = withContext(coroutineDispatchers.io) { try { keysBackupService.get().restoreKeysWithRecoveryKey( currentVersion, - savedKeyBackupKeyInfo?.recoveryKey ?: "", + recoveryKey, roomId, sessionId, null, diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/RustKeyBackupService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/RustKeyBackupService.kt index 37ef4ea29b..54ca9be784 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/RustKeyBackupService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/RustKeyBackupService.kt @@ -34,6 +34,7 @@ import org.matrix.android.sdk.api.failure.Failure import org.matrix.android.sdk.api.failure.MatrixError 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.BackupRecoveryKey import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupLastVersionResult import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupService import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupState @@ -60,7 +61,6 @@ import org.matrix.android.sdk.internal.session.SessionScope import org.matrix.android.sdk.internal.util.JsonCanonicalizer import org.matrix.olm.OlmException import timber.log.Timber -import uniffi.olm.BackupRecoveryKey import uniffi.olm.Request import uniffi.olm.RequestType import java.security.InvalidParameterException @@ -150,7 +150,7 @@ internal class RustKeyBackupService @Inject constructor( MegolmBackupCreationInfo( algorithm = publicKey.backupAlgorithm, authData = signedMegolmBackupAuthData, - recoveryKey = key.toBase58() + recoveryKey = key ) } } @@ -189,9 +189,11 @@ internal class RustKeyBackupService @Inject constructor( } } - override fun saveBackupRecoveryKey(recoveryKey: String?, version: String?) { + override fun saveBackupRecoveryKey(recoveryKey: BackupRecoveryKey?, version: String?) { cryptoCoroutineScope.launch { - olmMachine.saveRecoveryKey(recoveryKey, version) + val recoveryKeyStr = recoveryKey?.toBase64() + // TODO : change rust API to use BackupRecoveryKey + olmMachine.saveRecoveryKey(recoveryKeyStr, version) } } @@ -312,7 +314,8 @@ internal class RustKeyBackupService @Inject constructor( val body = UpdateKeysBackupVersionBody( algorithm = keysBackupVersion.algorithm, authData = newAuthData.copy(signatures = newSignatures).toJsonDict(), - version = keysBackupVersion.version) + version = keysBackupVersion.version + ) withContext(coroutineDispatchers.io) { sender.updateBackup(keysBackupVersion, body) @@ -353,14 +356,13 @@ internal class RustKeyBackupService @Inject constructor( } } - override suspend fun trustKeysBackupVersionWithRecoveryKey(keysBackupVersion: KeysVersionResult, recoveryKey: String) { + override suspend fun trustKeysBackupVersionWithRecoveryKey(keysBackupVersion: KeysVersionResult, recoveryKey: BackupRecoveryKey) { Timber.v("trustKeysBackupVersionWithRecoveryKey: version ${keysBackupVersion.version}") withContext(coroutineDispatchers.crypto) { // This is ~nowhere mentioned, the string here is actually a base58 encoded key. // This not really supported by the spec for the backup key, the 4S key supports // base58 encoding and the same method seems to be used here. - val key = BackupRecoveryKey.fromBase58(recoveryKey) - checkRecoveryKey(key, keysBackupVersion) + checkRecoveryKey(recoveryKey, keysBackupVersion) trustKeysBackupVersion(keysBackupVersion, true) } } @@ -378,7 +380,7 @@ internal class RustKeyBackupService @Inject constructor( withContext(coroutineDispatchers.crypto) { try { val version = sender.getKeyBackupLastVersion()?.toKeysVersionResult() - + Timber.v("Keybackup version: $version") if (version != null) { val key = BackupRecoveryKey.fromBase64(secret) if (isValidRecoveryKey(key, version)) { @@ -395,7 +397,9 @@ internal class RustKeyBackupService @Inject constructor( } } // we can save, it's valid - saveBackupRecoveryKey(key.toBase64(), version.version) + saveBackupRecoveryKey(key, version.version) + } else { + Timber.d("Invalid recovery key") } } else { Timber.e("onSecretKeyGossip: Failed to import backup recovery key, no backup version was found on the server") @@ -480,7 +484,7 @@ internal class RustKeyBackupService @Inject constructor( } // Save for next time and for gossiping - saveBackupRecoveryKey(recoveryKey.toBase64(), keysVersionResult.version) + saveBackupRecoveryKey(recoveryKey, keysVersionResult.version) } withContext(coroutineDispatchers.main) { @@ -519,14 +523,18 @@ internal class RustKeyBackupService @Inject constructor( stepProgressListener?.onStepProgress(stepProgress) } - Timber.v("restoreKeysWithRecoveryKey: Decrypted ${sessionsData.size} keys out" + - " of ${data.roomIdToRoomKeysBackupData.size} rooms from the backup store on the homeserver") + Timber.v( + "restoreKeysWithRecoveryKey: Decrypted ${sessionsData.size} keys out" + + " of ${data.roomIdToRoomKeysBackupData.size} rooms from the backup store on the homeserver" + ) // Do not trigger a backup for them if they come from the backup version we are using val backUp = keysVersionResult.version != keysBackupVersion?.version if (backUp) { - Timber.v("restoreKeysWithRecoveryKey: Those keys will be backed up" + - " to backup version: ${keysBackupVersion?.version}") + Timber.v( + "restoreKeysWithRecoveryKey: Those keys will be backed up" + + " to backup version: ${keysBackupVersion?.version}" + ) } // Import them into the crypto store @@ -557,15 +565,12 @@ internal class RustKeyBackupService @Inject constructor( } override suspend fun restoreKeysWithRecoveryKey(keysVersionResult: KeysVersionResult, - recoveryKey: String, + recoveryKey: BackupRecoveryKey, roomId: String?, sessionId: String?, stepProgressListener: StepProgressListener?): ImportRoomKeysResult { Timber.v("restoreKeysWithRecoveryKey: From backup version: ${keysVersionResult.version}") - - val key = BackupRecoveryKey.fromBase58(recoveryKey) - - return restoreBackup(keysVersionResult, key, roomId, sessionId, stepProgressListener) + return restoreBackup(keysVersionResult, recoveryKey, roomId, sessionId, stepProgressListener) } override suspend fun restoreKeyBackupWithPassword(keysBackupVersion: KeysVersionResult, @@ -577,7 +582,6 @@ internal class RustKeyBackupService @Inject constructor( val recoveryKey = withContext(coroutineDispatchers.crypto) { recoveryKeyFromPassword(password, keysBackupVersion) } - return restoreBackup(keysBackupVersion, recoveryKey, roomId, sessionId, stepProgressListener) } @@ -703,16 +707,15 @@ internal class RustKeyBackupService @Inject constructor( private fun isValidRecoveryKey(recoveryKey: BackupRecoveryKey, version: KeysVersionResult): Boolean { val publicKey = recoveryKey.megolmV1PublicKey().publicKey val authData = getMegolmBackupAuthData(version) ?: return false + Timber.v("recoveryKey.megolmV1PublicKey().publicKey $publicKey == getMegolmBackupAuthData(version).publicKey ${authData.publicKey}") return authData.publicKey == publicKey } - override suspend fun isValidRecoveryKeyForCurrentVersion(recoveryKey: String): Boolean { + override suspend fun isValidRecoveryKeyForCurrentVersion(recoveryKey: BackupRecoveryKey): Boolean { return withContext(coroutineDispatchers.crypto) { val keysBackupVersion = keysBackupVersion ?: return@withContext false - - val key = BackupRecoveryKey.fromBase64(recoveryKey) try { - isValidRecoveryKey(key, keysBackupVersion) + isValidRecoveryKey(recoveryKey, keysBackupVersion) } catch (failure: Throwable) { Timber.i("isValidRecoveryKeyForCurrentVersion: Invalid recovery key") false @@ -726,7 +729,9 @@ internal class RustKeyBackupService @Inject constructor( override suspend fun getKeyBackupRecoveryKeyInfo(): SavedKeyBackupKeyInfo? { val info = olmMachine.getBackupKeys() ?: return null - return SavedKeyBackupKeyInfo(info.recoveryKey, info.backupVersion) + // TODO change rust ffi to return BackupRecoveryKey instead of base64 string + val backupRecoveryKey = BackupRecoveryKey.fromBase64(info.recoveryKey) + return SavedKeyBackupKeyInfo(backupRecoveryKey, info.backupVersion) } /** diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/RealmCryptoStore.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/RealmCryptoStore.kt index d5750a2e2a..c7a0b5abf1 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/RealmCryptoStore.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/RealmCryptoStore.kt @@ -35,6 +35,7 @@ import org.matrix.android.sdk.api.session.crypto.OutgoingRoomKeyRequestState import org.matrix.android.sdk.api.session.crypto.crosssigning.CryptoCrossSigningKey import org.matrix.android.sdk.api.session.crypto.crosssigning.MXCrossSigningInfo import org.matrix.android.sdk.api.session.crypto.crosssigning.PrivateKeysInfo +import org.matrix.android.sdk.api.session.crypto.keysbackup.BackupRecoveryKey import org.matrix.android.sdk.api.session.crypto.keysbackup.SavedKeyBackupKeyInfo import org.matrix.android.sdk.api.session.crypto.model.AuditTrail import org.matrix.android.sdk.api.session.crypto.model.CryptoDeviceInfo @@ -469,7 +470,8 @@ internal class RealmCryptoStore @Inject constructor( val key = it.keyBackupRecoveryKey val version = it.keyBackupRecoveryKeyVersion if (!key.isNullOrBlank() && !version.isNullOrBlank()) { - SavedKeyBackupKeyInfo(recoveryKey = key, version = version) + val backupRecoveryKey = BackupRecoveryKey.fromBase58(key) + SavedKeyBackupKeyInfo(recoveryKey = backupRecoveryKey, version = version) } else { null } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/handler/room/RoomSyncHandler.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/handler/room/RoomSyncHandler.kt index fb1aac6a51..fe6368364b 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/handler/room/RoomSyncHandler.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/handler/room/RoomSyncHandler.kt @@ -520,10 +520,9 @@ internal class RoomSyncHandler @Inject constructor( private fun decryptIfNeeded(event: Event, roomId: String) { try { - // Event from sync does not have roomId, so add it to the event first // note: runBlocking should be used here while we are in realm single thread executor, to avoid thread switching val result = runBlocking { - cryptoService.decryptEvent(event.copy(roomId = roomId), "") + cryptoService.decryptEvent(event, "") } event.mxDecryptionResult = OlmDecryptionResult( payload = result.clearEvent, diff --git a/vector/src/main/java/im/vector/app/features/crypto/keysbackup/restore/KeysBackupRestoreFromKeyViewModel.kt b/vector/src/main/java/im/vector/app/features/crypto/keysbackup/restore/KeysBackupRestoreFromKeyViewModel.kt index a0a6a138dc..6e96d7c857 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/keysbackup/restore/KeysBackupRestoreFromKeyViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/keysbackup/restore/KeysBackupRestoreFromKeyViewModel.kt @@ -23,6 +23,7 @@ import im.vector.app.core.platform.WaitingViewData import im.vector.app.core.resources.StringProvider import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch +import org.matrix.android.sdk.api.session.crypto.keysbackup.BackupRecoveryKey import javax.inject.Inject class KeysBackupRestoreFromKeyViewModel @Inject constructor( @@ -42,7 +43,7 @@ class KeysBackupRestoreFromKeyViewModel @Inject constructor( sharedViewModel.loadingEvent.postValue(WaitingViewData(stringProvider.getString(R.string.loading))) recoveryCodeErrorText.value = null viewModelScope.launch(Dispatchers.IO) { - val recoveryKey = recoveryCode.value!! + val recoveryKey = BackupRecoveryKey.fromBase58(recoveryCode.value!!) try { sharedViewModel.recoverUsingBackupRecoveryKey(recoveryKey) } catch (failure: Throwable) { diff --git a/vector/src/main/java/im/vector/app/features/crypto/keysbackup/restore/KeysBackupRestoreSharedViewModel.kt b/vector/src/main/java/im/vector/app/features/crypto/keysbackup/restore/KeysBackupRestoreSharedViewModel.kt index 4c577d0a15..7fc8105dab 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/keysbackup/restore/KeysBackupRestoreSharedViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/keysbackup/restore/KeysBackupRestoreSharedViewModel.kt @@ -31,6 +31,7 @@ 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 +import org.matrix.android.sdk.api.session.crypto.keysbackup.BackupRecoveryKey import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupService import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysVersionResult import org.matrix.android.sdk.api.session.crypto.keysbackup.computeRecoveryKey @@ -88,7 +89,7 @@ class KeysBackupRestoreSharedViewModel @Inject constructor( private val progressObserver = object : StepProgressListener { override fun onStepProgress(step: StepProgressListener.Step) { when (step) { - is StepProgressListener.Step.ComputingKey -> { + is StepProgressListener.Step.ComputingKey -> { loadingEvent.postValue( WaitingViewData( stringProvider.getString(R.string.keys_backup_restoring_waiting_message) + @@ -107,7 +108,7 @@ class KeysBackupRestoreSharedViewModel @Inject constructor( ) ) } - is StepProgressListener.Step.ImportingKey -> { + is StepProgressListener.Step.ImportingKey -> { Timber.d("backupKeys.ImportingKey.progress: ${step.progress}") // Progress 0 can take a while, display an indeterminate progress in this case if (step.progress == 0) { @@ -131,14 +132,22 @@ class KeysBackupRestoreSharedViewModel @Inject constructor( } 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)) + 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)) + 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 + ) + ) } } } @@ -170,7 +179,7 @@ class KeysBackupRestoreSharedViewModel @Inject constructor( ) // Go and use it!! try { - recoverUsingBackupRecoveryKey(computeRecoveryKey(savedSecret.recoveryKey.fromBase64()), version) + recoverUsingBackupRecoveryKey(savedSecret.recoveryKey, version) } catch (failure: Throwable) { Timber.e(failure, "## recoverUsingBackupRecoveryKey FAILED") keySourceModel.postValue( @@ -212,7 +221,9 @@ class KeysBackupRestoreSharedViewModel @Inject constructor( viewModelScope.launch(Dispatchers.IO) { try { - recoverUsingBackupRecoveryKey(computeRecoveryKey(secret.fromBase64())) + val computedRecoveryKey = computeRecoveryKey(secret.fromBase64()) + val backupRecoveryKey = BackupRecoveryKey.fromBase58(computedRecoveryKey) + recoverUsingBackupRecoveryKey(backupRecoveryKey) } catch (failure: Throwable) { _navigateEvent.postValue( LiveEvent(NAVIGATE_FAILED_TO_LOAD_4S) @@ -234,7 +245,8 @@ class KeysBackupRestoreSharedViewModel @Inject constructor( loadingEvent.postValue(WaitingViewData(stringProvider.getString(R.string.loading))) try { - val result = keysBackup.restoreKeyBackupWithPassword(keyVersion, + val result = keysBackup.restoreKeyBackupWithPassword( + keyVersion, passphrase, null, session.myUserId, @@ -249,7 +261,7 @@ class KeysBackupRestoreSharedViewModel @Inject constructor( } } - suspend fun recoverUsingBackupRecoveryKey(recoveryKey: String, keyVersion: KeysVersionResult? = null) { + suspend fun recoverUsingBackupRecoveryKey(recoveryKey: BackupRecoveryKey, keyVersion: KeysVersionResult? = null) { val keysBackup = session.cryptoService().keysBackupService() // This is badddddd val version = keyVersion ?: keyVersionResult.value ?: return @@ -257,7 +269,8 @@ class KeysBackupRestoreSharedViewModel @Inject constructor( loadingEvent.postValue(WaitingViewData(stringProvider.getString(R.string.loading))) try { - val result = keysBackup.restoreKeysWithRecoveryKey(version, + val result = keysBackup.restoreKeysWithRecoveryKey( + version, recoveryKey, null, session.myUserId, diff --git a/vector/src/main/java/im/vector/app/features/crypto/keysbackup/setup/KeysBackupSetupSharedViewModel.kt b/vector/src/main/java/im/vector/app/features/crypto/keysbackup/setup/KeysBackupSetupSharedViewModel.kt index 5209e5edc3..62f5e305e9 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/keysbackup/setup/KeysBackupSetupSharedViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/keysbackup/setup/KeysBackupSetupSharedViewModel.kt @@ -27,6 +27,7 @@ import im.vector.app.core.time.Clock import im.vector.app.core.utils.LiveEvent import kotlinx.coroutines.launch import org.matrix.android.sdk.api.session.Session +import org.matrix.android.sdk.api.session.crypto.keysbackup.BackupRecoveryKey import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupService import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysVersion import org.matrix.android.sdk.api.session.crypto.keysbackup.MegolmBackupCreationInfo @@ -71,7 +72,7 @@ class KeysBackupSetupSharedViewModel @Inject constructor( // Step 3 // Var to ignore events from previous request(s) to generate a recovery key private var currentRequestId: MutableLiveData = MutableLiveData() - var recoveryKey: MutableLiveData = MutableLiveData(null) + var recoveryKey: MutableLiveData = MutableLiveData(null) var prepareRecoverFailError: MutableLiveData = MutableLiveData(null) var megolmBackupCreationInfo: MegolmBackupCreationInfo? = null var copyHasBeenMade = false diff --git a/vector/src/main/java/im/vector/app/features/crypto/keysbackup/setup/KeysBackupSetupStep3Fragment.kt b/vector/src/main/java/im/vector/app/features/crypto/keysbackup/setup/KeysBackupSetupStep3Fragment.kt index 61148f3aab..fa8725c943 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/keysbackup/setup/KeysBackupSetupStep3Fragment.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/keysbackup/setup/KeysBackupSetupStep3Fragment.kt @@ -66,7 +66,7 @@ class KeysBackupSetupStep3Fragment @Inject constructor() : VectorBaseFragment(R.id.keys_backup_recovery_key_text)?.let { it.isVisible = true - it.text = recoveryKey.replace(" ", "") + it.text = recoveryKey.toBase58() + .replace(" ", "") .chunked(16) .joinToString("\n") { it @@ -123,7 +124,7 @@ class KeysBackupSetupStep3Fragment @Inject constructor() : VectorBaseFragment + extractCurveKeyFromRecoveryKey(creationInfo.recoveryKey.toBase58())?.toBase64NoPadding()?.let { secret -> ssssService.storeSecret( KEYBACKUP_SECRET_SSSS_NAME, secret, @@ -251,7 +251,7 @@ class BootstrapCrossSigningTask @Inject constructor( 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.toBase58())?.toBase64NoPadding()?.let { secret -> ssssService.storeSecret( KEYBACKUP_SECRET_SSSS_NAME, secret, diff --git a/vector/src/main/java/im/vector/app/features/crypto/verification/VerificationBottomSheetViewModel.kt b/vector/src/main/java/im/vector/app/features/crypto/verification/VerificationBottomSheetViewModel.kt index 4910c74e59..9f66080111 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/verification/VerificationBottomSheetViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/verification/VerificationBottomSheetViewModel.kt @@ -37,6 +37,7 @@ import org.matrix.android.sdk.api.session.crypto.crosssigning.MASTER_KEY_SSSS_NA import org.matrix.android.sdk.api.session.crypto.crosssigning.SELF_SIGNING_KEY_SSSS_NAME import org.matrix.android.sdk.api.session.crypto.crosssigning.USER_SIGNING_KEY_SSSS_NAME import org.matrix.android.sdk.api.session.crypto.crosssigning.isVerified +import org.matrix.android.sdk.api.session.crypto.keysbackup.BackupRecoveryKey import org.matrix.android.sdk.api.session.crypto.keysbackup.computeRecoveryKey import org.matrix.android.sdk.api.session.crypto.keysbackup.toKeysVersionResult import org.matrix.android.sdk.api.session.crypto.verification.CancelCode @@ -431,9 +432,10 @@ class VerificationBottomSheetViewModel @AssistedInject constructor( val version = session.cryptoService().keysBackupService().getCurrentVersion()?.toKeysVersionResult() ?: return@launch val recoveryKey = computeRecoveryKey(secret.fromBase64()) - val isValid = session.cryptoService().keysBackupService().isValidRecoveryKeyForCurrentVersion(recoveryKey) + val backupRecoveryKey = BackupRecoveryKey.fromBase58(recoveryKey) + val isValid = session.cryptoService().keysBackupService().isValidRecoveryKeyForCurrentVersion(backupRecoveryKey) if (isValid) { - session.cryptoService().keysBackupService().saveBackupRecoveryKey(recoveryKey, version.version) + session.cryptoService().keysBackupService().saveBackupRecoveryKey(backupRecoveryKey, version.version) } session.cryptoService().keysBackupService().trustKeysBackupVersion(version, true) } catch (failure: Throwable) { @@ -502,6 +504,7 @@ class VerificationBottomSheetViewModel @AssistedInject constructor( } override fun transactionUpdated(tx: VerificationTransaction) = withState { state -> + Timber.v("transactionUpdated: $tx") handleTransactionUpdate(state, tx) } @@ -510,7 +513,7 @@ class VerificationBottomSheetViewModel @AssistedInject constructor( } override fun verificationRequestUpdated(pr: PendingVerificationRequest) = withState { state -> - + Timber.v("VerificationRequestUpdated: $pr") if (state.selfVerificationMode && state.pendingRequest.invoke() == null && state.transactionId == null) { // is this an incoming with that user if (pr.isIncoming && pr.otherUserId == state.otherUserMxItem?.id) {