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) { 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; return destination;
} }
private Intent getRoutedIntent(Class<?> destination, @Nullable Intent nextIntent) { private Intent getRoutedIntent(Class<?> destination, @Nullable Intent nextIntent) {
final Intent intent = new Intent(this, destination); 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; return intent;
} }

View File

@@ -25,6 +25,7 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import org.signal.core.util.logging.Log; import org.signal.core.util.logging.Log;
import org.thoughtcrime.securesms.LoggingFragment; import org.thoughtcrime.securesms.LoggingFragment;
import org.thoughtcrime.securesms.MainActivity; import org.thoughtcrime.securesms.MainActivity;
import org.thoughtcrime.securesms.PassphraseRequiredActivity;
import org.thoughtcrime.securesms.R; import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.dependencies.AppDependencies; import org.thoughtcrime.securesms.dependencies.AppDependencies;
import org.thoughtcrime.securesms.jobs.ProfileUploadJob; import org.thoughtcrime.securesms.jobs.ProfileUploadJob;
@@ -238,8 +239,10 @@ public class PinRestoreEntryFragment extends LoggingFragment {
Activity activity = requireActivity(); Activity activity = requireActivity();
if (RemoteConfig.messageBackups()) { if (RemoteConfig.messageBackups() && !SignalStore.registration().hasCompletedRestore()) {
startActivity(RestoreActivity.getIntentForTransferOrRestore(activity)); 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())) { } else if (Recipient.self().getProfileName().isEmpty() || !AvatarHelper.hasAvatar(activity, Recipient.self().getId())) {
final Intent main = MainActivity.clearTop(activity); final Intent main = MainActivity.clearTop(activity);
final Intent profile = CreateProfileActivity.getIntentForUserProfile(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 okio.ByteString.Companion.toByteString
import org.signal.libsignal.protocol.IdentityKey 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.KyberPreKeyRecord
import org.signal.libsignal.protocol.state.SignedPreKeyRecord import org.signal.libsignal.protocol.state.SignedPreKeyRecord
import org.thoughtcrime.securesms.database.model.databaseprotos.LocalRegistrationMetadata 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. * and combines them into a proto-backed class [LocalRegistrationMetadata] so they can be serialized & stored.
*/ */
object LocalRegistrationMetadataUtil { 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 { return LocalRegistrationMetadata.Builder().apply {
aciIdentityKey = remoteResult.aciPreKeyCollection.identityKey.serialize().toByteString() aciIdentityKeyPair = localAciIdentityKeyPair.serialize().toByteString()
aciSignedPreKey = remoteResult.aciPreKeyCollection.signedPreKey.serialize().toByteString() aciSignedPreKey = remoteResult.aciPreKeyCollection.signedPreKey.serialize().toByteString()
aciLastRestoreKyberPreKey = 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() pniSignedPreKey = remoteResult.pniPreKeyCollection.signedPreKey.serialize().toByteString()
pniLastRestoreKyberPreKey = remoteResult.pniPreKeyCollection.signedPreKey.serialize().toByteString() pniLastRestoreKyberPreKey = remoteResult.pniPreKeyCollection.signedPreKey.serialize().toByteString()
aci = remoteResult.uuid aci = remoteResult.uuid
@@ -43,9 +44,17 @@ object LocalRegistrationMetadataUtil {
}.build() }.build()
} }
fun LocalRegistrationMetadata.getAciIdentityKeyPair() : IdentityKeyPair {
return IdentityKeyPair(aciIdentityKeyPair.toByteArray())
}
fun LocalRegistrationMetadata.getPniIdentityKeyPair() : IdentityKeyPair {
return IdentityKeyPair(pniIdentityKeyPair.toByteArray())
}
fun LocalRegistrationMetadata.getAciPreKeyCollection(): PreKeyCollection { fun LocalRegistrationMetadata.getAciPreKeyCollection(): PreKeyCollection {
return PreKeyCollection( return PreKeyCollection(
IdentityKey(aciIdentityKey.toByteArray()), getAciIdentityKeyPair().publicKey,
SignedPreKeyRecord(aciSignedPreKey.toByteArray()), SignedPreKeyRecord(aciSignedPreKey.toByteArray()),
KyberPreKeyRecord(aciLastRestoreKyberPreKey.toByteArray()) KyberPreKeyRecord(aciLastRestoreKyberPreKey.toByteArray())
) )
@@ -53,7 +62,7 @@ object LocalRegistrationMetadataUtil {
fun LocalRegistrationMetadata.getPniPreKeyCollection(): PreKeyCollection { fun LocalRegistrationMetadata.getPniPreKeyCollection(): PreKeyCollection {
return PreKeyCollection( return PreKeyCollection(
IdentityKey(pniIdentityKey.toByteArray()), getPniIdentityKeyPair().publicKey,
SignedPreKeyRecord(pniSignedPreKey.toByteArray()), SignedPreKeyRecord(pniSignedPreKey.toByteArray()),
KyberPreKeyRecord(pniLastRestoreKyberPreKey.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.PushChallengeRequest
import org.thoughtcrime.securesms.registration.RegistrationData import org.thoughtcrime.securesms.registration.RegistrationData
import org.thoughtcrime.securesms.registration.VerifyAccountRepository 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.getAciPreKeyCollection
import org.thoughtcrime.securesms.registration.data.LocalRegistrationMetadataUtil.getPniIdentityKeyPair
import org.thoughtcrime.securesms.registration.data.LocalRegistrationMetadataUtil.getPniPreKeyCollection import org.thoughtcrime.securesms.registration.data.LocalRegistrationMetadataUtil.getPniPreKeyCollection
import org.thoughtcrime.securesms.registration.data.network.BackupAuthCheckResult import org.thoughtcrime.securesms.registration.data.network.BackupAuthCheckResult
import org.thoughtcrime.securesms.registration.data.network.RegisterAccountResult import org.thoughtcrime.securesms.registration.data.network.RegisterAccountResult
@@ -165,6 +167,11 @@ object RegistrationRepository {
suspend fun registerAccountLocally(context: Context, data: LocalRegistrationMetadata) = suspend fun registerAccountLocally(context: Context, data: LocalRegistrationMetadata) =
withContext(Dispatchers.IO) { withContext(Dispatchers.IO) {
Log.v(TAG, "registerAccountLocally()") 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 aciPreKeyCollection = data.getAciPreKeyCollection()
val pniPreKeyCollection = data.getPniPreKeyCollection() val pniPreKeyCollection = data.getPniPreKeyCollection()
val aci: ACI = ACI.parseOrThrow(data.aci) val aci: ACI = ACI.parseOrThrow(data.aci)
@@ -275,7 +282,7 @@ object RegistrationRepository {
/** /**
* Validates a session ID. * 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) { withContext(Dispatchers.IO) {
val api: RegistrationApi = AccountManagerFactory.getInstance().createUnauthenticated(context, e164, SignalServiceAddress.DEFAULT_DEVICE_ID, password).registrationApi val api: RegistrationApi = AccountManagerFactory.getInstance().createUnauthenticated(context, e164, SignalServiceAddress.DEFAULT_DEVICE_ID, password).registrationApi
Log.d(TAG, "Validating registration session with service.") 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), nextVerificationAttempt = RegistrationRepository.deriveTimestamp(networkResult.headers, networkResult.body.nextVerificationAttempt),
allowedToRequestCode = networkResult.body.allowedToRequestCode, allowedToRequestCode = networkResult.body.allowedToRequestCode,
challengesRequested = Challenge.parse(networkResult.body.requestedInformation), challengesRequested = Challenge.parse(networkResult.body.requestedInformation),
verified = networkResult.body.verified verified = networkResult.body.verified,
inProgress = false
) )
} }
}, },
errorHandler = { error -> errorHandler = { error ->
Log.d(TAG, "Setting ${error::class.simpleName} as session creation error.")
store.update { store.update {
it.copy( 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) { private suspend fun onSuccessfulRegistration(context: Context, registrationData: RegistrationData, remoteResult: RegistrationRepository.AccountRegistrationResult, reglockEnabled: Boolean) {
Log.v(TAG, "onSuccessfulRegistration()") 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) { if (RemoteConfig.restoreAfterRegistration) {
SignalStore.registration.localRegistrationMetadata = metadata SignalStore.registration.localRegistrationMetadata = metadata
} }
@@ -949,7 +952,10 @@ class RegistrationViewModel : ViewModel() {
return metadata return metadata
} }
else -> errorHandler(sessionResult) else -> {
Log.d(TAG, "Handling error during session creation.")
errorHandler(sessionResult)
}
} }
return null return null
} }

View File

@@ -516,10 +516,10 @@ message PaymentTombstone {
} }
message LocalRegistrationMetadata { message LocalRegistrationMetadata {
bytes aciIdentityKey = 1; bytes aciIdentityKeyPair = 1;
bytes aciSignedPreKey = 2; bytes aciSignedPreKey = 2;
bytes aciLastRestoreKyberPreKey = 3; bytes aciLastRestoreKyberPreKey = 3;
bytes pniIdentityKey = 4; bytes pniIdentityKeyPair = 4;
bytes pniSignedPreKey = 5; bytes pniSignedPreKey = 5;
bytes pniLastRestoreKyberPreKey = 6; bytes pniLastRestoreKyberPreKey = 6;
string aci = 7; string aci = 7;