aboutsummaryrefslogtreecommitdiff
path: root/app/src/main
diff options
context:
space:
mode:
Diffstat (limited to 'app/src/main')
-rw-r--r--app/src/main/java/app/passwordstore/injection/ssh/SSHKeyManagerModule.kt21
-rw-r--r--app/src/main/java/app/passwordstore/ui/settings/RepositorySettings.kt12
-rw-r--r--app/src/main/java/app/passwordstore/ui/settings/SettingsActivity.kt8
-rw-r--r--app/src/main/java/app/passwordstore/ui/sshkeygen/ShowSshKeyFragment.kt9
-rw-r--r--app/src/main/java/app/passwordstore/ui/sshkeygen/SshKeyGenActivity.kt39
-rw-r--r--app/src/main/java/app/passwordstore/ui/sshkeygen/SshKeyImportActivity.kt33
-rw-r--r--app/src/main/java/app/passwordstore/util/git/operation/GitOperation.kt17
-rw-r--r--app/src/main/java/app/passwordstore/util/git/sshj/SshjSessionFactory.kt10
8 files changed, 55 insertions, 94 deletions
diff --git a/app/src/main/java/app/passwordstore/injection/ssh/SSHKeyManagerModule.kt b/app/src/main/java/app/passwordstore/injection/ssh/SSHKeyManagerModule.kt
deleted file mode 100644
index c5abd487..00000000
--- a/app/src/main/java/app/passwordstore/injection/ssh/SSHKeyManagerModule.kt
+++ /dev/null
@@ -1,21 +0,0 @@
-package app.passwordstore.injection.ssh
-
-import android.content.Context
-import app.passwordstore.ssh.SSHKeyManager
-import dagger.Module
-import dagger.Provides
-import dagger.Reusable
-import dagger.hilt.InstallIn
-import dagger.hilt.android.qualifiers.ApplicationContext
-import dagger.hilt.components.SingletonComponent
-
-@Module
-@InstallIn(SingletonComponent::class)
-object SSHKeyManagerModule {
-
- @Provides
- @Reusable
- fun provideSSHKeyManager(@ApplicationContext context: Context): SSHKeyManager {
- return SSHKeyManager(context)
- }
-}
diff --git a/app/src/main/java/app/passwordstore/ui/settings/RepositorySettings.kt b/app/src/main/java/app/passwordstore/ui/settings/RepositorySettings.kt
index 462924ac..c6c30b88 100644
--- a/app/src/main/java/app/passwordstore/ui/settings/RepositorySettings.kt
+++ b/app/src/main/java/app/passwordstore/ui/settings/RepositorySettings.kt
@@ -15,7 +15,6 @@ import androidx.fragment.app.FragmentActivity
import app.passwordstore.R
import app.passwordstore.data.repo.PasswordRepository
import app.passwordstore.injection.prefs.GitPreferences
-import app.passwordstore.ssh.SSHKeyManager
import app.passwordstore.ui.git.config.GitConfigActivity
import app.passwordstore.ui.git.config.GitServerConfigActivity
import app.passwordstore.ui.proxy.ProxySelectorActivity
@@ -27,6 +26,7 @@ import app.passwordstore.util.extensions.launchActivity
import app.passwordstore.util.extensions.sharedPrefs
import app.passwordstore.util.extensions.snackbar
import app.passwordstore.util.extensions.unsafeLazy
+import app.passwordstore.util.git.sshj.SshKey
import app.passwordstore.util.settings.GitSettings
import app.passwordstore.util.settings.PreferenceKeys
import com.github.michaelbull.result.onFailure
@@ -42,13 +42,11 @@ import de.Maxr1998.modernpreferences.helpers.onClick
import de.Maxr1998.modernpreferences.helpers.pref
import de.Maxr1998.modernpreferences.helpers.switch
-class RepositorySettings(
- private val activity: FragmentActivity,
- private val sshKeyManager: SSHKeyManager,
-) : SettingsProvider {
+class RepositorySettings(private val activity: FragmentActivity) : SettingsProvider {
+
private val generateSshKey =
activity.registerForActivityResult(StartActivityForResult()) {
- showSshKeyPref?.visible = sshKeyManager.canShowPublicKey()
+ showSshKeyPref?.visible = SshKey.canShowSshPublicKey
}
private val hiltEntryPoint by unsafeLazy {
@@ -113,7 +111,7 @@ class RepositorySettings(
showSshKeyPref =
pref(PreferenceKeys.SSH_SEE_KEY) {
titleRes = R.string.pref_ssh_see_key_title
- visible = PasswordRepository.isGitRepo() && sshKeyManager.canShowPublicKey()
+ visible = PasswordRepository.isGitRepo() && SshKey.canShowSshPublicKey
onClick {
ShowSshKeyFragment().show(activity.supportFragmentManager, "public_key")
true
diff --git a/app/src/main/java/app/passwordstore/ui/settings/SettingsActivity.kt b/app/src/main/java/app/passwordstore/ui/settings/SettingsActivity.kt
index 697d0156..30e2b1b0 100644
--- a/app/src/main/java/app/passwordstore/ui/settings/SettingsActivity.kt
+++ b/app/src/main/java/app/passwordstore/ui/settings/SettingsActivity.kt
@@ -11,24 +11,19 @@ import androidx.appcompat.app.AppCompatActivity
import androidx.core.os.BundleCompat
import app.passwordstore.R
import app.passwordstore.databinding.ActivityPreferenceRecyclerviewBinding
-import app.passwordstore.ssh.SSHKeyManager
import app.passwordstore.util.extensions.viewBinding
import com.google.android.material.dialog.MaterialAlertDialogBuilder
-import dagger.hilt.android.AndroidEntryPoint
import de.Maxr1998.modernpreferences.Preference
import de.Maxr1998.modernpreferences.PreferencesAdapter
import de.Maxr1998.modernpreferences.helpers.screen
import de.Maxr1998.modernpreferences.helpers.subScreen
-import javax.inject.Inject
-@AndroidEntryPoint
class SettingsActivity : AppCompatActivity() {
- @Inject lateinit var sshKeyManager: SSHKeyManager
- private lateinit var repositorySettings: RepositorySettings
private val miscSettings = MiscSettings(this)
private val autofillSettings = AutofillSettings(this)
private val passwordSettings = PasswordSettings(this)
+ private val repositorySettings = RepositorySettings(this)
private val generalSettings = GeneralSettings(this)
private val pgpSettings = PGPSettings(this)
@@ -40,7 +35,6 @@ class SettingsActivity : AppCompatActivity() {
super.onCreate(savedInstanceState)
setContentView(binding.root)
Preference.Config.dialogBuilderFactory = { context -> MaterialAlertDialogBuilder(context) }
- repositorySettings = RepositorySettings(this, sshKeyManager)
val screen =
screen(this) {
subScreen {
diff --git a/app/src/main/java/app/passwordstore/ui/sshkeygen/ShowSshKeyFragment.kt b/app/src/main/java/app/passwordstore/ui/sshkeygen/ShowSshKeyFragment.kt
index 4f52b540..a42d6aa1 100644
--- a/app/src/main/java/app/passwordstore/ui/sshkeygen/ShowSshKeyFragment.kt
+++ b/app/src/main/java/app/passwordstore/ui/sshkeygen/ShowSshKeyFragment.kt
@@ -9,19 +9,14 @@ import android.content.Intent
import android.os.Bundle
import androidx.fragment.app.DialogFragment
import app.passwordstore.R
-import app.passwordstore.ssh.SSHKeyManager
+import app.passwordstore.util.git.sshj.SshKey
import com.google.android.material.dialog.MaterialAlertDialogBuilder
-import dagger.hilt.android.AndroidEntryPoint
-import javax.inject.Inject
-@AndroidEntryPoint
class ShowSshKeyFragment : DialogFragment() {
- @Inject lateinit var sshKeyManager: SSHKeyManager
-
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
val activity = requireActivity()
- val publicKey = sshKeyManager.publicKey()
+ val publicKey = SshKey.sshPublicKey
return MaterialAlertDialogBuilder(requireActivity()).run {
setMessage(getString(R.string.ssh_keygen_message, publicKey))
setTitle(R.string.your_public_key)
diff --git a/app/src/main/java/app/passwordstore/ui/sshkeygen/SshKeyGenActivity.kt b/app/src/main/java/app/passwordstore/ui/sshkeygen/SshKeyGenActivity.kt
index 34749e4c..68d5a40c 100644
--- a/app/src/main/java/app/passwordstore/ui/sshkeygen/SshKeyGenActivity.kt
+++ b/app/src/main/java/app/passwordstore/ui/sshkeygen/SshKeyGenActivity.kt
@@ -17,13 +17,12 @@ import androidx.lifecycle.lifecycleScope
import app.passwordstore.R
import app.passwordstore.databinding.ActivitySshKeygenBinding
import app.passwordstore.injection.prefs.GitPreferences
-import app.passwordstore.ssh.SSHKeyAlgorithm
-import app.passwordstore.ssh.SSHKeyManager
import app.passwordstore.util.auth.BiometricAuthenticator
import app.passwordstore.util.auth.BiometricAuthenticator.Result
import app.passwordstore.util.coroutines.DispatcherProvider
import app.passwordstore.util.extensions.keyguardManager
import app.passwordstore.util.extensions.viewBinding
+import app.passwordstore.util.git.sshj.SshKey
import com.github.michaelbull.result.fold
import com.github.michaelbull.result.runCatching
import com.google.android.material.dialog.MaterialAlertDialogBuilder
@@ -34,13 +33,24 @@ import kotlin.coroutines.suspendCoroutine
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
+private enum class KeyGenType(val generateKey: suspend (requireAuthentication: Boolean) -> Unit) {
+ Rsa({ requireAuthentication ->
+ SshKey.generateKeystoreNativeKey(SshKey.Algorithm.Rsa, requireAuthentication)
+ }),
+ Ecdsa({ requireAuthentication ->
+ SshKey.generateKeystoreNativeKey(SshKey.Algorithm.Ecdsa, requireAuthentication)
+ }),
+ Ed25519({ requireAuthentication ->
+ SshKey.generateKeystoreWrappedEd25519Key(requireAuthentication)
+ }),
+}
+
@AndroidEntryPoint
class SshKeyGenActivity : AppCompatActivity() {
- private var sshKeyAlgorithm = SSHKeyAlgorithm.ECDSA
+ private var keyGenType = KeyGenType.Ecdsa
private val binding by viewBinding(ActivitySshKeygenBinding::inflate)
@GitPreferences @Inject lateinit var gitPrefs: SharedPreferences
- @Inject lateinit var sshKeyManager: SSHKeyManager
@Inject lateinit var dispatcherProvider: DispatcherProvider
override fun onCreate(savedInstanceState: Bundle?) {
@@ -49,7 +59,7 @@ class SshKeyGenActivity : AppCompatActivity() {
supportActionBar?.setDisplayHomeAsUpEnabled(true)
with(binding) {
generate.setOnClickListener {
- if (sshKeyManager.keyExists()) {
+ if (SshKey.exists) {
MaterialAlertDialogBuilder(this@SshKeyGenActivity).run {
setTitle(R.string.ssh_keygen_existing_title)
setMessage(R.string.ssh_keygen_existing_message)
@@ -70,18 +80,18 @@ class SshKeyGenActivity : AppCompatActivity() {
keyTypeExplanation.setText(R.string.ssh_keygen_explanation_ecdsa)
keyTypeGroup.addOnButtonCheckedListener { _, checkedId, isChecked ->
if (isChecked) {
- sshKeyAlgorithm =
+ keyGenType =
when (checkedId) {
- R.id.key_type_ed25519 -> SSHKeyAlgorithm.ED25519
- R.id.key_type_ecdsa -> SSHKeyAlgorithm.ECDSA
- R.id.key_type_rsa -> SSHKeyAlgorithm.RSA
+ R.id.key_type_ed25519 -> KeyGenType.Ed25519
+ R.id.key_type_ecdsa -> KeyGenType.Ecdsa
+ R.id.key_type_rsa -> KeyGenType.Rsa
else -> throw IllegalStateException("Impossible key type selection")
}
keyTypeExplanation.setText(
- when (sshKeyAlgorithm) {
- SSHKeyAlgorithm.ED25519 -> R.string.ssh_keygen_explanation_ed25519
- SSHKeyAlgorithm.ECDSA -> R.string.ssh_keygen_explanation_ecdsa
- SSHKeyAlgorithm.RSA -> R.string.ssh_keygen_explanation_rsa
+ when (keyGenType) {
+ KeyGenType.Ed25519 -> R.string.ssh_keygen_explanation_ed25519
+ KeyGenType.Ecdsa -> R.string.ssh_keygen_explanation_ecdsa
+ KeyGenType.Rsa -> R.string.ssh_keygen_explanation_rsa
}
)
}
@@ -127,10 +137,9 @@ class SshKeyGenActivity : AppCompatActivity() {
if (result !is Result.Success)
throw UserNotAuthenticatedException(getString(R.string.biometric_auth_generic_failure))
}
- sshKeyManager.generateKey(sshKeyAlgorithm, requireAuthentication)
+ keyGenType.generateKey(requireAuthentication)
}
}
- // Check if we still need this
gitPrefs.edit { remove("ssh_key_local_passphrase") }
binding.generate.apply {
text = getString(R.string.ssh_keygen_generate)
diff --git a/app/src/main/java/app/passwordstore/ui/sshkeygen/SshKeyImportActivity.kt b/app/src/main/java/app/passwordstore/ui/sshkeygen/SshKeyImportActivity.kt
index a5d276ae..99b3bf3f 100644
--- a/app/src/main/java/app/passwordstore/ui/sshkeygen/SshKeyImportActivity.kt
+++ b/app/src/main/java/app/passwordstore/ui/sshkeygen/SshKeyImportActivity.kt
@@ -10,21 +10,14 @@ import android.os.Bundle
import android.widget.Toast
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AppCompatActivity
-import androidx.lifecycle.lifecycleScope
import app.passwordstore.R
-import app.passwordstore.ssh.SSHKeyManager
+import app.passwordstore.util.git.sshj.SshKey
import com.github.michaelbull.result.onFailure
import com.github.michaelbull.result.runCatching
import com.google.android.material.dialog.MaterialAlertDialogBuilder
-import dagger.hilt.android.AndroidEntryPoint
-import javax.inject.Inject
-import kotlinx.coroutines.launch
-@AndroidEntryPoint
class SshKeyImportActivity : AppCompatActivity() {
- @Inject lateinit var sshKeyManager: SSHKeyManager
-
private val sshKeyImportAction =
registerForActivityResult(ActivityResultContracts.OpenDocument()) { uri: Uri? ->
if (uri == null) {
@@ -32,17 +25,15 @@ class SshKeyImportActivity : AppCompatActivity() {
return@registerForActivityResult
}
runCatching {
- lifecycleScope.launch {
- sshKeyManager.importKey(uri)
- Toast.makeText(
- this@SshKeyImportActivity,
- resources.getString(R.string.ssh_key_success_dialog_title),
- Toast.LENGTH_LONG
- )
- .show()
- setResult(RESULT_OK)
- finish()
- }
+ SshKey.import(uri)
+ Toast.makeText(
+ this,
+ resources.getString(R.string.ssh_key_success_dialog_title),
+ Toast.LENGTH_LONG
+ )
+ .show()
+ setResult(RESULT_OK)
+ finish()
}
.onFailure { e ->
MaterialAlertDialogBuilder(this)
@@ -55,8 +46,8 @@ class SshKeyImportActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
- if (sshKeyManager.keyExists()) {
- MaterialAlertDialogBuilder(this@SshKeyImportActivity).run {
+ if (SshKey.exists) {
+ MaterialAlertDialogBuilder(this).run {
setTitle(R.string.ssh_keygen_existing_title)
setMessage(R.string.ssh_keygen_existing_message)
setPositiveButton(R.string.ssh_keygen_existing_replace) { _, _ -> importSshKey() }
diff --git a/app/src/main/java/app/passwordstore/util/git/operation/GitOperation.kt b/app/src/main/java/app/passwordstore/util/git/operation/GitOperation.kt
index 199fde94..89194b79 100644
--- a/app/src/main/java/app/passwordstore/util/git/operation/GitOperation.kt
+++ b/app/src/main/java/app/passwordstore/util/git/operation/GitOperation.kt
@@ -9,7 +9,6 @@ import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.FragmentActivity
import app.passwordstore.R
import app.passwordstore.data.repo.PasswordRepository
-import app.passwordstore.ssh.SSHKeyManager
import app.passwordstore.ui.sshkeygen.SshKeyGenActivity
import app.passwordstore.ui.sshkeygen.SshKeyImportActivity
import app.passwordstore.util.auth.BiometricAuthenticator
@@ -21,6 +20,7 @@ import app.passwordstore.util.coroutines.DispatcherProvider
import app.passwordstore.util.extensions.launchActivity
import app.passwordstore.util.git.GitCommandExecutor
import app.passwordstore.util.git.sshj.SshAuthMethod
+import app.passwordstore.util.git.sshj.SshKey
import app.passwordstore.util.git.sshj.SshjSessionFactory
import app.passwordstore.util.settings.AuthMode
import com.github.michaelbull.result.Err
@@ -67,11 +67,7 @@ abstract class GitOperation(protected val callingActivity: FragmentActivity) {
private val hostKeyFile = callingActivity.filesDir.resolve(".host_key")
private var sshSessionFactory: SshjSessionFactory? = null
private val hiltEntryPoint =
- EntryPointAccessors.fromApplication(
- callingActivity.applicationContext,
- GitOperationEntryPoint::class.java
- )
- private val sshKeyManager = hiltEntryPoint.sshKeyManager()
+ EntryPointAccessors.fromApplication<GitOperationEntryPoint>(callingActivity)
protected val repository = PasswordRepository.repository!!
protected val git = Git(repository)
private val authActivity
@@ -121,7 +117,8 @@ abstract class GitOperation(protected val callingActivity: FragmentActivity) {
authMethod: SshAuthMethod,
credentialsProvider: CredentialsProvider? = null
) {
- sshSessionFactory = SshjSessionFactory(authMethod, hostKeyFile, sshKeyManager, hiltEntryPoint.dispatcherProvider())
+ sshSessionFactory =
+ SshjSessionFactory(authMethod, hostKeyFile, hiltEntryPoint.dispatcherProvider())
commands.filterIsInstance<TransportCommand<*, *>>().forEach { command ->
command.setTransportConfigCallback { transport: Transport ->
(transport as? SshTransport)?.sshSessionFactory = sshSessionFactory
@@ -169,8 +166,8 @@ abstract class GitOperation(protected val callingActivity: FragmentActivity) {
suspend fun executeAfterAuthentication(authMode: AuthMode): Result<Unit, Throwable> {
when (authMode) {
AuthMode.SshKey ->
- if (sshKeyManager.keyExists()) {
- if (sshKeyManager.needsAuthentication()) {
+ if (SshKey.exists) {
+ if (SshKey.mustAuthenticate) {
val result =
withContext(hiltEntryPoint.dispatcherProvider().main()) {
suspendCoroutine { cont ->
@@ -247,8 +244,6 @@ abstract class GitOperation(protected val callingActivity: FragmentActivity) {
@EntryPoint
@InstallIn(SingletonComponent::class)
interface GitOperationEntryPoint {
- fun sshKeyManager(): SSHKeyManager
-
fun dispatcherProvider(): DispatcherProvider
}
}
diff --git a/app/src/main/java/app/passwordstore/util/git/sshj/SshjSessionFactory.kt b/app/src/main/java/app/passwordstore/util/git/sshj/SshjSessionFactory.kt
index 86416cd6..5e11a636 100644
--- a/app/src/main/java/app/passwordstore/util/git/sshj/SshjSessionFactory.kt
+++ b/app/src/main/java/app/passwordstore/util/git/sshj/SshjSessionFactory.kt
@@ -6,7 +6,6 @@ package app.passwordstore.util.git.sshj
import android.util.Base64
import androidx.appcompat.app.AppCompatActivity
-import app.passwordstore.ssh.SSHKeyManager
import app.passwordstore.util.coroutines.DispatcherProvider
import app.passwordstore.util.git.operation.CredentialFinder
import app.passwordstore.util.settings.AuthMode
@@ -71,7 +70,6 @@ abstract class InteractivePasswordFinder(private val dispatcherProvider: Dispatc
class SshjSessionFactory(
private val authMethod: SshAuthMethod,
private val hostKeyFile: File,
- private val sshKeyManager: SSHKeyManager,
private val dispatcherProvider: DispatcherProvider,
) : SshSessionFactory() {
@@ -84,7 +82,7 @@ class SshjSessionFactory(
tms: Int
): RemoteSession {
return currentSession
- ?: SshjSession(uri, uri.user, authMethod, hostKeyFile, dispatcherProvider, sshKeyManager).connect().also {
+ ?: SshjSession(uri, uri.user, authMethod, hostKeyFile, dispatcherProvider).connect().also {
logcat { "New SSH connection created" }
currentSession = it
}
@@ -129,7 +127,6 @@ private class SshjSession(
private val authMethod: SshAuthMethod,
private val hostKeyFile: File,
private val dispatcherProvider: DispatcherProvider,
- private val sshKeyManager: SSHKeyManager,
) : RemoteSession {
private lateinit var ssh: SSHClient
@@ -165,7 +162,10 @@ private class SshjSession(
is SshAuthMethod.SshKey -> {
val pubkeyAuth =
AuthPublickey(
- sshKeyManager.keyProvider(ssh, CredentialFinder(authMethod.activity, AuthMode.SshKey, dispatcherProvider))
+ SshKey.provide(
+ ssh,
+ CredentialFinder(authMethod.activity, AuthMode.SshKey, dispatcherProvider)
+ )
)
ssh.auth(username, pubkeyAuth, passwordAuth)
}