diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/RefreshAttributesJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/RefreshAttributesJob.java index 4f1c6f87ce..c0f5bec68f 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/RefreshAttributesJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/RefreshAttributesJob.java @@ -5,23 +5,23 @@ import android.text.TextUtils; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import org.signal.core.util.Base64; import org.signal.core.util.logging.Log; import org.thoughtcrime.securesms.AppCapabilities; import org.thoughtcrime.securesms.crypto.ProfileKeyUtil; import org.thoughtcrime.securesms.dependencies.AppDependencies; -import org.thoughtcrime.securesms.jobmanager.JsonJobData; import org.thoughtcrime.securesms.jobmanager.Job; +import org.thoughtcrime.securesms.jobmanager.JsonJobData; import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint; import org.thoughtcrime.securesms.keyvalue.PhoneNumberPrivacyValues.PhoneNumberDiscoverabilityMode; -import org.thoughtcrime.securesms.keyvalue.SvrValues; import org.thoughtcrime.securesms.keyvalue.SignalStore; -import org.thoughtcrime.securesms.registration.RegistrationRepository; +import org.thoughtcrime.securesms.keyvalue.SvrValues; +import org.thoughtcrime.securesms.registration.data.RegistrationRepository; import org.thoughtcrime.securesms.registration.secondary.DeviceNameCipher; import org.thoughtcrime.securesms.util.TextSecurePreferences; import org.whispersystems.signalservice.api.account.AccountAttributes; import org.whispersystems.signalservice.api.crypto.UnidentifiedAccess; import org.whispersystems.signalservice.api.push.exceptions.NetworkFailureException; -import org.signal.core.util.Base64; import java.io.IOException; import java.nio.charset.StandardCharsets; @@ -91,7 +91,7 @@ public class RefreshAttributesJob extends BaseJob { boolean universalUnidentifiedAccess = TextSecurePreferences.isUniversalUnidentifiedAccess(context); String registrationLockV2 = null; SvrValues svrValues = SignalStore.svr(); - int pniRegistrationId = new RegistrationRepository().getPniRegistrationId(); + int pniRegistrationId = RegistrationRepository.getPniRegistrationId(); String recoveryPassword = svrValues.getRecoveryPassword(); if (svrValues.isRegistrationLockEnabled()) { diff --git a/app/src/main/java/org/thoughtcrime/securesms/registration/RegistrationRepository.java b/app/src/main/java/org/thoughtcrime/securesms/registration/RegistrationRepository.java deleted file mode 100644 index 780717d30e..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/registration/RegistrationRepository.java +++ /dev/null @@ -1,80 +0,0 @@ -package org.thoughtcrime.securesms.registration; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.annotation.WorkerThread; - -import org.signal.core.util.logging.Log; -import org.signal.libsignal.protocol.IdentityKeyPair; -import org.signal.libsignal.protocol.state.KyberPreKeyRecord; -import org.signal.libsignal.protocol.state.SignedPreKeyRecord; -import org.signal.libsignal.protocol.util.KeyHelper; -import org.signal.libsignal.zkgroup.profiles.ProfileKey; -import org.thoughtcrime.securesms.crypto.PreKeyUtil; -import org.thoughtcrime.securesms.crypto.ProfileKeyUtil; -import org.thoughtcrime.securesms.crypto.storage.PreKeyMetadataStore; -import org.thoughtcrime.securesms.database.RecipientTable; -import org.thoughtcrime.securesms.database.SignalDatabase; -import org.thoughtcrime.securesms.keyvalue.SignalStore; -import org.thoughtcrime.securesms.recipients.Recipient; -import org.thoughtcrime.securesms.recipients.RecipientId; -import org.whispersystems.signalservice.api.account.PreKeyCollection; - -import java.util.Optional; - -/** - * Operations required for finalizing the registration of an account. This is - * to be used after verifying the code and registration lock (if necessary) with - * the server and being issued a UUID. - */ -public final class RegistrationRepository { - - private static final String TAG = Log.tag(RegistrationRepository.class); - - public RegistrationRepository() { - } - - public int getPniRegistrationId() { - int pniRegistrationId = SignalStore.account().getPniRegistrationId(); - if (pniRegistrationId == 0) { - pniRegistrationId = KeyHelper.generateRegistrationId(false); - SignalStore.account().setPniRegistrationId(pniRegistrationId); - } - return pniRegistrationId; - } - - public @NonNull ProfileKey getProfileKey(@NonNull String e164) { - ProfileKey profileKey = findExistingProfileKey(e164); - - if (profileKey == null) { - profileKey = ProfileKeyUtil.createNew(); - Log.i(TAG, "No profile key found, created a new one"); - } - - return profileKey; - } - - public static PreKeyCollection generateSignedAndLastResortPreKeys(IdentityKeyPair identity, PreKeyMetadataStore metadataStore) { - SignedPreKeyRecord signedPreKey = PreKeyUtil.generateSignedPreKey(metadataStore.getNextSignedPreKeyId(), identity.getPrivateKey()); - KyberPreKeyRecord lastResortKyberPreKey = PreKeyUtil.generateLastResortKyberPreKey(metadataStore.getNextKyberPreKeyId(), identity.getPrivateKey()); - - return new PreKeyCollection( - identity.getPublicKey(), - signedPreKey, - lastResortKyberPreKey - ); - } - - @WorkerThread - private static @Nullable ProfileKey findExistingProfileKey(@NonNull String e164number) { - RecipientTable recipientTable = SignalDatabase.recipients(); - Optional recipient = recipientTable.getByE164(e164number); - - if (recipient.isPresent()) { - return ProfileKeyUtil.profileKeyOrNull(Recipient.resolved(recipient.get()).getProfileKey()); - } - - return null; - } - -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/registration/VerifyAccountRepository.kt b/app/src/main/java/org/thoughtcrime/securesms/registration/VerifyAccountRepository.kt deleted file mode 100644 index 2d0b5a735f..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/registration/VerifyAccountRepository.kt +++ /dev/null @@ -1,17 +0,0 @@ -package org.thoughtcrime.securesms.registration - -import org.thoughtcrime.securesms.pin.SvrWrongPinException -import org.whispersystems.signalservice.api.SvrNoDataException -import org.whispersystems.signalservice.api.kbs.MasterKey -import java.io.IOException - -/** - * Request SMS/Phone verification codes to help prove ownership of a phone number. - */ -class VerifyAccountRepository { - - fun interface MasterKeyProducer { - @Throws(IOException::class, SvrWrongPinException::class, SvrNoDataException::class) - fun produceMasterKey(): MasterKey - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/registration/VerifyResponseProcessor.kt b/app/src/main/java/org/thoughtcrime/securesms/registration/VerifyResponseProcessor.kt index 3769a913f9..7fbe023c9b 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/registration/VerifyResponseProcessor.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/registration/VerifyResponseProcessor.kt @@ -41,4 +41,3 @@ class VerifyResponseWithoutKbs(response: ServiceResponse) : Veri return registrationLock() && getLockedException().svr2Credentials == null } } - 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 d6c089c5f3..e429aa9e58 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 @@ -45,7 +45,6 @@ import org.thoughtcrime.securesms.recipients.Recipient 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 @@ -393,7 +392,7 @@ object RegistrationRepository { /** * Submit the necessary assets as a verified account so that the user can actually use the service. */ - suspend fun registerAccount(context: Context, sessionId: String?, registrationData: RegistrationData, pin: String? = null, masterKeyProducer: VerifyAccountRepository.MasterKeyProducer? = null): RegisterAccountResult = + suspend fun registerAccount(context: Context, sessionId: String?, registrationData: RegistrationData, pin: String? = null, masterKeyProducer: MasterKeyProducer? = null): RegisterAccountResult = withContext(Dispatchers.IO) { Log.v(TAG, "registerAccount()") val api: RegistrationApi = AccountManagerFactory.getInstance().createUnauthenticated(context, registrationData.e164, SignalServiceAddress.DEFAULT_DEVICE_ID, registrationData.password).registrationApi @@ -434,8 +433,8 @@ object RegistrationRepository { SignalStore.account.generatePniIdentityKeyIfNecessary() val pniIdentity: IdentityKeyPair = SignalStore.account.pniIdentityKey - val aciPreKeyCollection = org.thoughtcrime.securesms.registration.RegistrationRepository.generateSignedAndLastResortPreKeys(aciIdentity, SignalStore.account.aciPreKeys) - val pniPreKeyCollection = org.thoughtcrime.securesms.registration.RegistrationRepository.generateSignedAndLastResortPreKeys(pniIdentity, SignalStore.account.pniPreKeys) + val aciPreKeyCollection = generateSignedAndLastResortPreKeys(aciIdentity, SignalStore.account.aciPreKeys) + val pniPreKeyCollection = generateSignedAndLastResortPreKeys(pniIdentity, SignalStore.account.pniPreKeys) val result: NetworkResult = api.registerAccount(sessionId, registrationData.recoveryPassword, accountAttributes, aciPreKeyCollection, pniPreKeyCollection, registrationData.fcmToken, true) .map { accountRegistrationResponse: VerifyAccountResponse -> @@ -589,6 +588,22 @@ object RegistrationRepository { return started == true } + private fun generateSignedAndLastResortPreKeys(identity: IdentityKeyPair, metadataStore: PreKeyMetadataStore): PreKeyCollection { + val signedPreKey = PreKeyUtil.generateSignedPreKey(metadataStore.nextSignedPreKeyId, identity.privateKey) + val lastResortKyberPreKey = PreKeyUtil.generateLastResortKyberPreKey(metadataStore.nextKyberPreKeyId, identity.privateKey) + + return PreKeyCollection( + identity.publicKey, + signedPreKey, + lastResortKyberPreKey + ) + } + + fun interface MasterKeyProducer { + @Throws(IOException::class, SvrWrongPinException::class, SvrNoDataException::class) + fun produceMasterKey(): MasterKey + } + enum class Mode(val isSmsRetrieverSupported: Boolean, val transport: PushServiceSocket.VerificationCodeTransport) { SMS_WITH_LISTENER(true, PushServiceSocket.VerificationCodeTransport.SMS), SMS_WITHOUT_LISTENER(false, PushServiceSocket.VerificationCodeTransport.SMS),