Fixes #1214
This commit is contained in:
parent
3968bb3488
commit
34dec64d9c
|
@ -14,6 +14,7 @@ Improvements 🙌:
|
|||
- Cross-Signing | Setup key backup as part of SSSS bootstrapping (#1201)
|
||||
- Cross-Signing | Gossip key backup recovery key (#1200)
|
||||
- Show room encryption status as a bubble tile (#1078)
|
||||
- Cross-Signing | Restore history after recover from passphrase (#1214)
|
||||
|
||||
Bugfix 🐛:
|
||||
- Missing avatar/displayname after verification request message (#841)
|
||||
|
|
|
@ -37,6 +37,7 @@ import kotlinx.coroutines.Dispatchers
|
|||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import timber.log.Timber
|
||||
import java.io.ByteArrayOutputStream
|
||||
|
||||
data class SharedSecureStorageViewState(
|
||||
|
@ -117,11 +118,15 @@ class SharedSecureStorageViewModel @AssistedInject constructor(
|
|||
withContext(Dispatchers.IO) {
|
||||
args.requestedSecrets.forEach {
|
||||
val res = awaitCallback<String> { callback ->
|
||||
session.sharedSecretStorageService.getSecret(
|
||||
name = it,
|
||||
keyId = keyInfo.id,
|
||||
secretKey = keySpec,
|
||||
callback = callback)
|
||||
if (session.getAccountDataEvent(it) != null) {
|
||||
session.sharedSecretStorageService.getSecret(
|
||||
name = it,
|
||||
keyId = keyInfo.id,
|
||||
secretKey = keySpec,
|
||||
callback = callback)
|
||||
} else {
|
||||
Timber.w("## Cannot find secret $it in SSSS, skip")
|
||||
}
|
||||
}
|
||||
decryptedSecretMap[it] = res
|
||||
}
|
||||
|
|
|
@ -32,6 +32,7 @@ import com.airbnb.mvrx.MvRx
|
|||
import com.airbnb.mvrx.fragmentViewModel
|
||||
import com.airbnb.mvrx.withState
|
||||
import im.vector.matrix.android.api.session.Session
|
||||
import im.vector.matrix.android.api.session.crypto.crosssigning.KEYBACKUP_SECRET_SSSS_NAME
|
||||
import im.vector.matrix.android.api.session.crypto.crosssigning.MASTER_KEY_SSSS_NAME
|
||||
import im.vector.matrix.android.api.session.crypto.crosssigning.SELF_SIGNING_KEY_SSSS_NAME
|
||||
import im.vector.matrix.android.api.session.crypto.crosssigning.USER_SIGNING_KEY_SSSS_NAME
|
||||
|
@ -108,7 +109,7 @@ class VerificationBottomSheet : VectorBaseBottomSheetDialogFragment() {
|
|||
startActivityForResult(SharedSecureStorageActivity.newIntent(
|
||||
requireContext(),
|
||||
null, // use default key
|
||||
listOf(MASTER_KEY_SSSS_NAME, USER_SIGNING_KEY_SSSS_NAME, SELF_SIGNING_KEY_SSSS_NAME),
|
||||
listOf(MASTER_KEY_SSSS_NAME, USER_SIGNING_KEY_SSSS_NAME, SELF_SIGNING_KEY_SSSS_NAME, KEYBACKUP_SECRET_SSSS_NAME),
|
||||
SharedSecureStorageActivity.DEFAULT_RESULT_KEYSTORE_ALIAS
|
||||
), SECRET_REQUEST_CODE)
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
*/
|
||||
package im.vector.riotx.features.crypto.verification
|
||||
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.airbnb.mvrx.Async
|
||||
import com.airbnb.mvrx.Fail
|
||||
import com.airbnb.mvrx.FragmentViewModelContext
|
||||
|
@ -28,6 +29,7 @@ import com.squareup.inject.assisted.Assisted
|
|||
import com.squareup.inject.assisted.AssistedInject
|
||||
import im.vector.matrix.android.api.MatrixCallback
|
||||
import im.vector.matrix.android.api.session.Session
|
||||
import im.vector.matrix.android.api.session.crypto.crosssigning.KEYBACKUP_SECRET_SSSS_NAME
|
||||
import im.vector.matrix.android.api.session.crypto.crosssigning.MASTER_KEY_SSSS_NAME
|
||||
import im.vector.matrix.android.api.session.crypto.crosssigning.SELF_SIGNING_KEY_SSSS_NAME
|
||||
import im.vector.matrix.android.api.session.crypto.crosssigning.USER_SIGNING_KEY_SSSS_NAME
|
||||
|
@ -46,8 +48,13 @@ import im.vector.matrix.android.api.util.MatrixItem
|
|||
import im.vector.matrix.android.api.util.toMatrixItem
|
||||
import im.vector.matrix.android.internal.crypto.crosssigning.fromBase64
|
||||
import im.vector.matrix.android.internal.crypto.crosssigning.isVerified
|
||||
import im.vector.matrix.android.internal.crypto.keysbackup.model.rest.KeysVersionResult
|
||||
import im.vector.matrix.android.internal.crypto.keysbackup.util.computeRecoveryKey
|
||||
import im.vector.matrix.android.internal.crypto.model.ImportRoomKeysResult
|
||||
import im.vector.matrix.android.internal.util.awaitCallback
|
||||
import im.vector.riotx.core.extensions.exhaustive
|
||||
import im.vector.riotx.core.platform.VectorViewModel
|
||||
import kotlinx.coroutines.launch
|
||||
import timber.log.Timber
|
||||
|
||||
data class VerificationBottomSheetViewState(
|
||||
|
@ -334,40 +341,82 @@ class VerificationBottomSheetViewModel @AssistedInject constructor(
|
|||
_viewEvents.post(VerificationBottomSheetViewEvents.AccessSecretStore)
|
||||
}
|
||||
is VerificationAction.GotResultFromSsss -> {
|
||||
try {
|
||||
action.cypherData.fromBase64().inputStream().use { ins ->
|
||||
val res = session.loadSecureSecret<Map<String, String>>(ins, action.alias)
|
||||
val trustResult = session.cryptoService().crossSigningService().checkTrustFromPrivateKeys(
|
||||
res?.get(MASTER_KEY_SSSS_NAME),
|
||||
res?.get(USER_SIGNING_KEY_SSSS_NAME),
|
||||
res?.get(SELF_SIGNING_KEY_SSSS_NAME)
|
||||
)
|
||||
if (trustResult.isVerified()) {
|
||||
// Sign this device and upload the signature
|
||||
session.sessionParams.credentials.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")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
setState {
|
||||
copy(verifiedFromPrivateKeys = true)
|
||||
}
|
||||
} else {
|
||||
// POP UP something
|
||||
_viewEvents.post(VerificationBottomSheetViewEvents.ModalError("Failed to import keys"))
|
||||
}
|
||||
}
|
||||
} catch (failure: Throwable) {
|
||||
_viewEvents.post(VerificationBottomSheetViewEvents.ModalError(failure.localizedMessage))
|
||||
}
|
||||
handleSecretBackFromSSSS(action)
|
||||
}
|
||||
}.exhaustive
|
||||
}
|
||||
|
||||
private fun handleSecretBackFromSSSS(action: VerificationAction.GotResultFromSsss) {
|
||||
try {
|
||||
action.cypherData.fromBase64().inputStream().use { ins ->
|
||||
val res = session.loadSecureSecret<Map<String, String>>(ins, action.alias)
|
||||
val trustResult = session.cryptoService().crossSigningService().checkTrustFromPrivateKeys(
|
||||
res?.get(MASTER_KEY_SSSS_NAME),
|
||||
res?.get(USER_SIGNING_KEY_SSSS_NAME),
|
||||
res?.get(SELF_SIGNING_KEY_SSSS_NAME)
|
||||
)
|
||||
if (trustResult.isVerified()) {
|
||||
// Sign this device and upload the signature
|
||||
session.sessionParams.credentials.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")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
setState {
|
||||
copy(verifiedFromPrivateKeys = true)
|
||||
}
|
||||
|
||||
// try to get keybackup key
|
||||
} else {
|
||||
// POP UP something
|
||||
_viewEvents.post(VerificationBottomSheetViewEvents.ModalError("Failed to import keys"))
|
||||
}
|
||||
|
||||
// try the keybackup
|
||||
tentativeRestoreBackup(res)
|
||||
Unit
|
||||
}
|
||||
} catch (failure: Throwable) {
|
||||
_viewEvents.post(VerificationBottomSheetViewEvents.ModalError(failure.localizedMessage))
|
||||
}
|
||||
}
|
||||
|
||||
private fun tentativeRestoreBackup(res: Map<String, String>?) {
|
||||
viewModelScope.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
|
||||
|
||||
awaitCallback<ImportRoomKeysResult> {
|
||||
session.cryptoService().keysBackupService().restoreKeysWithRecoveryKey(
|
||||
version,
|
||||
computeRecoveryKey(secret.fromBase64()),
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
it
|
||||
)
|
||||
}
|
||||
|
||||
awaitCallback<Unit> {
|
||||
session.cryptoService().keysBackupService().trustKeysBackupVersion(version, true, it)
|
||||
}
|
||||
} catch (failure: Throwable) {
|
||||
// Just ignore for now
|
||||
Timber.v("## Failed to restore backup after SSSS recovery")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun transactionCreated(tx: VerificationTransaction) {
|
||||
transactionUpdated(tx)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue