diff --git a/app/src/main/java/org/thoughtcrime/securesms/PassphraseRequiredActivity.java b/app/src/main/java/org/thoughtcrime/securesms/PassphraseRequiredActivity.java index df0d57cdb9..1b36a37742 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/PassphraseRequiredActivity.java +++ b/app/src/main/java/org/thoughtcrime/securesms/PassphraseRequiredActivity.java @@ -268,13 +268,13 @@ public abstract class PassphraseRequiredActivity extends BaseActivity implements } private Intent getRoutedIntent(Intent destination, @Nullable Intent nextIntent) { - if (nextIntent != null) destination.putExtra("next_intent", nextIntent); + if (nextIntent != null) destination.putExtra(NEXT_INTENT_EXTRA, nextIntent); return destination; } private Intent getRoutedIntent(Class destination, @Nullable Intent nextIntent) { final Intent intent = new Intent(this, destination); - if (nextIntent != null) intent.putExtra("next_intent", nextIntent); + if (nextIntent != null) intent.putExtra(NEXT_INTENT_EXTRA, nextIntent); return intent; } diff --git a/app/src/main/java/org/thoughtcrime/securesms/pin/PinRestoreEntryFragment.java b/app/src/main/java/org/thoughtcrime/securesms/pin/PinRestoreEntryFragment.java index fc11abdc9f..36404904b2 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/pin/PinRestoreEntryFragment.java +++ b/app/src/main/java/org/thoughtcrime/securesms/pin/PinRestoreEntryFragment.java @@ -25,6 +25,7 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder; import org.signal.core.util.logging.Log; import org.thoughtcrime.securesms.LoggingFragment; import org.thoughtcrime.securesms.MainActivity; +import org.thoughtcrime.securesms.PassphraseRequiredActivity; import org.thoughtcrime.securesms.R; import org.thoughtcrime.securesms.dependencies.AppDependencies; import org.thoughtcrime.securesms.jobs.ProfileUploadJob; @@ -238,8 +239,10 @@ public class PinRestoreEntryFragment extends LoggingFragment { Activity activity = requireActivity(); - if (RemoteConfig.messageBackups()) { - startActivity(RestoreActivity.getIntentForTransferOrRestore(activity)); + if (RemoteConfig.messageBackups() && !SignalStore.registration().hasCompletedRestore()) { + final Intent transferOrRestore = RestoreActivity.getIntentForTransferOrRestore(activity); + transferOrRestore.putExtra(PassphraseRequiredActivity.NEXT_INTENT_EXTRA, MainActivity.clearTop(requireContext())); + startActivity(transferOrRestore); } else if (Recipient.self().getProfileName().isEmpty() || !AvatarHelper.hasAvatar(activity, Recipient.self().getId())) { final Intent main = MainActivity.clearTop(activity); final Intent profile = CreateProfileActivity.getIntentForUserProfile(activity); diff --git a/app/src/main/java/org/thoughtcrime/securesms/registration/data/LocalRegistrationMetadataUtil.kt b/app/src/main/java/org/thoughtcrime/securesms/registration/data/LocalRegistrationMetadataUtil.kt index 216f6a44cf..4eaa4dd31a 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/registration/data/LocalRegistrationMetadataUtil.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/registration/data/LocalRegistrationMetadataUtil.kt @@ -7,6 +7,7 @@ package org.thoughtcrime.securesms.registration.data import okio.ByteString.Companion.toByteString import org.signal.libsignal.protocol.IdentityKey +import org.signal.libsignal.protocol.IdentityKeyPair import org.signal.libsignal.protocol.state.KyberPreKeyRecord import org.signal.libsignal.protocol.state.SignedPreKeyRecord import org.thoughtcrime.securesms.database.model.databaseprotos.LocalRegistrationMetadata @@ -18,12 +19,12 @@ import org.whispersystems.signalservice.api.account.PreKeyCollection * and combines them into a proto-backed class [LocalRegistrationMetadata] so they can be serialized & stored. */ object LocalRegistrationMetadataUtil { - fun createLocalRegistrationMetadata(registrationData: RegistrationData, remoteResult: RegistrationRepository.AccountRegistrationResult, reglockEnabled: Boolean): LocalRegistrationMetadata { + fun createLocalRegistrationMetadata(localAciIdentityKeyPair: IdentityKeyPair, localPniIdentityKeyPair: IdentityKeyPair, registrationData: RegistrationData, remoteResult: RegistrationRepository.AccountRegistrationResult, reglockEnabled: Boolean): LocalRegistrationMetadata { return LocalRegistrationMetadata.Builder().apply { - aciIdentityKey = remoteResult.aciPreKeyCollection.identityKey.serialize().toByteString() + aciIdentityKeyPair = localAciIdentityKeyPair.serialize().toByteString() aciSignedPreKey = remoteResult.aciPreKeyCollection.signedPreKey.serialize().toByteString() aciLastRestoreKyberPreKey = remoteResult.aciPreKeyCollection.signedPreKey.serialize().toByteString() - pniIdentityKey = remoteResult.pniPreKeyCollection.identityKey.serialize().toByteString() + pniIdentityKeyPair = localPniIdentityKeyPair.serialize().toByteString() pniSignedPreKey = remoteResult.pniPreKeyCollection.signedPreKey.serialize().toByteString() pniLastRestoreKyberPreKey = remoteResult.pniPreKeyCollection.signedPreKey.serialize().toByteString() aci = remoteResult.uuid @@ -43,9 +44,17 @@ object LocalRegistrationMetadataUtil { }.build() } + fun LocalRegistrationMetadata.getAciIdentityKeyPair() : IdentityKeyPair { + return IdentityKeyPair(aciIdentityKeyPair.toByteArray()) + } + + fun LocalRegistrationMetadata.getPniIdentityKeyPair() : IdentityKeyPair { + return IdentityKeyPair(pniIdentityKeyPair.toByteArray()) + } + fun LocalRegistrationMetadata.getAciPreKeyCollection(): PreKeyCollection { return PreKeyCollection( - IdentityKey(aciIdentityKey.toByteArray()), + getAciIdentityKeyPair().publicKey, SignedPreKeyRecord(aciSignedPreKey.toByteArray()), KyberPreKeyRecord(aciLastRestoreKyberPreKey.toByteArray()) ) @@ -53,7 +62,7 @@ object LocalRegistrationMetadataUtil { fun LocalRegistrationMetadata.getPniPreKeyCollection(): PreKeyCollection { return PreKeyCollection( - IdentityKey(pniIdentityKey.toByteArray()), + getPniIdentityKeyPair().publicKey, SignedPreKeyRecord(pniSignedPreKey.toByteArray()), KyberPreKeyRecord(pniLastRestoreKyberPreKey.toByteArray()) ) diff --git a/app/src/main/java/org/thoughtcrime/securesms/registration/data/RegistrationRepository.kt b/app/src/main/java/org/thoughtcrime/securesms/registration/data/RegistrationRepository.kt index e98681b0f7..d6c089c5f3 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/registration/data/RegistrationRepository.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/registration/data/RegistrationRepository.kt @@ -46,7 +46,9 @@ import org.thoughtcrime.securesms.recipients.RecipientId import org.thoughtcrime.securesms.registration.PushChallengeRequest import org.thoughtcrime.securesms.registration.RegistrationData import org.thoughtcrime.securesms.registration.VerifyAccountRepository +import org.thoughtcrime.securesms.registration.data.LocalRegistrationMetadataUtil.getAciIdentityKeyPair import org.thoughtcrime.securesms.registration.data.LocalRegistrationMetadataUtil.getAciPreKeyCollection +import org.thoughtcrime.securesms.registration.data.LocalRegistrationMetadataUtil.getPniIdentityKeyPair import org.thoughtcrime.securesms.registration.data.LocalRegistrationMetadataUtil.getPniPreKeyCollection import org.thoughtcrime.securesms.registration.data.network.BackupAuthCheckResult import org.thoughtcrime.securesms.registration.data.network.RegisterAccountResult @@ -165,6 +167,11 @@ object RegistrationRepository { suspend fun registerAccountLocally(context: Context, data: LocalRegistrationMetadata) = withContext(Dispatchers.IO) { Log.v(TAG, "registerAccountLocally()") + val aciIdentityKeyPair = data.getAciIdentityKeyPair() + val pniIdentityKeyPair = data.getPniIdentityKeyPair() + SignalStore.account.restoreAciIdentityKeyFromBackup(aciIdentityKeyPair.publicKey.serialize(), aciIdentityKeyPair.privateKey.serialize()) + SignalStore.account.restorePniIdentityKeyFromBackup(pniIdentityKeyPair.publicKey.serialize(), pniIdentityKeyPair.privateKey.serialize()) + val aciPreKeyCollection = data.getAciPreKeyCollection() val pniPreKeyCollection = data.getPniPreKeyCollection() val aci: ACI = ACI.parseOrThrow(data.aci) @@ -275,7 +282,7 @@ object RegistrationRepository { /** * Validates a session ID. */ - suspend fun validateSession(context: Context, sessionId: String, e164: String, password: String): RegistrationSessionCheckResult = + private suspend fun validateSession(context: Context, sessionId: String, e164: String, password: String): RegistrationSessionCheckResult = withContext(Dispatchers.IO) { val api: RegistrationApi = AccountManagerFactory.getInstance().createUnauthenticated(context, e164, SignalServiceAddress.DEFAULT_DEVICE_ID, password).registrationApi Log.d(TAG, "Validating registration session with service.") diff --git a/app/src/main/java/org/thoughtcrime/securesms/registration/ui/RegistrationViewModel.kt b/app/src/main/java/org/thoughtcrime/securesms/registration/ui/RegistrationViewModel.kt index 0809d39161..687bdc7951 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/registration/ui/RegistrationViewModel.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/registration/ui/RegistrationViewModel.kt @@ -398,14 +398,17 @@ class RegistrationViewModel : ViewModel() { nextVerificationAttempt = RegistrationRepository.deriveTimestamp(networkResult.headers, networkResult.body.nextVerificationAttempt), allowedToRequestCode = networkResult.body.allowedToRequestCode, challengesRequested = Challenge.parse(networkResult.body.requestedInformation), - verified = networkResult.body.verified + verified = networkResult.body.verified, + inProgress = false ) } }, errorHandler = { error -> + Log.d(TAG, "Setting ${error::class.simpleName} as session creation error.") store.update { it.copy( - sessionCreationError = error + sessionCreationError = error, + inProgress = false ) } } @@ -816,7 +819,7 @@ class RegistrationViewModel : ViewModel() { private suspend fun onSuccessfulRegistration(context: Context, registrationData: RegistrationData, remoteResult: RegistrationRepository.AccountRegistrationResult, reglockEnabled: Boolean) { Log.v(TAG, "onSuccessfulRegistration()") - val metadata = LocalRegistrationMetadataUtil.createLocalRegistrationMetadata(registrationData, remoteResult, reglockEnabled) + val metadata = LocalRegistrationMetadataUtil.createLocalRegistrationMetadata(SignalStore.account.aciIdentityKey, SignalStore.account.pniIdentityKey, registrationData, remoteResult, reglockEnabled) if (RemoteConfig.restoreAfterRegistration) { SignalStore.registration.localRegistrationMetadata = metadata } @@ -949,7 +952,10 @@ class RegistrationViewModel : ViewModel() { return metadata } - else -> errorHandler(sessionResult) + else -> { + Log.d(TAG, "Handling error during session creation.") + errorHandler(sessionResult) + } } return null } diff --git a/app/src/main/protowire/Database.proto b/app/src/main/protowire/Database.proto index 05f6de813a..9394c85d5c 100644 --- a/app/src/main/protowire/Database.proto +++ b/app/src/main/protowire/Database.proto @@ -516,10 +516,10 @@ message PaymentTombstone { } message LocalRegistrationMetadata { - bytes aciIdentityKey = 1; + bytes aciIdentityKeyPair = 1; bytes aciSignedPreKey = 2; bytes aciLastRestoreKyberPreKey = 3; - bytes pniIdentityKey = 4; + bytes pniIdentityKeyPair = 4; bytes pniSignedPreKey = 5; bytes pniLastRestoreKyberPreKey = 6; string aci = 7;