From a2330f443acb41157840386ee99be854d1cef8d6 Mon Sep 17 00:00:00 2001 From: Cody Henthorne Date: Fri, 22 Nov 2024 10:19:35 -0500 Subject: [PATCH] Use AEP for regv3 flows. --- .../backup/v2/ArchiveImportExportTests.kt | 4 +--- .../MessageBackupsFlowFragment.kt | 2 +- .../subscription/MessageBackupsFlowState.kt | 4 ++-- .../MessageBackupsKeyRecordScreen.kt | 11 +++++----- .../remote/BackupKeyDisplayFragment.kt | 2 +- .../securesms/keyvalue/SvrValues.kt | 20 ------------------- .../data/QuickRegistrationRepository.kt | 3 +-- .../ui/RegistrationViewModel.kt | 9 +++++---- .../ui/restore/EnterBackupKeyFragment.kt | 4 ++-- .../ui/restore/EnterBackupKeyViewModel.kt | 20 +++---------------- 10 files changed, 21 insertions(+), 58 deletions(-) diff --git a/app/src/androidTest/java/org/thoughtcrime/securesms/backup/v2/ArchiveImportExportTests.kt b/app/src/androidTest/java/org/thoughtcrime/securesms/backup/v2/ArchiveImportExportTests.kt index 373b162685..4f2ef39b58 100644 --- a/app/src/androidTest/java/org/thoughtcrime/securesms/backup/v2/ArchiveImportExportTests.kt +++ b/app/src/androidTest/java/org/thoughtcrime/securesms/backup/v2/ArchiveImportExportTests.kt @@ -24,7 +24,6 @@ import org.thoughtcrime.securesms.backup.v2.stream.PlainTextBackupReader import org.thoughtcrime.securesms.database.KeyValueDatabase import org.thoughtcrime.securesms.dependencies.AppDependencies import org.thoughtcrime.securesms.keyvalue.SignalStore -import org.whispersystems.signalservice.api.kbs.MasterKey import org.whispersystems.signalservice.api.push.ServiceId import java.io.ByteArrayInputStream import java.util.UUID @@ -40,7 +39,6 @@ class ArchiveImportExportTests { val SELF_PNI = ServiceId.PNI.from(UUID.fromString("00000000-0000-4000-8000-000000000002")) val SELF_E164 = "+10000000000" val SELF_PROFILE_KEY: ByteArray = Base64.decode("YQKRq+3DQklInaOaMcmlzZnN0m/1hzLiaONX7gB12dg=") - val MASTER_KEY = Base64.decode("sHuBMP4ToZk4tcNU+S8eBUeCt8Am5EZnvuqTBJIR4Do") } @Before @@ -274,7 +272,7 @@ class ArchiveImportExportTests { KeyValueDatabase.getInstance(AppDependencies.application).clear() SignalStore.resetCache() - SignalStore.svr.setMasterKey(MasterKey(MASTER_KEY), "1234") + SignalStore.account.resetAccountEntropyPool() SignalStore.account.setE164(SELF_E164) SignalStore.account.setAci(SELF_ACI) SignalStore.account.setPni(SELF_PNI) diff --git a/app/src/main/java/org/thoughtcrime/securesms/backup/v2/ui/subscription/MessageBackupsFlowFragment.kt b/app/src/main/java/org/thoughtcrime/securesms/backup/v2/ui/subscription/MessageBackupsFlowFragment.kt index e2fefa24df..f839bd5ab9 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/backup/v2/ui/subscription/MessageBackupsFlowFragment.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/backup/v2/ui/subscription/MessageBackupsFlowFragment.kt @@ -103,7 +103,7 @@ class MessageBackupsFlowFragment : ComposeFragment(), InAppPaymentCheckoutDelega val context = LocalContext.current MessageBackupsKeyRecordScreen( - messageBackupKey = state.messageBackupKey, + backupKey = state.accountEntropyPool.value, onNavigationClick = viewModel::goToPreviousStage, onNextClick = viewModel::goToNextStage, onCopyToClipboardClick = { diff --git a/app/src/main/java/org/thoughtcrime/securesms/backup/v2/ui/subscription/MessageBackupsFlowState.kt b/app/src/main/java/org/thoughtcrime/securesms/backup/v2/ui/subscription/MessageBackupsFlowState.kt index 38ddcfb053..698bc87440 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/backup/v2/ui/subscription/MessageBackupsFlowState.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/backup/v2/ui/subscription/MessageBackupsFlowState.kt @@ -8,7 +8,7 @@ package org.thoughtcrime.securesms.backup.v2.ui.subscription import org.thoughtcrime.securesms.backup.v2.MessageBackupTier import org.thoughtcrime.securesms.database.InAppPaymentTable import org.thoughtcrime.securesms.keyvalue.SignalStore -import org.whispersystems.signalservice.api.backup.MessageBackupKey +import org.whispersystems.signalservice.api.AccountEntropyPool data class MessageBackupsFlowState( val hasBackupSubscriberAvailable: Boolean = false, @@ -18,6 +18,6 @@ data class MessageBackupsFlowState( val inAppPayment: InAppPaymentTable.InAppPayment? = null, val startScreen: MessageBackupsStage, val stage: MessageBackupsStage = startScreen, - val messageBackupKey: MessageBackupKey = SignalStore.backup.messageBackupKey, + val accountEntropyPool: AccountEntropyPool = SignalStore.account.accountEntropyPool, val failure: Throwable? = null ) diff --git a/app/src/main/java/org/thoughtcrime/securesms/backup/v2/ui/subscription/MessageBackupsKeyRecordScreen.kt b/app/src/main/java/org/thoughtcrime/securesms/backup/v2/ui/subscription/MessageBackupsKeyRecordScreen.kt index 8c6d5611a0..1c79475757 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/backup/v2/ui/subscription/MessageBackupsKeyRecordScreen.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/backup/v2/ui/subscription/MessageBackupsKeyRecordScreen.kt @@ -48,10 +48,9 @@ import org.signal.core.ui.Previews import org.signal.core.ui.Scaffolds import org.signal.core.ui.SignalPreview import org.signal.core.ui.theme.SignalTheme -import org.signal.core.util.Hex import org.thoughtcrime.securesms.R -import org.whispersystems.signalservice.api.backup.MessageBackupKey import kotlin.random.Random +import kotlin.random.nextInt import org.signal.core.ui.R as CoreUiR /** @@ -61,7 +60,7 @@ import org.signal.core.ui.R as CoreUiR @OptIn(ExperimentalMaterial3Api::class) @Composable fun MessageBackupsKeyRecordScreen( - messageBackupKey: MessageBackupKey, + backupKey: String, onNavigationClick: () -> Unit = {}, onCopyToClipboardClick: (String) -> Unit = {}, onNextClick: () -> Unit = {} @@ -105,8 +104,8 @@ fun MessageBackupsKeyRecordScreen( modifier = Modifier.padding(top = 12.dp) ) - val backupKeyString = remember(messageBackupKey) { - messageBackupKey.value.toList().chunked(2).map { Hex.toStringCondensed(it.toByteArray()) }.joinToString(" ") + val backupKeyString = remember(backupKey) { + backupKey.chunked(4).joinToString(" ") } Box( @@ -259,7 +258,7 @@ private fun BottomSheetContent( private fun MessageBackupsKeyRecordScreenPreview() { Previews.Preview { MessageBackupsKeyRecordScreen( - messageBackupKey = MessageBackupKey(Random.nextBytes(32)) + backupKey = (0 until 64).map { Random.nextInt(97..122).toChar() }.joinToString("") ) } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/backups/remote/BackupKeyDisplayFragment.kt b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/backups/remote/BackupKeyDisplayFragment.kt index 5497ee7f56..8ce22a2a99 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/backups/remote/BackupKeyDisplayFragment.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/backups/remote/BackupKeyDisplayFragment.kt @@ -19,7 +19,7 @@ class BackupKeyDisplayFragment : ComposeFragment() { @Composable override fun FragmentContent() { MessageBackupsKeyRecordScreen( - messageBackupKey = SignalStore.backup.messageBackupKey, + backupKey = SignalStore.account.accountEntropyPool.value, onNavigationClick = { findNavController().popBackStack() }, onCopyToClipboardClick = { Util.copyToClipboard(requireContext(), it) }, onNextClick = { findNavController().popBackStack() } diff --git a/app/src/main/java/org/thoughtcrime/securesms/keyvalue/SvrValues.kt b/app/src/main/java/org/thoughtcrime/securesms/keyvalue/SvrValues.kt index 6a517d9658..8e53ddf820 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/keyvalue/SvrValues.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/keyvalue/SvrValues.kt @@ -45,26 +45,6 @@ class SvrValues internal constructor(store: KeyValueStore) : SignalStoreValues(s .commit() } - @Deprecated("Switch to restoring AEP instead") - @Synchronized - fun setMasterKey(masterKey: MasterKey, pin: String?) { - store.beginWrite().apply { -// putBlob(MASTER_KEY, masterKey.serialize()) - putLong(LAST_CREATE_FAILED_TIMESTAMP, -1) - putBoolean(OPTED_OUT, false) - - if (pin != null) { - putString(LOCK_LOCAL_PIN_HASH, localPinHash(pin)) - putString(PIN, pin) - remove(RESTORED_VIA_ACCOUNT_ENTROPY_KEY) - } else { - putBoolean(RESTORED_VIA_ACCOUNT_ENTROPY_KEY, true) - remove(LOCK_LOCAL_PIN_HASH) - remove(PIN) - } - }.commit() - } - @Synchronized fun setPin(pin: String) { store.beginWrite() diff --git a/app/src/main/java/org/thoughtcrime/securesms/registrationv3/data/QuickRegistrationRepository.kt b/app/src/main/java/org/thoughtcrime/securesms/registrationv3/data/QuickRegistrationRepository.kt index b7a966bf94..d593ca658d 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/registrationv3/data/QuickRegistrationRepository.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/registrationv3/data/QuickRegistrationRepository.kt @@ -11,7 +11,6 @@ import kotlinx.coroutines.delay import kotlinx.coroutines.isActive import kotlinx.coroutines.withContext import org.signal.core.util.Base64.decode -import org.signal.core.util.Hex import org.signal.core.util.isNotNullOrBlank import org.signal.core.util.logging.Log import org.signal.libsignal.protocol.InvalidKeyException @@ -81,7 +80,7 @@ object QuickRegistrationRepository { RegistrationProvisionMessage( e164 = SignalStore.account.requireE164(), aci = SignalStore.account.requireAci().toByteString(), - accountEntropyPool = Hex.toStringCondensed(SignalStore.svr.masterKey.serialize()), + accountEntropyPool = SignalStore.account.accountEntropyPool.value, pin = pin, platform = RegistrationProvisionMessage.Platform.ANDROID, backupTimestampMs = SignalStore.backup.lastBackupTime.coerceAtLeast(0L), diff --git a/app/src/main/java/org/thoughtcrime/securesms/registrationv3/ui/RegistrationViewModel.kt b/app/src/main/java/org/thoughtcrime/securesms/registrationv3/ui/RegistrationViewModel.kt index ff8c911de7..4e6dcc2029 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/registrationv3/ui/RegistrationViewModel.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/registrationv3/ui/RegistrationViewModel.kt @@ -21,7 +21,6 @@ import kotlinx.coroutines.flow.update import kotlinx.coroutines.flow.updateAndGet import kotlinx.coroutines.launch import kotlinx.coroutines.withContext -import org.signal.core.util.Hex import org.signal.core.util.Stopwatch import org.signal.core.util.isNotNullOrBlank import org.signal.core.util.logging.Log @@ -69,6 +68,7 @@ import org.thoughtcrime.securesms.registrationv3.data.RegistrationRepository import org.thoughtcrime.securesms.util.RemoteConfig import org.thoughtcrime.securesms.util.Util import org.thoughtcrime.securesms.util.dualsim.MccMncProducer +import org.whispersystems.signalservice.api.AccountEntropyPool import org.whispersystems.signalservice.api.SvrNoDataException import org.whispersystems.signalservice.api.kbs.MasterKey import org.whispersystems.signalservice.internal.push.RegistrationSessionMetadataResponse @@ -935,9 +935,10 @@ class RegistrationViewModel : ViewModel() { setPhoneNumber(PhoneNumberUtil.getInstance().parse(e164, null)) } - // TODO [backups] use new data and not master key - val masterKey = MasterKey(Hex.fromStringCondensed(backupKey)) - SignalStore.svr.setMasterKey(masterKey, pin) + val accountEntropyPool = AccountEntropyPool(backupKey) + SignalStore.account.restoreAccountEntropyPool(accountEntropyPool) + + val masterKey = accountEntropyPool.deriveMasterKey() setRecoveryPassword(masterKey.deriveRegistrationRecoveryPassword()) verifyReRegisterInternal(context = context, pin = pin, masterKey = masterKey) diff --git a/app/src/main/java/org/thoughtcrime/securesms/registrationv3/ui/restore/EnterBackupKeyFragment.kt b/app/src/main/java/org/thoughtcrime/securesms/registrationv3/ui/restore/EnterBackupKeyFragment.kt index b0aa6de96a..82406b85f2 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/registrationv3/ui/restore/EnterBackupKeyFragment.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/registrationv3/ui/restore/EnterBackupKeyFragment.kt @@ -29,7 +29,6 @@ import androidx.compose.material3.TextField import androidx.compose.material3.rememberModalBottomSheetState import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope @@ -48,6 +47,7 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.fragment.app.activityViewModels import androidx.fragment.app.viewModels +import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.navigation.fragment.findNavController import kotlinx.coroutines.launch import org.signal.core.ui.BottomSheets @@ -81,7 +81,7 @@ class EnterBackupKeyFragment : ComposeFragment() { @Composable override fun FragmentContent() { val state by viewModel.state - val sharedState by sharedViewModel.state.collectAsState() + val sharedState by sharedViewModel.state.collectAsStateWithLifecycle() EnterBackupKeyScreen( state = state, diff --git a/app/src/main/java/org/thoughtcrime/securesms/registrationv3/ui/restore/EnterBackupKeyViewModel.kt b/app/src/main/java/org/thoughtcrime/securesms/registrationv3/ui/restore/EnterBackupKeyViewModel.kt index 155d0001c9..1d2a91971d 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/registrationv3/ui/restore/EnterBackupKeyViewModel.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/registrationv3/ui/restore/EnterBackupKeyViewModel.kt @@ -9,14 +9,11 @@ import androidx.compose.runtime.MutableState import androidx.compose.runtime.State import androidx.compose.runtime.mutableStateOf import androidx.lifecycle.ViewModel -import org.signal.core.util.Hex -import java.io.IOException class EnterBackupKeyViewModel : ViewModel() { companion object { - // TODO [backups] Set actual valid characters for key input - private val VALID_CHARACTERS = setOf('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f') + private val INVALID_CHARACTERS = Regex("[^0-9a-zA-Z]") } private val _state = mutableStateOf( @@ -37,22 +34,11 @@ class EnterBackupKeyViewModel : ViewModel() { } private fun validate(length: Int, backupKey: String): Boolean { - if (backupKey.length != length) { - return false - } - - try { - // TODO [backups] Actually validate key with requirements instead of just hex - Hex.fromStringCondensed(backupKey) - } catch (e: IOException) { - return false - } - - return true + return backupKey.length == length } private fun String.removeIllegalCharacters(): String { - return filter { VALID_CHARACTERS.contains(it) } + return this.replace(INVALID_CHARACTERS, "") } private inline fun MutableState.update(update: T.() -> T) {