mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-04-20 00:29:11 +01:00
Add quickstart variant that launches with predefined credentials.
This commit is contained in:
committed by
Alex Hart
parent
9922621945
commit
e67307a961
@@ -65,6 +65,7 @@ import org.thoughtcrime.securesms.megaphone.Megaphones
|
||||
import org.thoughtcrime.securesms.payments.DataExportUtil
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId
|
||||
import org.thoughtcrime.securesms.registration.data.QuickstartCredentialExporter
|
||||
import org.thoughtcrime.securesms.storage.StorageSyncHelper
|
||||
import org.thoughtcrime.securesms.util.ConversationUtil
|
||||
import org.thoughtcrime.securesms.util.adapter.mapping.MappingAdapter
|
||||
@@ -164,6 +165,16 @@ class InternalSettingsFragment : DSLSettingsFragment(R.string.preferences__inter
|
||||
}
|
||||
)
|
||||
|
||||
if (BuildConfig.DEBUG) {
|
||||
clickPref(
|
||||
title = DSLSettingsText.from("Export quickstart credentials"),
|
||||
summary = DSLSettingsText.from("Export registration credentials to a JSON file for quickstart builds."),
|
||||
onClick = {
|
||||
exportQuickstartCredentials()
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
clickPref(
|
||||
title = DSLSettingsText.from("Unregister"),
|
||||
summary = DSLSettingsText.from("This will unregister your account without deleting it."),
|
||||
@@ -1144,6 +1155,21 @@ class InternalSettingsFragment : DSLSettingsFragment(R.string.preferences__inter
|
||||
}
|
||||
}
|
||||
|
||||
private fun exportQuickstartCredentials() {
|
||||
MaterialAlertDialogBuilder(requireContext())
|
||||
.setTitle("Export quickstart credentials?")
|
||||
.setMessage("This will export your account's private keys and credentials to an unencrypted file on disk. This is very dangerous! Only use it with test accounts.")
|
||||
.setPositiveButton("Export") { _, _ ->
|
||||
SimpleTask.run({
|
||||
QuickstartCredentialExporter.export(requireContext())
|
||||
}) { file ->
|
||||
Toast.makeText(requireContext(), "Exported to ${file.absolutePath}", Toast.LENGTH_LONG).show()
|
||||
}
|
||||
}
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.show()
|
||||
}
|
||||
|
||||
private fun promptUserForSentTimestamp() {
|
||||
val input = EditText(requireContext()).apply {
|
||||
inputType = android.text.InputType.TYPE_CLASS_NUMBER
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright 2025 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.thoughtcrime.securesms.registration.data
|
||||
|
||||
import android.content.Context
|
||||
import android.util.Base64
|
||||
import kotlinx.serialization.encodeToString
|
||||
import kotlinx.serialization.json.Json
|
||||
import org.signal.core.util.logging.Log
|
||||
import org.thoughtcrime.securesms.dependencies.AppDependencies
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
import java.io.File
|
||||
|
||||
/**
|
||||
* Exports current account registration credentials to a JSON file
|
||||
* that can be used with quickstart builds.
|
||||
*/
|
||||
object QuickstartCredentialExporter {
|
||||
|
||||
private val TAG = Log.tag(QuickstartCredentialExporter::class.java)
|
||||
|
||||
private val json = Json { prettyPrint = true }
|
||||
|
||||
fun export(context: Context): File {
|
||||
val aci = SignalStore.account.requireAci()
|
||||
val pni = SignalStore.account.requirePni()
|
||||
val e164 = SignalStore.account.requireE164()
|
||||
val servicePassword = SignalStore.account.servicePassword ?: error("No service password")
|
||||
|
||||
val aciIdentityKeyPair = SignalStore.account.aciIdentityKey
|
||||
val pniIdentityKeyPair = SignalStore.account.pniIdentityKey
|
||||
|
||||
val aciSignedPreKey = AppDependencies.protocolStore.aci().loadSignedPreKey(SignalStore.account.aciPreKeys.activeSignedPreKeyId)
|
||||
val aciLastResortKyberPreKey = AppDependencies.protocolStore.aci().loadKyberPreKey(SignalStore.account.aciPreKeys.lastResortKyberPreKeyId)
|
||||
val pniSignedPreKey = AppDependencies.protocolStore.pni().loadSignedPreKey(SignalStore.account.pniPreKeys.activeSignedPreKeyId)
|
||||
val pniLastResortKyberPreKey = AppDependencies.protocolStore.pni().loadKyberPreKey(SignalStore.account.pniPreKeys.lastResortKyberPreKeyId)
|
||||
|
||||
val self = Recipient.self()
|
||||
val profileKey = self.profileKey ?: error("No profile key")
|
||||
val profileName = self.profileName
|
||||
|
||||
val credentials = QuickstartCredentials(
|
||||
aci = aci.toString(),
|
||||
pni = pni.toString(),
|
||||
e164 = e164,
|
||||
servicePassword = servicePassword,
|
||||
aciIdentityKeyPair = Base64.encodeToString(aciIdentityKeyPair.serialize(), Base64.NO_WRAP),
|
||||
pniIdentityKeyPair = Base64.encodeToString(pniIdentityKeyPair.serialize(), Base64.NO_WRAP),
|
||||
aciSignedPreKey = Base64.encodeToString(aciSignedPreKey.serialize(), Base64.NO_WRAP),
|
||||
aciLastResortKyberPreKey = Base64.encodeToString(aciLastResortKyberPreKey.serialize(), Base64.NO_WRAP),
|
||||
pniSignedPreKey = Base64.encodeToString(pniSignedPreKey.serialize(), Base64.NO_WRAP),
|
||||
pniLastResortKyberPreKey = Base64.encodeToString(pniLastResortKyberPreKey.serialize(), Base64.NO_WRAP),
|
||||
profileKey = Base64.encodeToString(profileKey, Base64.NO_WRAP),
|
||||
registrationId = SignalStore.account.registrationId,
|
||||
pniRegistrationId = SignalStore.account.pniRegistrationId,
|
||||
profileGivenName = profileName.givenName,
|
||||
profileFamilyName = profileName.familyName
|
||||
)
|
||||
|
||||
val outputDir = context.getExternalFilesDir(null) ?: error("No external files directory")
|
||||
val outputFile = File(outputDir, "quickstart-credentials.json")
|
||||
outputFile.writeText(json.encodeToString(credentials))
|
||||
|
||||
Log.i(TAG, "Exported quickstart credentials to ${outputFile.absolutePath}")
|
||||
return outputFile
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright 2025 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.thoughtcrime.securesms.registration.data
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
/**
|
||||
* JSON-serializable bundle of registration credentials for quickstart builds.
|
||||
* All byte arrays are base64-encoded strings.
|
||||
*/
|
||||
@Serializable
|
||||
data class QuickstartCredentials(
|
||||
val version: Int = 1,
|
||||
val aci: String,
|
||||
val pni: String,
|
||||
val e164: String,
|
||||
val servicePassword: String,
|
||||
val aciIdentityKeyPair: String,
|
||||
val pniIdentityKeyPair: String,
|
||||
val aciSignedPreKey: String,
|
||||
val aciLastResortKyberPreKey: String,
|
||||
val pniSignedPreKey: String,
|
||||
val pniLastResortKyberPreKey: String,
|
||||
val profileKey: String,
|
||||
val registrationId: Int,
|
||||
val pniRegistrationId: Int,
|
||||
val profileGivenName: String,
|
||||
val profileFamilyName: String
|
||||
)
|
||||
Reference in New Issue
Block a user