Update to nullable fields on registration provisioning proto.

This commit is contained in:
Greyson Parrelli
2026-09-23 10:17:26 -04:00
parent 53b888710d
commit 636762ea5b
10 changed files with 37 additions and 33 deletions
@@ -10,7 +10,6 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.isActive
import kotlinx.coroutines.withContext
import okio.ByteString
import okio.ByteString.Companion.toByteString
import org.signal.core.util.Base64.decode
import org.signal.core.util.isNotNullOrBlank
@@ -105,7 +104,7 @@ object QuickRegistrationRepository {
ephemeralId,
publicKey,
RegistrationProvisionMessage(
e164 = e164.orEmpty(),
e164 = e164,
aci = SignalStore.account.requireAci().toByteString(),
accountEntropyPool = SignalStore.account.accountEntropyPool.value,
pin = SignalStore.svr.pin,
@@ -120,8 +119,8 @@ object QuickRegistrationRepository {
restoreMethodToken = restoreMethodToken,
aciIdentityKeyPublic = SignalStore.account.aciIdentityKey.publicKey.serialize().toByteString(),
aciIdentityKeyPrivate = SignalStore.account.aciIdentityKey.privateKey.serialize().toByteString(),
pniIdentityKeyPublic = pniIdentityKey?.publicKey?.serialize()?.toByteString() ?: ByteString.EMPTY,
pniIdentityKeyPrivate = pniIdentityKey?.privateKey?.serialize()?.toByteString() ?: ByteString.EMPTY,
pniIdentityKeyPublic = pniIdentityKey?.publicKey?.serialize()?.toByteString(),
pniIdentityKeyPrivate = pniIdentityKey?.privateKey?.serialize()?.toByteString(),
backupVersion = SignalStore.backup.lastBackupProtoVersion
)
)
@@ -91,7 +91,7 @@ class NoBackupToRestoreFragment : ComposeFragment() {
sharedViewModel.registerWithBackupKey(
context = requireContext(),
backupKey = message.accountEntropyPool,
e164 = message.e164,
e164 = message.e164OrNull,
pin = message.pin,
aciIdentityKeyPair = message.aciIdentityKeyPair,
pniIdentityKeyPair = message.pniIdentityKeyPair
@@ -11,6 +11,12 @@ import org.signal.libsignal.protocol.ecc.ECPrivateKey
import org.signal.registration.proto.RegistrationProvisionMessage
import java.security.InvalidKeyException
/**
* The phone number, or null if absent or empty.
*/
val RegistrationProvisionMessage.e164OrNull: String?
get() = e164?.takeIf { it.isNotEmpty() }
/**
* Attempt to parse the ACI identity key pair from the proto message parts.
*/
@@ -27,14 +33,17 @@ val RegistrationProvisionMessage.aciIdentityKeyPair: IdentityKeyPair?
}
/**
* Attempt to parse the PNI identity key pair from the proto message parts.
* Attempt to parse the PNI identity key pair from the proto message parts. Null if absent or empty.
*/
val RegistrationProvisionMessage.pniIdentityKeyPair: IdentityKeyPair?
get() {
val publicKey = pniIdentityKeyPublic?.takeIf { it.size > 0 } ?: return null
val privateKey = pniIdentityKeyPrivate?.takeIf { it.size > 0 } ?: return null
return try {
IdentityKeyPair(
IdentityKey(pniIdentityKeyPublic.toByteArray()),
ECPrivateKey(pniIdentityKeyPrivate.toByteArray())
IdentityKey(publicKey.toByteArray()),
ECPrivateKey(privateKey.toByteArray())
)
} catch (_: InvalidKeyException) {
null
@@ -106,7 +106,7 @@ class RestoreViaQrFragment : ComposeFragment() {
.distinctUntilChanged()
.collect { message ->
if (message.platform == RegistrationProvisionMessage.Platform.ANDROID || message.tier != null) {
sharedViewModel.registerWithBackupKey(requireContext(), message.accountEntropyPool, message.e164, message.pin, message.aciIdentityKeyPair, message.pniIdentityKeyPair)
sharedViewModel.registerWithBackupKey(requireContext(), message.accountEntropyPool, message.e164OrNull, message.pin, message.aciIdentityKeyPair, message.pniIdentityKeyPair)
} else {
sharedViewModel.registrationProvisioningMessage = message
findNavController().safeNavigate(RestoreViaQrFragmentDirections.goToNoBackupToRestore())
@@ -102,6 +102,8 @@ import org.thoughtcrime.securesms.profiles.ProfileName
import org.thoughtcrime.securesms.recipients.Recipient
import org.thoughtcrime.securesms.registration.fcm.PushChallengeRequest
import org.thoughtcrime.securesms.registration.ui.restore.StorageServiceRestore
import org.thoughtcrime.securesms.registration.ui.restore.e164OrNull
import org.thoughtcrime.securesms.registration.ui.restore.pniIdentityKeyPair
import org.thoughtcrime.securesms.registration.util.RegistrationUtil
import org.thoughtcrime.securesms.registration.viewmodel.SvrAuthCredentialSet
import org.thoughtcrime.securesms.util.Environment
@@ -623,14 +625,10 @@ class AppRegistrationNetworkController(
ProvisioningMessage(
accountEntropyPool = msg.accountEntropyPool,
aci = aci,
e164 = msg.e164.takeIf { it.isNotBlank() },
e164 = msg.e164OrNull,
pin = msg.pin,
aciIdentityKeyPair = IdentityKeyPair(IdentityKey(msg.aciIdentityKeyPublic.toByteArray()), ECPrivateKey(msg.aciIdentityKeyPrivate.toByteArray())),
pniIdentityKeyPair = if (msg.pniIdentityKeyPublic.size > 0 && msg.pniIdentityKeyPrivate.size > 0) {
IdentityKeyPair(IdentityKey(msg.pniIdentityKeyPublic.toByteArray()), ECPrivateKey(msg.pniIdentityKeyPrivate.toByteArray()))
} else {
null
},
pniIdentityKeyPair = msg.pniIdentityKeyPair,
platform = when (msg.platform) {
RegistrationProvisionMessage.Platform.ANDROID -> ProvisioningMessage.Platform.ANDROID
RegistrationProvisionMessage.Platform.IOS -> ProvisioningMessage.Platform.IOS
@@ -552,16 +552,19 @@ class DemoNetworkController(
return@start
}
val pniPublicKey = msg.pniIdentityKeyPublic
val pniPrivateKey = msg.pniIdentityKeyPrivate
trySend(
ProvisioningEvent.MessageReceived(
ProvisioningMessage(
accountEntropyPool = msg.accountEntropyPool,
aci = aci,
e164 = msg.e164.takeIf { it.isNotBlank() },
e164 = msg.e164?.takeIf { it.isNotEmpty() },
pin = msg.pin,
aciIdentityKeyPair = IdentityKeyPair(IdentityKey(msg.aciIdentityKeyPublic.toByteArray()), ECPrivateKey(msg.aciIdentityKeyPrivate.toByteArray())),
pniIdentityKeyPair = if (msg.pniIdentityKeyPublic.size > 0 && msg.pniIdentityKeyPrivate.size > 0) {
IdentityKeyPair(IdentityKey(msg.pniIdentityKeyPublic.toByteArray()), ECPrivateKey(msg.pniIdentityKeyPrivate.toByteArray()))
pniIdentityKeyPair = if (pniPublicKey != null && pniPublicKey.size > 0 && pniPrivateKey != null && pniPrivateKey.size > 0) {
IdentityKeyPair(IdentityKey(pniPublicKey.toByteArray()), ECPrivateKey(pniPrivateKey.toByteArray()))
} else {
null
},
@@ -217,14 +217,10 @@ class DemoStorageController(private val context: Context) : StorageController {
NetworkController.ProvisioningMessage(
accountEntropyPool = data.accountEntropyPool,
aci = ACI.parseOrThrow(accountData.aci),
e164 = accountData.e164,
e164 = accountData.e164?.takeIf { it.isNotEmpty() },
pin = data.pin.ifEmpty { null },
aciIdentityKeyPair = IdentityKeyPair(accountData.aciIdentityKeyPair.toByteArray()),
pniIdentityKeyPair = if (accountData.pniIdentityKeyPair.size > 0) {
IdentityKeyPair(accountData.pniIdentityKeyPair.toByteArray())
} else {
null
},
pniIdentityKeyPair = accountData.pniIdentityKeyPair.takeIf { it.size > 0 }?.let { IdentityKeyPair(it.toByteArray()) },
platform = when (prov.platform) {
ProvisioningData.Platform.ANDROID -> NetworkController.ProvisioningMessage.Platform.ANDROID
ProvisioningData.Platform.IOS -> NetworkController.ProvisioningMessage.Platform.IOS
@@ -84,11 +84,11 @@ class TransferAccountViewModel(
withContext(Dispatchers.IO) {
val publicKey = ECPublicKey(Base64.decode(publicKeyEncoded))
val e164 = checkNotNull(RegistrationPreferences.e164) { "No e164 stored" }
val e164 = RegistrationPreferences.e164
val aci = checkNotNull(RegistrationPreferences.aci) { "No ACI stored" }
val aep = checkNotNull(RegistrationPreferences.aep) { "No AEP stored" }
val aciKeyPair = checkNotNull(RegistrationPreferences.aciIdentityKeyPair) { "No ACI identity key pair stored" }
val pniKeyPair = checkNotNull(RegistrationPreferences.pniIdentityKeyPair) { "No PNI identity key pair stored" }
val pniKeyPair = RegistrationPreferences.pniIdentityKeyPair
val restoreMethodToken = UUID.randomUUID().toString()
val message = RegistrationProvisionMessage(
@@ -101,8 +101,8 @@ class TransferAccountViewModel(
restoreMethodToken = restoreMethodToken,
aciIdentityKeyPublic = okio.ByteString.of(*aciKeyPair.publicKey.serialize()),
aciIdentityKeyPrivate = okio.ByteString.of(*aciKeyPair.privateKey.serialize()),
pniIdentityKeyPublic = okio.ByteString.of(*pniKeyPair.publicKey.serialize()),
pniIdentityKeyPrivate = okio.ByteString.of(*pniKeyPair.privateKey.serialize()),
pniIdentityKeyPublic = pniKeyPair?.let { okio.ByteString.of(*it.publicKey.serialize()) },
pniIdentityKeyPrivate = pniKeyPair?.let { okio.ByteString.of(*it.privateKey.serialize()) },
backupVersion = 0
)
@@ -100,7 +100,6 @@ class QuickRestoreQrViewModel(
private suspend fun handleProvisioningMessage(message: NetworkController.ProvisioningMessage) {
parentEventEmitter(RegistrationFlowEvent.RestoreMethodTokenReceived(message.restoreMethodToken))
if (message.e164 != null) {
parentEventEmitter(RegistrationFlowEvent.E164Chosen(message.e164))
}
@@ -19,7 +19,7 @@ message RegistrationProvisionMessage {
PAID = 1;
}
string e164 = 1;
optional string e164 = 1;
bytes aci = 2;
string accountEntropyPool = 3;
optional string pin = 4;
@@ -30,7 +30,7 @@ message RegistrationProvisionMessage {
string restoreMethodToken = 9;
bytes aciIdentityKeyPublic = 10;
bytes aciIdentityKeyPrivate = 11;
bytes pniIdentityKeyPublic = 12;
bytes pniIdentityKeyPrivate = 13;
optional bytes pniIdentityKeyPublic = 12;
optional bytes pniIdentityKeyPrivate = 13;
uint64 backupVersion = 14;
}
}