mirror of
https://github.com/SchildiChat/SchildiChat-android.git
synced 2024-12-25 18:38:32 +03:00
Use BackupRecoveryKey instead of plain string
This commit is contained in:
parent
7c76ba8184
commit
b0aae84727
16 changed files with 101 additions and 75 deletions
|
@ -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.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.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.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.MegolmBackupAuthData
|
||||||
import org.matrix.android.sdk.api.session.crypto.keysbackup.MegolmBackupCreationInfo
|
import org.matrix.android.sdk.api.session.crypto.keysbackup.MegolmBackupCreationInfo
|
||||||
import org.matrix.android.sdk.api.session.crypto.keysbackup.extractCurveKeyFromRecoveryKey
|
import org.matrix.android.sdk.api.session.crypto.keysbackup.extractCurveKeyFromRecoveryKey
|
||||||
|
@ -250,7 +251,7 @@ class CryptoTestHelper(private val testHelper: CommonTestHelper) {
|
||||||
return MegolmBackupCreationInfo(
|
return MegolmBackupCreationInfo(
|
||||||
algorithm = MXCRYPTO_ALGORITHM_MEGOLM_BACKUP,
|
algorithm = MXCRYPTO_ALGORITHM_MEGOLM_BACKUP,
|
||||||
authData = createFakeMegolmBackupAuthData(),
|
authData = createFakeMegolmBackupAuthData(),
|
||||||
recoveryKey = "fake"
|
recoveryKey = BackupRecoveryKey.fromBase58("3cnTdW")
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -445,7 +446,7 @@ class CryptoTestHelper(private val testHelper: CommonTestHelper) {
|
||||||
// Save it for gossiping
|
// Save it for gossiping
|
||||||
session.cryptoService().keysBackupService().saveBackupRecoveryKey(creationInfo.recoveryKey, version = version.version)
|
session.cryptoService().keysBackupService().saveBackupRecoveryKey(creationInfo.recoveryKey, version = version.version)
|
||||||
|
|
||||||
extractCurveKeyFromRecoveryKey(creationInfo.recoveryKey)?.toBase64NoPadding()?.let { secret ->
|
extractCurveKeyFromRecoveryKey(creationInfo.recoveryKey.toBase58())?.toBase64NoPadding()?.let { secret ->
|
||||||
ssssService.storeSecret(
|
ssssService.storeSecret(
|
||||||
KEYBACKUP_SECRET_SSSS_NAME,
|
KEYBACKUP_SECRET_SSSS_NAME,
|
||||||
secret,
|
secret,
|
||||||
|
|
|
@ -34,6 +34,7 @@ import org.junit.runners.MethodSorters
|
||||||
import org.matrix.android.sdk.InstrumentedTest
|
import org.matrix.android.sdk.InstrumentedTest
|
||||||
import org.matrix.android.sdk.api.crypto.MXCRYPTO_ALGORITHM_MEGOLM_BACKUP
|
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.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.KeysBackupState
|
||||||
import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupStateListener
|
import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupStateListener
|
||||||
import org.matrix.android.sdk.api.session.crypto.keysbackup.toKeysVersionResult
|
import org.matrix.android.sdk.api.session.crypto.keysbackup.toKeysVersionResult
|
||||||
|
@ -505,7 +506,7 @@ class KeysBackupTest : InstrumentedTest {
|
||||||
try {
|
try {
|
||||||
testData.aliceSession2.cryptoService().keysBackupService().trustKeysBackupVersionWithRecoveryKey(
|
testData.aliceSession2.cryptoService().keysBackupService().trustKeysBackupVersionWithRecoveryKey(
|
||||||
testData.aliceSession2.cryptoService().keysBackupService().keysBackupVersion!!,
|
testData.aliceSession2.cryptoService().keysBackupService().keysBackupVersion!!,
|
||||||
"Bad recovery key"
|
BackupRecoveryKey.fromBase58("Bad recovery key")
|
||||||
)
|
)
|
||||||
fail("Should have failed to trust")
|
fail("Should have failed to trust")
|
||||||
} catch (failure: Throwable) {
|
} catch (failure: Throwable) {
|
||||||
|
@ -645,7 +646,7 @@ class KeysBackupTest : InstrumentedTest {
|
||||||
var importRoomKeysResult: ImportRoomKeysResult? = null
|
var importRoomKeysResult: ImportRoomKeysResult? = null
|
||||||
testHelper.runBlockingTest {
|
testHelper.runBlockingTest {
|
||||||
testData.aliceSession2.cryptoService().keysBackupService().restoreKeysWithRecoveryKey(testData.aliceSession2.cryptoService().keysBackupService().keysBackupVersion!!,
|
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,
|
null,
|
||||||
null
|
null
|
||||||
|
|
|
@ -142,8 +142,7 @@ interface KeysBackupService {
|
||||||
* @param keysBackupVersion the backup version to check.
|
* @param keysBackupVersion the backup version to check.
|
||||||
* @param recoveryKey the recovery key to challenge with the key backup public key.
|
* @param recoveryKey the recovery key to challenge with the key backup public key.
|
||||||
*/
|
*/
|
||||||
suspend fun trustKeysBackupVersionWithRecoveryKey(keysBackupVersion: KeysVersionResult,
|
suspend fun trustKeysBackupVersionWithRecoveryKey(keysBackupVersion: KeysVersionResult, recoveryKey: BackupRecoveryKey)
|
||||||
recoveryKey: String)
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set trust on a keys backup version.
|
* 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.
|
* @param callback Callback. It provides the number of found keys and the number of successfully imported keys.
|
||||||
*/
|
*/
|
||||||
suspend fun restoreKeysWithRecoveryKey(keysVersionResult: KeysVersionResult,
|
suspend fun restoreKeysWithRecoveryKey(keysVersionResult: KeysVersionResult,
|
||||||
recoveryKey: String, roomId: String?,
|
recoveryKey: BackupRecoveryKey, roomId: String?,
|
||||||
sessionId: String?,
|
sessionId: String?,
|
||||||
stepProgressListener: StepProgressListener?): ImportRoomKeysResult
|
stepProgressListener: StepProgressListener?): ImportRoomKeysResult
|
||||||
|
|
||||||
|
@ -194,10 +193,10 @@ interface KeysBackupService {
|
||||||
val state: KeysBackupState
|
val state: KeysBackupState
|
||||||
|
|
||||||
// For gossiping
|
// For gossiping
|
||||||
fun saveBackupRecoveryKey(recoveryKey: String?, version: String?)
|
fun saveBackupRecoveryKey(recoveryKey: BackupRecoveryKey?, version: String?)
|
||||||
suspend fun getKeyBackupRecoveryKeyInfo(): SavedKeyBackupKeyInfo?
|
suspend fun getKeyBackupRecoveryKeyInfo(): SavedKeyBackupKeyInfo?
|
||||||
|
|
||||||
suspend fun isValidRecoveryKeyForCurrentVersion(recoveryKey: String): Boolean
|
suspend fun isValidRecoveryKeyForCurrentVersion(recoveryKey: BackupRecoveryKey): Boolean
|
||||||
|
|
||||||
fun computePrivateKey(passphrase: String,
|
fun computePrivateKey(passphrase: String,
|
||||||
privateKeySalt: String,
|
privateKeySalt: String,
|
||||||
|
|
|
@ -31,7 +31,7 @@ data class MegolmBackupCreationInfo(
|
||||||
val authData: MegolmBackupAuthData,
|
val authData: MegolmBackupAuthData,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Base58 recovery key.
|
* The recovery key.
|
||||||
*/
|
*/
|
||||||
val recoveryKey: String
|
val recoveryKey: BackupRecoveryKey
|
||||||
)
|
)
|
||||||
|
|
|
@ -17,6 +17,6 @@
|
||||||
package org.matrix.android.sdk.api.session.crypto.keysbackup
|
package org.matrix.android.sdk.api.session.crypto.keysbackup
|
||||||
|
|
||||||
data class SavedKeyBackupKeyInfo(
|
data class SavedKeyBackupKeyInfo(
|
||||||
val recoveryKey: String,
|
val recoveryKey: BackupRecoveryKey,
|
||||||
val version: String
|
val version: String
|
||||||
)
|
)
|
||||||
|
|
|
@ -20,10 +20,9 @@ import dagger.Lazy
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import org.matrix.android.sdk.api.MatrixCoroutineDispatchers
|
import org.matrix.android.sdk.api.MatrixCoroutineDispatchers
|
||||||
import org.matrix.android.sdk.api.logger.LoggerTag
|
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.KeysVersionResult
|
||||||
import org.matrix.android.sdk.api.session.crypto.keysbackup.SavedKeyBackupKeyInfo
|
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.keysbackup.RustKeyBackupService
|
||||||
import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore
|
import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore
|
||||||
import org.matrix.android.sdk.internal.util.time.Clock
|
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
|
(now - lastTry.timestamp) > MIN_TRY_BACKUP_PERIOD_MILLIS
|
||||||
|
|
||||||
if (!shouldQuery) return false
|
if (!shouldQuery) return false
|
||||||
|
val recoveryKey = savedKeyBackupKeyInfo?.recoveryKey ?: return false
|
||||||
val successfullyImported = withContext(coroutineDispatchers.io) {
|
val successfullyImported = withContext(coroutineDispatchers.io) {
|
||||||
try {
|
try {
|
||||||
keysBackupService.get().restoreKeysWithRecoveryKey(
|
keysBackupService.get().restoreKeysWithRecoveryKey(
|
||||||
currentVersion,
|
currentVersion,
|
||||||
savedKeyBackupKeyInfo?.recoveryKey ?: "",
|
recoveryKey,
|
||||||
roomId,
|
roomId,
|
||||||
sessionId,
|
sessionId,
|
||||||
null,
|
null,
|
||||||
|
|
|
@ -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.failure.MatrixError
|
||||||
import org.matrix.android.sdk.api.listeners.ProgressListener
|
import org.matrix.android.sdk.api.listeners.ProgressListener
|
||||||
import org.matrix.android.sdk.api.listeners.StepProgressListener
|
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.KeysBackupLastVersionResult
|
||||||
import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupService
|
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.KeysBackupState
|
||||||
|
@ -60,7 +61,6 @@ import org.matrix.android.sdk.internal.session.SessionScope
|
||||||
import org.matrix.android.sdk.internal.util.JsonCanonicalizer
|
import org.matrix.android.sdk.internal.util.JsonCanonicalizer
|
||||||
import org.matrix.olm.OlmException
|
import org.matrix.olm.OlmException
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import uniffi.olm.BackupRecoveryKey
|
|
||||||
import uniffi.olm.Request
|
import uniffi.olm.Request
|
||||||
import uniffi.olm.RequestType
|
import uniffi.olm.RequestType
|
||||||
import java.security.InvalidParameterException
|
import java.security.InvalidParameterException
|
||||||
|
@ -150,7 +150,7 @@ internal class RustKeyBackupService @Inject constructor(
|
||||||
MegolmBackupCreationInfo(
|
MegolmBackupCreationInfo(
|
||||||
algorithm = publicKey.backupAlgorithm,
|
algorithm = publicKey.backupAlgorithm,
|
||||||
authData = signedMegolmBackupAuthData,
|
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 {
|
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(
|
val body = UpdateKeysBackupVersionBody(
|
||||||
algorithm = keysBackupVersion.algorithm,
|
algorithm = keysBackupVersion.algorithm,
|
||||||
authData = newAuthData.copy(signatures = newSignatures).toJsonDict(),
|
authData = newAuthData.copy(signatures = newSignatures).toJsonDict(),
|
||||||
version = keysBackupVersion.version)
|
version = keysBackupVersion.version
|
||||||
|
)
|
||||||
|
|
||||||
withContext(coroutineDispatchers.io) {
|
withContext(coroutineDispatchers.io) {
|
||||||
sender.updateBackup(keysBackupVersion, body)
|
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}")
|
Timber.v("trustKeysBackupVersionWithRecoveryKey: version ${keysBackupVersion.version}")
|
||||||
withContext(coroutineDispatchers.crypto) {
|
withContext(coroutineDispatchers.crypto) {
|
||||||
// This is ~nowhere mentioned, the string here is actually a base58 encoded key.
|
// 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
|
// 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.
|
// base58 encoding and the same method seems to be used here.
|
||||||
val key = BackupRecoveryKey.fromBase58(recoveryKey)
|
checkRecoveryKey(recoveryKey, keysBackupVersion)
|
||||||
checkRecoveryKey(key, keysBackupVersion)
|
|
||||||
trustKeysBackupVersion(keysBackupVersion, true)
|
trustKeysBackupVersion(keysBackupVersion, true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -378,7 +380,7 @@ internal class RustKeyBackupService @Inject constructor(
|
||||||
withContext(coroutineDispatchers.crypto) {
|
withContext(coroutineDispatchers.crypto) {
|
||||||
try {
|
try {
|
||||||
val version = sender.getKeyBackupLastVersion()?.toKeysVersionResult()
|
val version = sender.getKeyBackupLastVersion()?.toKeysVersionResult()
|
||||||
|
Timber.v("Keybackup version: $version")
|
||||||
if (version != null) {
|
if (version != null) {
|
||||||
val key = BackupRecoveryKey.fromBase64(secret)
|
val key = BackupRecoveryKey.fromBase64(secret)
|
||||||
if (isValidRecoveryKey(key, version)) {
|
if (isValidRecoveryKey(key, version)) {
|
||||||
|
@ -395,7 +397,9 @@ internal class RustKeyBackupService @Inject constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// we can save, it's valid
|
// we can save, it's valid
|
||||||
saveBackupRecoveryKey(key.toBase64(), version.version)
|
saveBackupRecoveryKey(key, version.version)
|
||||||
|
} else {
|
||||||
|
Timber.d("Invalid recovery key")
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Timber.e("onSecretKeyGossip: Failed to import backup recovery key, no backup version was found on the server")
|
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
|
// Save for next time and for gossiping
|
||||||
saveBackupRecoveryKey(recoveryKey.toBase64(), keysVersionResult.version)
|
saveBackupRecoveryKey(recoveryKey, keysVersionResult.version)
|
||||||
}
|
}
|
||||||
|
|
||||||
withContext(coroutineDispatchers.main) {
|
withContext(coroutineDispatchers.main) {
|
||||||
|
@ -519,14 +523,18 @@ internal class RustKeyBackupService @Inject constructor(
|
||||||
stepProgressListener?.onStepProgress(stepProgress)
|
stepProgressListener?.onStepProgress(stepProgress)
|
||||||
}
|
}
|
||||||
|
|
||||||
Timber.v("restoreKeysWithRecoveryKey: Decrypted ${sessionsData.size} keys out" +
|
Timber.v(
|
||||||
" of ${data.roomIdToRoomKeysBackupData.size} rooms from the backup store on the homeserver")
|
"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
|
// Do not trigger a backup for them if they come from the backup version we are using
|
||||||
val backUp = keysVersionResult.version != keysBackupVersion?.version
|
val backUp = keysVersionResult.version != keysBackupVersion?.version
|
||||||
if (backUp) {
|
if (backUp) {
|
||||||
Timber.v("restoreKeysWithRecoveryKey: Those keys will be backed up" +
|
Timber.v(
|
||||||
" to backup version: ${keysBackupVersion?.version}")
|
"restoreKeysWithRecoveryKey: Those keys will be backed up" +
|
||||||
|
" to backup version: ${keysBackupVersion?.version}"
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Import them into the crypto store
|
// Import them into the crypto store
|
||||||
|
@ -557,15 +565,12 @@ internal class RustKeyBackupService @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun restoreKeysWithRecoveryKey(keysVersionResult: KeysVersionResult,
|
override suspend fun restoreKeysWithRecoveryKey(keysVersionResult: KeysVersionResult,
|
||||||
recoveryKey: String,
|
recoveryKey: BackupRecoveryKey,
|
||||||
roomId: String?,
|
roomId: String?,
|
||||||
sessionId: String?,
|
sessionId: String?,
|
||||||
stepProgressListener: StepProgressListener?): ImportRoomKeysResult {
|
stepProgressListener: StepProgressListener?): ImportRoomKeysResult {
|
||||||
Timber.v("restoreKeysWithRecoveryKey: From backup version: ${keysVersionResult.version}")
|
Timber.v("restoreKeysWithRecoveryKey: From backup version: ${keysVersionResult.version}")
|
||||||
|
return restoreBackup(keysVersionResult, recoveryKey, roomId, sessionId, stepProgressListener)
|
||||||
val key = BackupRecoveryKey.fromBase58(recoveryKey)
|
|
||||||
|
|
||||||
return restoreBackup(keysVersionResult, key, roomId, sessionId, stepProgressListener)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun restoreKeyBackupWithPassword(keysBackupVersion: KeysVersionResult,
|
override suspend fun restoreKeyBackupWithPassword(keysBackupVersion: KeysVersionResult,
|
||||||
|
@ -577,7 +582,6 @@ internal class RustKeyBackupService @Inject constructor(
|
||||||
val recoveryKey = withContext(coroutineDispatchers.crypto) {
|
val recoveryKey = withContext(coroutineDispatchers.crypto) {
|
||||||
recoveryKeyFromPassword(password, keysBackupVersion)
|
recoveryKeyFromPassword(password, keysBackupVersion)
|
||||||
}
|
}
|
||||||
|
|
||||||
return restoreBackup(keysBackupVersion, recoveryKey, roomId, sessionId, stepProgressListener)
|
return restoreBackup(keysBackupVersion, recoveryKey, roomId, sessionId, stepProgressListener)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -703,16 +707,15 @@ internal class RustKeyBackupService @Inject constructor(
|
||||||
private fun isValidRecoveryKey(recoveryKey: BackupRecoveryKey, version: KeysVersionResult): Boolean {
|
private fun isValidRecoveryKey(recoveryKey: BackupRecoveryKey, version: KeysVersionResult): Boolean {
|
||||||
val publicKey = recoveryKey.megolmV1PublicKey().publicKey
|
val publicKey = recoveryKey.megolmV1PublicKey().publicKey
|
||||||
val authData = getMegolmBackupAuthData(version) ?: return false
|
val authData = getMegolmBackupAuthData(version) ?: return false
|
||||||
|
Timber.v("recoveryKey.megolmV1PublicKey().publicKey $publicKey == getMegolmBackupAuthData(version).publicKey ${authData.publicKey}")
|
||||||
return authData.publicKey == publicKey
|
return authData.publicKey == publicKey
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun isValidRecoveryKeyForCurrentVersion(recoveryKey: String): Boolean {
|
override suspend fun isValidRecoveryKeyForCurrentVersion(recoveryKey: BackupRecoveryKey): Boolean {
|
||||||
return withContext(coroutineDispatchers.crypto) {
|
return withContext(coroutineDispatchers.crypto) {
|
||||||
val keysBackupVersion = keysBackupVersion ?: return@withContext false
|
val keysBackupVersion = keysBackupVersion ?: return@withContext false
|
||||||
|
|
||||||
val key = BackupRecoveryKey.fromBase64(recoveryKey)
|
|
||||||
try {
|
try {
|
||||||
isValidRecoveryKey(key, keysBackupVersion)
|
isValidRecoveryKey(recoveryKey, keysBackupVersion)
|
||||||
} catch (failure: Throwable) {
|
} catch (failure: Throwable) {
|
||||||
Timber.i("isValidRecoveryKeyForCurrentVersion: Invalid recovery key")
|
Timber.i("isValidRecoveryKeyForCurrentVersion: Invalid recovery key")
|
||||||
false
|
false
|
||||||
|
@ -726,7 +729,9 @@ internal class RustKeyBackupService @Inject constructor(
|
||||||
|
|
||||||
override suspend fun getKeyBackupRecoveryKeyInfo(): SavedKeyBackupKeyInfo? {
|
override suspend fun getKeyBackupRecoveryKeyInfo(): SavedKeyBackupKeyInfo? {
|
||||||
val info = olmMachine.getBackupKeys() ?: return null
|
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)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -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.CryptoCrossSigningKey
|
||||||
import org.matrix.android.sdk.api.session.crypto.crosssigning.MXCrossSigningInfo
|
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.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.keysbackup.SavedKeyBackupKeyInfo
|
||||||
import org.matrix.android.sdk.api.session.crypto.model.AuditTrail
|
import org.matrix.android.sdk.api.session.crypto.model.AuditTrail
|
||||||
import org.matrix.android.sdk.api.session.crypto.model.CryptoDeviceInfo
|
import org.matrix.android.sdk.api.session.crypto.model.CryptoDeviceInfo
|
||||||
|
@ -469,7 +470,8 @@ internal class RealmCryptoStore @Inject constructor(
|
||||||
val key = it.keyBackupRecoveryKey
|
val key = it.keyBackupRecoveryKey
|
||||||
val version = it.keyBackupRecoveryKeyVersion
|
val version = it.keyBackupRecoveryKeyVersion
|
||||||
if (!key.isNullOrBlank() && !version.isNullOrBlank()) {
|
if (!key.isNullOrBlank() && !version.isNullOrBlank()) {
|
||||||
SavedKeyBackupKeyInfo(recoveryKey = key, version = version)
|
val backupRecoveryKey = BackupRecoveryKey.fromBase58(key)
|
||||||
|
SavedKeyBackupKeyInfo(recoveryKey = backupRecoveryKey, version = version)
|
||||||
} else {
|
} else {
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
|
|
|
@ -520,10 +520,9 @@ internal class RoomSyncHandler @Inject constructor(
|
||||||
|
|
||||||
private fun decryptIfNeeded(event: Event, roomId: String) {
|
private fun decryptIfNeeded(event: Event, roomId: String) {
|
||||||
try {
|
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
|
// note: runBlocking should be used here while we are in realm single thread executor, to avoid thread switching
|
||||||
val result = runBlocking {
|
val result = runBlocking {
|
||||||
cryptoService.decryptEvent(event.copy(roomId = roomId), "")
|
cryptoService.decryptEvent(event, "")
|
||||||
}
|
}
|
||||||
event.mxDecryptionResult = OlmDecryptionResult(
|
event.mxDecryptionResult = OlmDecryptionResult(
|
||||||
payload = result.clearEvent,
|
payload = result.clearEvent,
|
||||||
|
|
|
@ -23,6 +23,7 @@ import im.vector.app.core.platform.WaitingViewData
|
||||||
import im.vector.app.core.resources.StringProvider
|
import im.vector.app.core.resources.StringProvider
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
import org.matrix.android.sdk.api.session.crypto.keysbackup.BackupRecoveryKey
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class KeysBackupRestoreFromKeyViewModel @Inject constructor(
|
class KeysBackupRestoreFromKeyViewModel @Inject constructor(
|
||||||
|
@ -42,7 +43,7 @@ class KeysBackupRestoreFromKeyViewModel @Inject constructor(
|
||||||
sharedViewModel.loadingEvent.postValue(WaitingViewData(stringProvider.getString(R.string.loading)))
|
sharedViewModel.loadingEvent.postValue(WaitingViewData(stringProvider.getString(R.string.loading)))
|
||||||
recoveryCodeErrorText.value = null
|
recoveryCodeErrorText.value = null
|
||||||
viewModelScope.launch(Dispatchers.IO) {
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
val recoveryKey = recoveryCode.value!!
|
val recoveryKey = BackupRecoveryKey.fromBase58(recoveryCode.value!!)
|
||||||
try {
|
try {
|
||||||
sharedViewModel.recoverUsingBackupRecoveryKey(recoveryKey)
|
sharedViewModel.recoverUsingBackupRecoveryKey(recoveryKey)
|
||||||
} catch (failure: Throwable) {
|
} catch (failure: Throwable) {
|
||||||
|
|
|
@ -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.listeners.StepProgressListener
|
||||||
import org.matrix.android.sdk.api.session.Session
|
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.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.KeysBackupService
|
||||||
import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysVersionResult
|
import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysVersionResult
|
||||||
import org.matrix.android.sdk.api.session.crypto.keysbackup.computeRecoveryKey
|
import org.matrix.android.sdk.api.session.crypto.keysbackup.computeRecoveryKey
|
||||||
|
@ -88,7 +89,7 @@ class KeysBackupRestoreSharedViewModel @Inject constructor(
|
||||||
private val progressObserver = object : StepProgressListener {
|
private val progressObserver = object : StepProgressListener {
|
||||||
override fun onStepProgress(step: StepProgressListener.Step) {
|
override fun onStepProgress(step: StepProgressListener.Step) {
|
||||||
when (step) {
|
when (step) {
|
||||||
is StepProgressListener.Step.ComputingKey -> {
|
is StepProgressListener.Step.ComputingKey -> {
|
||||||
loadingEvent.postValue(
|
loadingEvent.postValue(
|
||||||
WaitingViewData(
|
WaitingViewData(
|
||||||
stringProvider.getString(R.string.keys_backup_restoring_waiting_message) +
|
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}")
|
Timber.d("backupKeys.ImportingKey.progress: ${step.progress}")
|
||||||
// Progress 0 can take a while, display an indeterminate progress in this case
|
// Progress 0 can take a while, display an indeterminate progress in this case
|
||||||
if (step.progress == 0) {
|
if (step.progress == 0) {
|
||||||
|
@ -131,14 +132,22 @@ class KeysBackupRestoreSharedViewModel @Inject constructor(
|
||||||
}
|
}
|
||||||
is StepProgressListener.Step.DecryptingKey -> {
|
is StepProgressListener.Step.DecryptingKey -> {
|
||||||
if (step.progress == 0) {
|
if (step.progress == 0) {
|
||||||
loadingEvent.postValue(WaitingViewData(stringProvider.getString(R.string.keys_backup_restoring_waiting_message) +
|
loadingEvent.postValue(
|
||||||
"\n" + stringProvider.getString(R.string.keys_backup_restoring_decrypting_keys_waiting_message),
|
WaitingViewData(
|
||||||
isIndeterminate = true))
|
stringProvider.getString(R.string.keys_backup_restoring_waiting_message) +
|
||||||
|
"\n" + stringProvider.getString(R.string.keys_backup_restoring_decrypting_keys_waiting_message),
|
||||||
|
isIndeterminate = true
|
||||||
|
)
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
loadingEvent.postValue(WaitingViewData(stringProvider.getString(R.string.keys_backup_restoring_waiting_message) +
|
loadingEvent.postValue(
|
||||||
"\n" + stringProvider.getString(R.string.keys_backup_restoring_decrypting_keys_waiting_message),
|
WaitingViewData(
|
||||||
step.progress,
|
stringProvider.getString(R.string.keys_backup_restoring_waiting_message) +
|
||||||
step.total))
|
"\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!!
|
// Go and use it!!
|
||||||
try {
|
try {
|
||||||
recoverUsingBackupRecoveryKey(computeRecoveryKey(savedSecret.recoveryKey.fromBase64()), version)
|
recoverUsingBackupRecoveryKey(savedSecret.recoveryKey, version)
|
||||||
} catch (failure: Throwable) {
|
} catch (failure: Throwable) {
|
||||||
Timber.e(failure, "## recoverUsingBackupRecoveryKey FAILED")
|
Timber.e(failure, "## recoverUsingBackupRecoveryKey FAILED")
|
||||||
keySourceModel.postValue(
|
keySourceModel.postValue(
|
||||||
|
@ -212,7 +221,9 @@ class KeysBackupRestoreSharedViewModel @Inject constructor(
|
||||||
|
|
||||||
viewModelScope.launch(Dispatchers.IO) {
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
try {
|
try {
|
||||||
recoverUsingBackupRecoveryKey(computeRecoveryKey(secret.fromBase64()))
|
val computedRecoveryKey = computeRecoveryKey(secret.fromBase64())
|
||||||
|
val backupRecoveryKey = BackupRecoveryKey.fromBase58(computedRecoveryKey)
|
||||||
|
recoverUsingBackupRecoveryKey(backupRecoveryKey)
|
||||||
} catch (failure: Throwable) {
|
} catch (failure: Throwable) {
|
||||||
_navigateEvent.postValue(
|
_navigateEvent.postValue(
|
||||||
LiveEvent(NAVIGATE_FAILED_TO_LOAD_4S)
|
LiveEvent(NAVIGATE_FAILED_TO_LOAD_4S)
|
||||||
|
@ -234,7 +245,8 @@ class KeysBackupRestoreSharedViewModel @Inject constructor(
|
||||||
loadingEvent.postValue(WaitingViewData(stringProvider.getString(R.string.loading)))
|
loadingEvent.postValue(WaitingViewData(stringProvider.getString(R.string.loading)))
|
||||||
|
|
||||||
try {
|
try {
|
||||||
val result = keysBackup.restoreKeyBackupWithPassword(keyVersion,
|
val result = keysBackup.restoreKeyBackupWithPassword(
|
||||||
|
keyVersion,
|
||||||
passphrase,
|
passphrase,
|
||||||
null,
|
null,
|
||||||
session.myUserId,
|
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()
|
val keysBackup = session.cryptoService().keysBackupService()
|
||||||
// This is badddddd
|
// This is badddddd
|
||||||
val version = keyVersion ?: keyVersionResult.value ?: return
|
val version = keyVersion ?: keyVersionResult.value ?: return
|
||||||
|
@ -257,7 +269,8 @@ class KeysBackupRestoreSharedViewModel @Inject constructor(
|
||||||
loadingEvent.postValue(WaitingViewData(stringProvider.getString(R.string.loading)))
|
loadingEvent.postValue(WaitingViewData(stringProvider.getString(R.string.loading)))
|
||||||
|
|
||||||
try {
|
try {
|
||||||
val result = keysBackup.restoreKeysWithRecoveryKey(version,
|
val result = keysBackup.restoreKeysWithRecoveryKey(
|
||||||
|
version,
|
||||||
recoveryKey,
|
recoveryKey,
|
||||||
null,
|
null,
|
||||||
session.myUserId,
|
session.myUserId,
|
||||||
|
|
|
@ -27,6 +27,7 @@ import im.vector.app.core.time.Clock
|
||||||
import im.vector.app.core.utils.LiveEvent
|
import im.vector.app.core.utils.LiveEvent
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import org.matrix.android.sdk.api.session.Session
|
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.KeysBackupService
|
||||||
import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysVersion
|
import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysVersion
|
||||||
import org.matrix.android.sdk.api.session.crypto.keysbackup.MegolmBackupCreationInfo
|
import org.matrix.android.sdk.api.session.crypto.keysbackup.MegolmBackupCreationInfo
|
||||||
|
@ -71,7 +72,7 @@ class KeysBackupSetupSharedViewModel @Inject constructor(
|
||||||
// Step 3
|
// Step 3
|
||||||
// Var to ignore events from previous request(s) to generate a recovery key
|
// Var to ignore events from previous request(s) to generate a recovery key
|
||||||
private var currentRequestId: MutableLiveData<Long> = MutableLiveData()
|
private var currentRequestId: MutableLiveData<Long> = MutableLiveData()
|
||||||
var recoveryKey: MutableLiveData<String?> = MutableLiveData(null)
|
var recoveryKey: MutableLiveData<BackupRecoveryKey?> = MutableLiveData(null)
|
||||||
var prepareRecoverFailError: MutableLiveData<Throwable?> = MutableLiveData(null)
|
var prepareRecoverFailError: MutableLiveData<Throwable?> = MutableLiveData(null)
|
||||||
var megolmBackupCreationInfo: MegolmBackupCreationInfo? = null
|
var megolmBackupCreationInfo: MegolmBackupCreationInfo? = null
|
||||||
var copyHasBeenMade = false
|
var copyHasBeenMade = false
|
||||||
|
|
|
@ -66,7 +66,7 @@ class KeysBackupSetupStep3Fragment @Inject constructor() : VectorBaseFragment<Fr
|
||||||
views.keysBackupSetupStep3Label2.text = getString(R.string.keys_backup_setup_step3_text_line2_no_passphrase)
|
views.keysBackupSetupStep3Label2.text = getString(R.string.keys_backup_setup_step3_text_line2_no_passphrase)
|
||||||
views.keysBackupSetupStep3FinishButton.text = getString(R.string.keys_backup_setup_step3_button_title_no_passphrase)
|
views.keysBackupSetupStep3FinishButton.text = getString(R.string.keys_backup_setup_step3_button_title_no_passphrase)
|
||||||
|
|
||||||
views.keysBackupSetupStep3RecoveryKeyText.text = viewModel.recoveryKey.value!!
|
views.keysBackupSetupStep3RecoveryKeyText.text = viewModel.recoveryKey.value!!.toBase58()
|
||||||
.replace(" ", "")
|
.replace(" ", "")
|
||||||
.chunked(16)
|
.chunked(16)
|
||||||
.joinToString("\n") {
|
.joinToString("\n") {
|
||||||
|
@ -114,7 +114,8 @@ class KeysBackupSetupStep3Fragment @Inject constructor() : VectorBaseFragment<Fr
|
||||||
} else {
|
} else {
|
||||||
dialog.findViewById<TextView>(R.id.keys_backup_recovery_key_text)?.let {
|
dialog.findViewById<TextView>(R.id.keys_backup_recovery_key_text)?.let {
|
||||||
it.isVisible = true
|
it.isVisible = true
|
||||||
it.text = recoveryKey.replace(" ", "")
|
it.text = recoveryKey.toBase58()
|
||||||
|
.replace(" ", "")
|
||||||
.chunked(16)
|
.chunked(16)
|
||||||
.joinToString("\n") {
|
.joinToString("\n") {
|
||||||
it
|
it
|
||||||
|
@ -123,7 +124,7 @@ class KeysBackupSetupStep3Fragment @Inject constructor() : VectorBaseFragment<Fr
|
||||||
}
|
}
|
||||||
|
|
||||||
it.debouncedClicks {
|
it.debouncedClicks {
|
||||||
copyToClipboard(requireActivity(), recoveryKey)
|
copyToClipboard(requireActivity(), recoveryKey.toBase58())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -145,7 +146,7 @@ class KeysBackupSetupStep3Fragment @Inject constructor() : VectorBaseFragment<Fr
|
||||||
fragment = this,
|
fragment = this,
|
||||||
activityResultLauncher = null,
|
activityResultLauncher = null,
|
||||||
chooserTitle = context?.getString(R.string.keys_backup_setup_step3_share_intent_chooser_title),
|
chooserTitle = context?.getString(R.string.keys_backup_setup_step3_share_intent_chooser_title),
|
||||||
text = recoveryKey,
|
text = recoveryKey.toBase58(),
|
||||||
subject = context?.getString(R.string.recovery_key)
|
subject = context?.getString(R.string.recovery_key)
|
||||||
)
|
)
|
||||||
viewModel.copyHasBeenMade = true
|
viewModel.copyHasBeenMade = true
|
||||||
|
@ -159,7 +160,7 @@ class KeysBackupSetupStep3Fragment @Inject constructor() : VectorBaseFragment<Fr
|
||||||
viewModel.recoveryKey.value?.let {
|
viewModel.recoveryKey.value?.let {
|
||||||
viewModel.copyHasBeenMade = true
|
viewModel.copyHasBeenMade = true
|
||||||
|
|
||||||
copyToClipboard(requireActivity(), it)
|
copyToClipboard(requireActivity(), it.toBase58())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -202,7 +203,7 @@ class KeysBackupSetupStep3Fragment @Inject constructor() : VectorBaseFragment<Fr
|
||||||
val uri = activityRessult.data?.data ?: return@registerStartForActivityResult
|
val uri = activityRessult.data?.data ?: return@registerStartForActivityResult
|
||||||
if (activityRessult.resultCode == Activity.RESULT_OK) {
|
if (activityRessult.resultCode == Activity.RESULT_OK) {
|
||||||
viewModel.recoveryKey.value?.let {
|
viewModel.recoveryKey.value?.let {
|
||||||
exportRecoveryKeyToFile(uri, it)
|
exportRecoveryKeyToFile(uri, it.toBase58())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@ import im.vector.app.core.resources.StringProvider
|
||||||
import org.matrix.android.sdk.api.listeners.ProgressListener
|
import org.matrix.android.sdk.api.listeners.ProgressListener
|
||||||
import org.matrix.android.sdk.api.session.Session
|
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.KEYBACKUP_SECRET_SSSS_NAME
|
||||||
|
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.computeRecoveryKey
|
||||||
import org.matrix.android.sdk.api.session.crypto.keysbackup.extractCurveKeyFromRecoveryKey
|
import org.matrix.android.sdk.api.session.crypto.keysbackup.extractCurveKeyFromRecoveryKey
|
||||||
import org.matrix.android.sdk.api.session.securestorage.EmptyKeySigner
|
import org.matrix.android.sdk.api.session.securestorage.EmptyKeySigner
|
||||||
|
@ -91,8 +92,8 @@ class BackupToQuadSMigrationTask @Inject constructor(
|
||||||
|
|
||||||
reportProgress(params, R.string.bootstrap_progress_compute_curve_key)
|
reportProgress(params, R.string.bootstrap_progress_compute_curve_key)
|
||||||
val recoveryKey = computeRecoveryKey(curveKey)
|
val recoveryKey = computeRecoveryKey(curveKey)
|
||||||
|
val backupRecoveryKey = BackupRecoveryKey.fromBase58(recoveryKey)
|
||||||
val isValid = keysBackupService.isValidRecoveryKeyForCurrentVersion(recoveryKey)
|
val isValid = keysBackupService.isValidRecoveryKeyForCurrentVersion(backupRecoveryKey)
|
||||||
|
|
||||||
if (!isValid) return Result.InvalidRecoverySecret
|
if (!isValid) return Result.InvalidRecoverySecret
|
||||||
|
|
||||||
|
@ -143,7 +144,7 @@ class BackupToQuadSMigrationTask @Inject constructor(
|
||||||
)
|
)
|
||||||
|
|
||||||
// save for gossiping
|
// save for gossiping
|
||||||
keysBackupService.saveBackupRecoveryKey(recoveryKey, version.version)
|
keysBackupService.saveBackupRecoveryKey(backupRecoveryKey, version.version)
|
||||||
// It's not a good idea to download the full backup, it might take very long
|
// It's not a good idea to download the full backup, it might take very long
|
||||||
// and use a lot of resources
|
// and use a lot of resources
|
||||||
return Result.Success
|
return Result.Success
|
||||||
|
|
|
@ -236,7 +236,7 @@ class BootstrapCrossSigningTask @Inject constructor(
|
||||||
Timber.d("## BootstrapCrossSigningTask: Creating 4S - Save megolm backup key for gossiping")
|
Timber.d("## BootstrapCrossSigningTask: Creating 4S - Save megolm backup key for gossiping")
|
||||||
session.cryptoService().keysBackupService().saveBackupRecoveryKey(creationInfo.recoveryKey, version = version.version)
|
session.cryptoService().keysBackupService().saveBackupRecoveryKey(creationInfo.recoveryKey, version = version.version)
|
||||||
|
|
||||||
extractCurveKeyFromRecoveryKey(creationInfo.recoveryKey)?.toBase64NoPadding()?.let { secret ->
|
extractCurveKeyFromRecoveryKey(creationInfo.recoveryKey.toBase58())?.toBase64NoPadding()?.let { secret ->
|
||||||
ssssService.storeSecret(
|
ssssService.storeSecret(
|
||||||
KEYBACKUP_SECRET_SSSS_NAME,
|
KEYBACKUP_SECRET_SSSS_NAME,
|
||||||
secret,
|
secret,
|
||||||
|
@ -251,7 +251,7 @@ class BootstrapCrossSigningTask @Inject constructor(
|
||||||
val isValid = session.cryptoService().keysBackupService().isValidRecoveryKeyForCurrentVersion(knownMegolmSecret!!.recoveryKey)
|
val isValid = session.cryptoService().keysBackupService().isValidRecoveryKeyForCurrentVersion(knownMegolmSecret!!.recoveryKey)
|
||||||
if (isValid) {
|
if (isValid) {
|
||||||
Timber.d("## BootstrapCrossSigningTask: Creating 4S - Megolm key valid and known")
|
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(
|
ssssService.storeSecret(
|
||||||
KEYBACKUP_SECRET_SSSS_NAME,
|
KEYBACKUP_SECRET_SSSS_NAME,
|
||||||
secret,
|
secret,
|
||||||
|
|
|
@ -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.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.USER_SIGNING_KEY_SSSS_NAME
|
||||||
import org.matrix.android.sdk.api.session.crypto.crosssigning.isVerified
|
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.computeRecoveryKey
|
||||||
import org.matrix.android.sdk.api.session.crypto.keysbackup.toKeysVersionResult
|
import org.matrix.android.sdk.api.session.crypto.keysbackup.toKeysVersionResult
|
||||||
import org.matrix.android.sdk.api.session.crypto.verification.CancelCode
|
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 version = session.cryptoService().keysBackupService().getCurrentVersion()?.toKeysVersionResult() ?: return@launch
|
||||||
|
|
||||||
val recoveryKey = computeRecoveryKey(secret.fromBase64())
|
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) {
|
if (isValid) {
|
||||||
session.cryptoService().keysBackupService().saveBackupRecoveryKey(recoveryKey, version.version)
|
session.cryptoService().keysBackupService().saveBackupRecoveryKey(backupRecoveryKey, version.version)
|
||||||
}
|
}
|
||||||
session.cryptoService().keysBackupService().trustKeysBackupVersion(version, true)
|
session.cryptoService().keysBackupService().trustKeysBackupVersion(version, true)
|
||||||
} catch (failure: Throwable) {
|
} catch (failure: Throwable) {
|
||||||
|
@ -502,6 +504,7 @@ class VerificationBottomSheetViewModel @AssistedInject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun transactionUpdated(tx: VerificationTransaction) = withState { state ->
|
override fun transactionUpdated(tx: VerificationTransaction) = withState { state ->
|
||||||
|
Timber.v("transactionUpdated: $tx")
|
||||||
handleTransactionUpdate(state, tx)
|
handleTransactionUpdate(state, tx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -510,7 +513,7 @@ class VerificationBottomSheetViewModel @AssistedInject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun verificationRequestUpdated(pr: PendingVerificationRequest) = withState { state ->
|
override fun verificationRequestUpdated(pr: PendingVerificationRequest) = withState { state ->
|
||||||
|
Timber.v("VerificationRequestUpdated: $pr")
|
||||||
if (state.selfVerificationMode && state.pendingRequest.invoke() == null && state.transactionId == null) {
|
if (state.selfVerificationMode && state.pendingRequest.invoke() == null && state.transactionId == null) {
|
||||||
// is this an incoming with that user
|
// is this an incoming with that user
|
||||||
if (pr.isIncoming && pr.otherUserId == state.otherUserMxItem?.id) {
|
if (pr.isIncoming && pr.otherUserId == state.otherUserMxItem?.id) {
|
||||||
|
|
Loading…
Reference in a new issue