Skip to content

Commit

Permalink
Secure backup is required (#989)
Browse files Browse the repository at this point in the history
  • Loading branch information
yostyle authored Jul 9, 2024
1 parent 5728e91 commit b084ce4
Show file tree
Hide file tree
Showing 13 changed files with 96 additions and 55 deletions.
1 change: 1 addition & 0 deletions changelog.d/988.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Forcer la génération du code de récupération et la sauvegarde automatique.
16 changes: 8 additions & 8 deletions library/ui-strings/src/main/res/values-fr/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1292,7 +1292,7 @@
<string name="login_signup_username_hint">Nom d’utilisateur</string>
<string name="settings_dev_tools">Outils de développement</string>
<string name="settings_account_data">Données du compte</string>
<string name="verification_cannot_access_other_session">Utiliser le Code de Récupération</string><!-- Tchap: Use custom string -->
<string name="verification_cannot_access_other_session">Vérifier avec le Code de Récupération</string><!-- Tchap: Use custom string -->
<string name="verification_use_passphrase">Si vous n’avez pas accès à un appareil existant</string> <!-- Tchap: Use custom string -->
<string name="enter_secret_storage_invalid">Impossible de trouver les secrets dans le stockage</string>
<string name="message_action_item_redact">Supprimer…</string>
Expand Down Expand Up @@ -1521,7 +1521,7 @@
<string name="disclaimer_positive_button">EN SAVOIR PLUS</string>
<string name="disclaimer_negative_button">COMPRIS</string>
<string name="disclaimer_content">L’apparence et l’organisation de votre application évoluent.\nDe nouveaux changements seront introduits progressivement pour faciliter et enrichir votre expérience.</string> <!-- Tchap: Custom string -->
<string name="disclaimer_title">Bienvenue dans la nouvelle version de Tchap !</string> <!-- Tchap: Custom string -->
<string name="disclaimer_title">Bienvenue dans la nouvelle version de ${app_name} !</string> <!-- Tchap: Custom string -->
<string name="notice_crypto_unable_to_decrypt_merged">Attente de l’historique du chiffrement</string>
<string name="crypto_error_withheld_generic">Impossible d’accéder à ce message car l’envoyeur n’a intentionnellement pas envoyé les clés</string>
<string name="crypto_error_withheld_unverified">Vous ne pouvez pas accéder à ce message car l’envoyeur n’a pas confiance en votre appareil</string> <!-- Tchap: Use custom string -->
Expand All @@ -1542,9 +1542,9 @@
<string name="power_level_edit_title">Définir le rôle</string>
<string name="secure_backup_reset_no_history">Vous redémarrerez sans aucun historique, message, appareil ou utilisateurs connus</string>
<string name="secure_backup_reset_if_you_reset_all">Si vous réinitialisez tout</string>
<string name="secure_backup_reset_all_no_other_devices">Faites uniquement ceci si vous n\'avez aucun autre appareil pouvant vérifier celui-ci.</string>
<string name="secure_backup_reset_all_no_other_devices">Uniquement si vous avez perdu votre Code et n\'avez aucun autre appareil connecté à ${app_name}.</string> <!-- Tchap: Use custom string -->
<string name="secure_backup_reset_all">Réinitialiser tout</string>
<string name="bad_passphrase_key_reset_all_action">Vous avez perdu votre Code de Récupération ? Générez-en un nouveau.</string><!-- Tchap: Use custom string -->
<string name="bad_passphrase_key_reset_all_action">Générer un nouveau Code de Récupération</string> <!-- Tchap: Use custom string -->
<string name="error_saving_media_file">Impossible d’enregistrer le fichier multimédia</string>
<string name="auth_invalid_login_deactivated_account">Ce compte a été désactivé.</string>
<string name="bootstrap_cancel_text">Si vous annulez maintenant, vous pourrez perdre les messages et données chiffrés si vous perdez accès à vos identifiants.
Expand Down Expand Up @@ -2940,12 +2940,12 @@
<string name="pill_message_from_unknown_user">Message</string>
<string name="pill_message_from_user">Message de %s</string>
<string name="encrypted_by_deleted">Chiffré par un appareil supprimé</string>
<string name="secure_backup_reset_danger_warning">Veuillez ne continuer que si vous êtes certain d’avoir perdu tous vos autres appareils et votre clé de sécurité.</string>
<string name="secure_backup_reset_all_no_other_devices_long">La réinitialisation de vos clés de vérification ne peut pas être annulé. Après la réinitialisation, vous n’aurez plus accès à vos anciens messages chiffrés, et tous les amis que vous aviez précédemment vérifiés verront des avertissement de sécurité jusqu\'à ce vous les vérifiiez à nouveau.</string>
<string name="secure_backup_reset_danger_warning">Veuillez ne continuer que si vous êtes certain d’avoir perdu tous vos autres appareils et votre Code de Récupération.</string> <!-- Tchap: Use custom string -->
<string name="secure_backup_reset_all_no_other_devices_long">La réinitialisation ne peut pas être annulée. Vous n’aurez plus accès à vos anciens messages chiffrés.</string> <!-- Tchap: Use custom string -->
<string name="verification_not_found">La demande de vérification n’a pas été trouvée. Elle a peut-être été annulée, ou prise en charge dans une autre session.</string>
<string name="verification_request_was_sent">Une demande de vérification a été envoyée. Ouvrez l’une de vos autres sessions pour accepter et commencer la vérification.</string>
<string name="verification_request_was_sent">Une demande de vérification a été envoyée. Ouvrez ${app_name} sur l’un de vos autres appareils pour accepter et commencer la vérification.</string> <!-- Tchap: Use custom string -->
<string name="_resume">Reprendre</string>
<string name="verification_verify_identity">Vérifiez votre identité pour accéder aux messages chiffrés et prouver votre identité aux autres.</string>
<string name="verification_verify_identity">Vérifiez cet appareil pour accéder à vos messages.</string> <!-- Tchap: Use custom string -->
<string name="verification_verify_with_another_device">Vérifier avec un autre appareil</string>
<string name="verification_request_waiting_for_recovery">Vérification depuis la clé ou phrase de sécurité…</string>
<string name="settings_acceptable_use_policy">Politique d’utilisation acceptable</string>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ class DebugVectorFeatures(

override fun tchapIsLabsVisible(domain: String) = vectorFeatures.tchapIsLabsVisible(domain)

override fun tchapIsSecureBackupRequired() = vectorFeatures.tchapIsSecureBackupRequired()

override fun onboardingVariant(): OnboardingVariant {
return readPreferences().getEnum<OnboardingVariant>() ?: vectorFeatures.onboardingVariant()
}
Expand Down
1 change: 1 addition & 0 deletions vector-config/src/btchap/res/values/config-features.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
<bool name="tchap_is_cross_signing_enabled">true</bool>
<bool name="tchap_is_key_backup_enabled">true</bool>
<bool name="tchap_is_thread_enabled">false</bool>
<bool name="tchap_is_secure_backup_required">true</bool>

<string-array name="tchap_is_voip_supported_homeservers" translatable="false" />
</resources>
1 change: 1 addition & 0 deletions vector-config/src/devTchap/res/values/config-features.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
<bool name="tchap_is_cross_signing_enabled">true</bool>
<bool name="tchap_is_key_backup_enabled">true</bool>
<bool name="tchap_is_thread_enabled">false</bool>
<bool name="tchap_is_secure_backup_required">true</bool>

<string-array name="tchap_is_voip_supported_homeservers" translatable="false" />
</resources>
1 change: 1 addition & 0 deletions vector-config/src/tchap/res/values/config-features.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
<bool name="tchap_is_cross_signing_enabled">true</bool>
<bool name="tchap_is_key_backup_enabled">true</bool>
<bool name="tchap_is_thread_enabled">false</bool>
<bool name="tchap_is_secure_backup_required">true</bool>

<string-array name="tchap_is_voip_supported_homeservers" translatable="false" />
</resources>
2 changes: 2 additions & 0 deletions vector/src/main/java/im/vector/app/features/VectorFeatures.kt
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ interface VectorFeatures {
fun tchapIsKeyBackupEnabled(): Boolean
fun tchapIsThreadEnabled(): Boolean
fun tchapIsLabsVisible(domain: String): Boolean
fun tchapIsSecureBackupRequired(): Boolean
fun onboardingVariant(): OnboardingVariant
fun isOnboardingAlreadyHaveAccountSplashEnabled(): Boolean
fun isOnboardingSplashCarouselEnabled(): Boolean
Expand Down Expand Up @@ -71,6 +72,7 @@ class DefaultVectorFeatures @Inject constructor(
override fun tchapIsThreadEnabled() = booleanProvider.getBoolean(R.bool.tchap_is_thread_enabled)
override fun tchapIsLabsVisible(domain: String) = booleanProvider.getBoolean(R.bool.settings_root_labs_visible) ||
domain == appNameProvider.getAppName()
override fun tchapIsSecureBackupRequired() = booleanProvider.getBoolean(R.bool.tchap_is_secure_backup_required)
override fun onboardingVariant() = Config.ONBOARDING_VARIANT
override fun isOnboardingAlreadyHaveAccountSplashEnabled() = true
override fun isOnboardingSplashCarouselEnabled() = false // TCHAP no carousel
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,16 @@ import im.vector.app.core.di.hiltMavericksViewModelFactory
import im.vector.app.core.platform.VectorViewModel
import im.vector.app.core.platform.WaitingViewData
import im.vector.app.core.resources.StringProvider
import im.vector.app.features.VectorFeatures
import im.vector.app.features.raw.wellknown.getElementWellknown
import im.vector.app.features.raw.wellknown.isSecureBackupRequired
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import org.matrix.android.sdk.api.Matrix
import org.matrix.android.sdk.api.listeners.ProgressListener
import org.matrix.android.sdk.api.raw.RawService
import org.matrix.android.sdk.api.session.Session
import org.matrix.android.sdk.api.session.securestorage.IntegrityResult
import org.matrix.android.sdk.api.session.securestorage.KeyInfo
Expand Down Expand Up @@ -88,7 +92,9 @@ data class SharedSecureStorageViewState(
class SharedSecureStorageViewModel @AssistedInject constructor(
@Assisted private val initialState: SharedSecureStorageViewState,
private val stringProvider: StringProvider,
private val vectorFeatures: VectorFeatures,
private val session: Session,
private val rawService: RawService,
private val matrix: Matrix,
) :
VectorViewModel<SharedSecureStorageViewState, SharedSecureStorageAction, SharedSecureStorageViewEvent>(initialState) {
Expand All @@ -102,16 +108,25 @@ class SharedSecureStorageViewModel @AssistedInject constructor(
setState {
copy(userId = session.myUserId)
}
if (initialState.requestType is RequestType.ReadSecrets) {
val integrityResult =
session.sharedSecretStorageService().checkShouldBeAbleToAccessSecrets(initialState.requestType.secretsName, initialState.keyId)
if (integrityResult !is IntegrityResult.Success) {
_viewEvents.post(
SharedSecureStorageViewEvent.Error(
stringProvider.getString(R.string.enter_secret_storage_invalid),
true
)
)

// TCHAP force to configure secure backup even if well-known is null
// Do not check integrity if the session is not verified
viewModelScope.launch(Dispatchers.IO) {
val elementWellKnown = rawService.getElementWellknown(session.sessionParams)
val isSecureBackupRequired = elementWellKnown?.isSecureBackupRequired() ?: vectorFeatures.tchapIsSecureBackupRequired()
val isThisSessionVerified = session.cryptoService().crossSigningService().isCrossSigningVerified()

if ((isThisSessionVerified || !isSecureBackupRequired) && initialState.requestType is RequestType.ReadSecrets) {
val integrityResult =
session.sharedSecretStorageService().checkShouldBeAbleToAccessSecrets(initialState.requestType.secretsName, initialState.keyId)
if (integrityResult !is IntegrityResult.Success) {
_viewEvents.post(
SharedSecureStorageViewEvent.Error(
stringProvider.getString(R.string.enter_secret_storage_invalid),
true
)
)
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,18 +44,17 @@ class BootstrapSetupRecoveryKeyFragment :

// TCHAP we directly send user to Security Key
// Actions when a key backup exist
// views.bootstrapSetupSecureSubmit.views.bottomSheetActionClickableZone.debouncedClicks {
// sharedViewModel.handle(BootstrapActions.StartKeyBackupMigration)
// }

// Actions when there is no key backup
// views.bootstrapSetupSecureUseSecurityKey.views.bottomSheetActionClickableZone.debouncedClicks {
// sharedViewModel.handle(BootstrapActions.Start(userWantsToEnterPassphrase = false))
// }
// views.bootstrapSetupSecureUseSecurityPassphrase.views.bottomSheetActionClickableZone.debouncedClicks {
// sharedViewModel.handle(BootstrapActions.Start(userWantsToEnterPassphrase = true))
// }

// views.bootstrapSetupSecureSubmit.views.bottomSheetActionClickableZone.debouncedClicks {
// sharedViewModel.handle(BootstrapActions.StartKeyBackupMigration)
// }
//
// // Actions when there is no key backup
// views.bootstrapSetupSecureUseSecurityKey.views.bottomSheetActionClickableZone.debouncedClicks {
// sharedViewModel.handle(BootstrapActions.Start(userWantsToEnterPassphrase = false))
// }
// views.bootstrapSetupSecureUseSecurityPassphrase.views.bottomSheetActionClickableZone.debouncedClicks {
// sharedViewModel.handle(BootstrapActions.Start(userWantsToEnterPassphrase = true))
// }
sharedViewModel.handle(BootstrapActions.Start(userWantsToEnterPassphrase = false))
}

Expand Down Expand Up @@ -95,7 +94,7 @@ class BootstrapSetupRecoveryKeyFragment :
private fun renderBackupMethodActions(method: SecureBackupMethod) = with(views) {
bootstrapSetupSecureUseSecurityKey.isVisible = method.isKeyAvailable
// TCHAP Hide Security Passphrase
// views.bootstrapSetupSecureUseSecurityPassphrase.isVisible = method.isPassphraseAvailable
// views.bootstrapSetupSecureUseSecurityPassphraseSeparator.isVisible = method.isPassphraseAvailable
// bootstrapSetupSecureUseSecurityPassphrase.isVisible = method.isPassphraseAvailable
// bootstrapSetupSecureUseSecurityPassphraseSeparator.isVisible = method.isPassphraseAvailable
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import im.vector.app.core.error.ErrorFormatter
import im.vector.app.core.platform.VectorViewModel
import im.vector.app.core.platform.WaitingViewData
import im.vector.app.core.resources.StringProvider
import im.vector.app.features.VectorFeatures
import im.vector.app.features.auth.PendingAuthHandler
import im.vector.app.features.raw.wellknown.SecureBackupMethod
import im.vector.app.features.raw.wellknown.getElementWellknown
Expand All @@ -45,7 +46,6 @@ 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.orFalse
import org.matrix.android.sdk.api.extensions.tryOrNull
import org.matrix.android.sdk.api.failure.Failure
import org.matrix.android.sdk.api.raw.RawService
Expand All @@ -63,6 +63,7 @@ class BootstrapSharedViewModel @AssistedInject constructor(
@Assisted initialState: BootstrapViewState,
private val stringProvider: StringProvider,
private val errorFormatter: ErrorFormatter,
private val vectorFeatures: VectorFeatures,
private val session: Session,
private val rawService: RawService,
private val bootstrapTask: BootstrapCrossSigningTask,
Expand Down Expand Up @@ -92,8 +93,9 @@ class BootstrapSharedViewModel @AssistedInject constructor(
val wellKnown = rawService.getElementWellknown(session.sessionParams)
setState {
copy(
isSecureBackupRequired = wellKnown?.isSecureBackupRequired().orFalse(),
secureBackupMethod = wellKnown?.secureBackupMethod() ?: SecureBackupMethod.KEY_OR_PASSPHRASE,
// TCHAP force to configure secure backup key even if well-known is null
isSecureBackupRequired = wellKnown?.isSecureBackupRequired() ?: vectorFeatures.tchapIsSecureBackupRequired(),
secureBackupMethod = wellKnown?.secureBackupMethod() ?: SecureBackupMethod.KEY,
)
}
}
Expand Down Expand Up @@ -212,7 +214,10 @@ class BootstrapSharedViewModel @AssistedInject constructor(
}
is BootstrapActions.DoInitialize -> {
if (state.passphrase == state.passphraseRepeat) {
startInitializeFlow(state)
// TCHAP do not ask user password multiple times
if (state.step !is BootstrapStep.AccountReAuth) {
startInitializeFlow(state)
}
} else {
setState {
copy(
Expand All @@ -222,7 +227,10 @@ class BootstrapSharedViewModel @AssistedInject constructor(
}
}
is BootstrapActions.DoInitializeGeneratedKey -> {
startInitializeFlow(state)
// TCHAP do not ask user password multiple times
if (state.step !is BootstrapStep.AccountReAuth) {
startInitializeFlow(state)
}
}
BootstrapActions.RecoveryKeySaved -> {
_viewEvents.post(BootstrapViewEvents.RecoveryKeySaved)
Expand Down Expand Up @@ -603,4 +611,4 @@ class BootstrapSharedViewModel @AssistedInject constructor(
}
}

private val BootstrapViewState.canLeave: Boolean get() = !isSecureBackupRequired || isRecoverySetup
private val BootstrapViewState.canLeave: Boolean get() = !isSecureBackupRequired || isRecoverySetup // TCHAP add a reminder instead ?
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,8 @@ class SelfVerificationController @Inject constructor(
id("passphrase")
title(host.stringProvider.getString(R.string.verification_cannot_access_other_session))
titleColor(host.colorProvider.getColorFromAttribute(R.attr.vctr_content_primary))
subTitle(host.stringProvider.getString(R.string.verification_use_passphrase))
// TCHAP use recovery key with no restriction
// subTitle(host.stringProvider.getString(R.string.verification_use_passphrase))
iconRes(R.drawable.ic_arrow_right)
iconColor(host.colorProvider.getColorFromAttribute(R.attr.vctr_content_primary))
listener { host.selfVerificationListener?.onClickRecoverFromPassphrase() }
Expand Down
Loading

0 comments on commit b084ce4

Please sign in to comment.