Restore-after-registration fixes.

This commit is contained in:
Nicholas Tinsley 2024-08-09 15:51:54 -04:00 committed by mtang-signal
parent fa7e4c9686
commit f296fcd716
6 changed files with 41 additions and 16 deletions

View file

@ -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;
}

View file

@ -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);

View file

@ -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())
)

View file

@ -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.")

View file

@ -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
}

View file

@ -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;