Fix issue with using registration recovery password.

This commit is contained in:
Greyson Parrelli
2024-12-06 15:59:46 -05:00
committed by GitHub
parent 6824f09631
commit 014218782f
10 changed files with 150 additions and 80 deletions

View File

@@ -275,8 +275,6 @@ object RegistrationRepository {
withContext(Dispatchers.IO) {
val credentialSet = SvrAuthCredentialSet(svr2Credentials = svr2Credentials, svr3Credentials = svr3Credentials)
val masterKey = SvrRepository.restoreMasterKeyPreRegistration(credentialSet, pin)
SignalStore.storageService.storageKeyForInitialDataRestore = masterKey.deriveStorageServiceKey()
SignalStore.svr.setPin(pin)
return@withContext masterKey
}

View File

@@ -19,6 +19,7 @@ import kotlinx.coroutines.flow.update
import kotlinx.coroutines.flow.updateAndGet
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import org.signal.core.util.Base64
import org.signal.core.util.Stopwatch
import org.signal.core.util.isNotNullOrBlank
import org.signal.core.util.logging.Log
@@ -66,9 +67,12 @@ import org.thoughtcrime.securesms.util.Util
import org.thoughtcrime.securesms.util.dualsim.MccMncProducer
import org.whispersystems.signalservice.api.SvrNoDataException
import org.whispersystems.signalservice.api.kbs.MasterKey
import org.whispersystems.signalservice.api.svr.Svr3Credentials
import org.whispersystems.signalservice.internal.push.AuthCredentials
import org.whispersystems.signalservice.internal.push.RegistrationSessionMetadataJson
import org.whispersystems.signalservice.internal.push.RegistrationSessionMetadataResponse
import java.io.IOException
import java.nio.charset.StandardCharsets
import java.util.concurrent.TimeUnit
import kotlin.jvm.optionals.getOrNull
import kotlin.time.Duration.Companion.minutes
@@ -615,31 +619,18 @@ class RegistrationViewModel : ViewModel() {
fun verifyReRegisterWithPin(context: Context, pin: String, wrongPinHandler: () -> Unit) {
setInProgress(true)
// Local recovery password
if (RegistrationRepository.canUseLocalRecoveryPassword()) {
if (RegistrationRepository.doesPinMatchLocalHash(pin)) {
Log.d(TAG, "Found recovery password, attempting to re-register.")
viewModelScope.launch(context = coroutineExceptionHandler) {
verifyReRegisterInternal(context, pin, SignalStore.svr.masterKey)
setInProgress(false)
}
} else {
Log.d(TAG, "Entered PIN did not match local PIN hash.")
wrongPinHandler()
setInProgress(false)
}
return
}
// remote recovery password
val svr2Credentials = store.value.svr2AuthCredentials
val svr3Credentials = store.value.svr3AuthCredentials
val svr2Credentials = store.value.svr2AuthCredentials ?: SignalStore.svr.svr2AuthTokens.toSvrCredentials()
val svr3Credentials = store.value.svr3AuthCredentials ?: SignalStore.svr.svr3AuthTokens.toSvrCredentials()?.let { Svr3Credentials(it.username(), it.password(), null) }
if (svr2Credentials != null || svr3Credentials != null) {
Log.d(TAG, "Found SVR auth credentials, fetching recovery password from SVR (svr2: ${svr2Credentials != null}, svr3: ${svr3Credentials != null}).")
viewModelScope.launch(context = coroutineExceptionHandler) {
try {
val masterKey = RegistrationRepository.fetchMasterKeyFromSvrRemote(pin, svr2Credentials, svr3Credentials)
SignalStore.svr.masterKeyForInitialDataRestore = masterKey
SignalStore.svr.setPin(pin)
setRecoveryPassword(masterKey.deriveRegistrationRecoveryPassword())
updateSvrTriesRemaining(10)
verifyReRegisterInternal(context, pin, masterKey)
@@ -657,6 +648,22 @@ class RegistrationViewModel : ViewModel() {
return
}
// Local recovery password
if (RegistrationRepository.canUseLocalRecoveryPassword()) {
if (RegistrationRepository.doesPinMatchLocalHash(pin)) {
Log.d(TAG, "Found recovery password, attempting to re-register.")
viewModelScope.launch(context = coroutineExceptionHandler) {
verifyReRegisterInternal(context, pin, SignalStore.svr.masterKey)
setInProgress(false)
}
} else {
Log.d(TAG, "Entered PIN did not match local PIN hash.")
wrongPinHandler()
setInProgress(false)
}
return
}
Log.w(TAG, "Could not get credentials to skip SMS registration, aborting!")
store.update {
it.copy(canSkipSms = false, inProgress = false)
@@ -917,6 +924,31 @@ class RegistrationViewModel : ViewModel() {
setInProgress(false)
}
/** Converts the basic-auth creds we have locally into username:password pairs that are suitable for handing off to the service. */
private fun List<String?>.toSvrCredentials(): AuthCredentials? {
return this
.asSequence()
.filterNotNull()
.map { it.replace("Basic ", "").trim() }
.mapNotNull {
try {
Base64.decode(it)
} catch (e: IOException) {
Log.w(TAG, "Encountered error trying to decode a token!", e)
null
}
}
.map { String(it, StandardCharsets.ISO_8859_1) }
.mapNotNull {
val colonIndex = it.indexOf(":")
if (colonIndex < 0) {
return@mapNotNull null
}
AuthCredentials.create(it.substring(0, colonIndex), it.substring(colonIndex + 1))
}
.firstOrNull()
}
companion object {
private val TAG = Log.tag(RegistrationViewModel::class.java)