enabling pgp passphrase cache with authentication (#3124)

* enabling pgp passphrase cache with authentication

* clear passphrase cache on first autofill decrypt after screen off

---------

Co-authored-by: Alexander Grahn <me@null.org>
This commit is contained in:
agrahn 2024-07-20 17:46:26 +02:00 committed by GitHub
parent 3062c9233e
commit 763fa9e459
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 37 additions and 27 deletions

View file

@ -13,6 +13,7 @@ import android.os.Bundle
import android.view.autofill.AutofillManager import android.view.autofill.AutofillManager
import androidx.fragment.app.setFragmentResultListener import androidx.fragment.app.setFragmentResultListener
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import app.passwordstore.Application.Companion.screenWasOff
import app.passwordstore.R import app.passwordstore.R
import app.passwordstore.crypto.PGPIdentifier import app.passwordstore.crypto.PGPIdentifier
import app.passwordstore.data.crypto.PGPPassphraseCache import app.passwordstore.data.crypto.PGPPassphraseCache
@ -28,6 +29,7 @@ import app.passwordstore.util.autofill.DirectoryStructure
import app.passwordstore.util.extensions.asLog import app.passwordstore.util.extensions.asLog
import app.passwordstore.util.features.Feature.EnablePGPPassphraseCache import app.passwordstore.util.features.Feature.EnablePGPPassphraseCache
import app.passwordstore.util.features.Features import app.passwordstore.util.features.Features
import app.passwordstore.util.settings.PreferenceKeys
import com.github.androidpasswordstore.autofillparser.AutofillAction import com.github.androidpasswordstore.autofillparser.AutofillAction
import com.github.androidpasswordstore.autofillparser.Credentials import com.github.androidpasswordstore.autofillparser.Credentials
import com.github.michaelbull.result.getOrElse import com.github.michaelbull.result.getOrElse
@ -110,6 +112,12 @@ class AutofillDecryptActivity : BasePGPActivity() {
askPassphrase(filePath, gpgIdentifiers, clientState, action) askPassphrase(filePath, gpgIdentifiers, clientState, action)
// //
is Result.Success -> { is Result.Success -> {
/* clear passphrase cache on first use after application startup or if screen was off;
also make sure to purge a stale cache after caching has been disabled via PGP settings */
if (screenWasOff && settings.getBoolean(PreferenceKeys.CLEAR_PASSPHRASE_CACHE, true)) {
passphraseCache.clearAllCachedPassphrases(this@AutofillDecryptActivity)
screenWasOff = false
}
val cachedPassphrase = val cachedPassphrase =
passphraseCache.retrieveCachedPassphrase( passphraseCache.retrieveCachedPassphrase(
this@AutofillDecryptActivity, this@AutofillDecryptActivity,

View file

@ -168,8 +168,9 @@ class DecryptActivity : BasePGPActivity() {
askPassphrase(isError, gpgIdentifiers, authResult) askPassphrase(isError, gpgIdentifiers, authResult)
// //
is BiometricResult.Success -> { is BiometricResult.Success -> {
// clear passphrase cache on first use after application startup or if screen was off /* clear passphrase cache on first use after application startup or if screen was off;
if (screenWasOff && settings.getBoolean(PreferenceKeys.CLEAR_PASSPHRASE_CACHE, false)) { also make sure to purge a stale cache after caching has been disabled via PGP settings */
if (screenWasOff && settings.getBoolean(PreferenceKeys.CLEAR_PASSPHRASE_CACHE, true)) {
passphraseCache.clearAllCachedPassphrases(this@DecryptActivity) passphraseCache.clearAllCachedPassphrases(this@DecryptActivity)
screenWasOff = false screenWasOff = false
} }

View file

@ -5,6 +5,7 @@
package app.passwordstore.ui.settings package app.passwordstore.ui.settings
import androidx.core.content.edit
import androidx.fragment.app.FragmentActivity import androidx.fragment.app.FragmentActivity
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import app.passwordstore.R import app.passwordstore.R
@ -12,6 +13,7 @@ import app.passwordstore.data.crypto.PGPPassphraseCache
import app.passwordstore.ui.pgp.PGPKeyListActivity import app.passwordstore.ui.pgp.PGPKeyListActivity
import app.passwordstore.util.auth.BiometricAuthenticator import app.passwordstore.util.auth.BiometricAuthenticator
import app.passwordstore.util.extensions.launchActivity import app.passwordstore.util.extensions.launchActivity
import app.passwordstore.util.extensions.sharedPrefs
import app.passwordstore.util.features.Feature import app.passwordstore.util.features.Feature
import app.passwordstore.util.settings.PreferenceKeys import app.passwordstore.util.settings.PreferenceKeys
import de.Maxr1998.modernpreferences.PreferenceScreen import de.Maxr1998.modernpreferences.PreferenceScreen
@ -46,16 +48,24 @@ class PGPSettings(
summaryRes = R.string.pref_passphrase_cache_summary summaryRes = R.string.pref_passphrase_cache_summary
defaultValue = false defaultValue = false
onCheckedChange { checked -> onCheckedChange { checked ->
if (!checked && BiometricAuthenticator.canAuthenticate(activity)) { if (checked) {
BiometricAuthenticator.authenticate( if (BiometricAuthenticator.canAuthenticate(activity)) {
activity, BiometricAuthenticator.authenticate(
R.string.pref_passphrase_cache_authenticate_clear, activity,
) { R.string.pref_passphrase_cache_authenticate_enable,
if (it is BiometricAuthenticator.Result.Success) ) {
activity.lifecycleScope.launch { if (!(it is BiometricAuthenticator.Result.Success))
passphraseCache.clearAllCachedPassphrases(activity) activity.sharedPrefs.edit {
} putBoolean(Feature.EnablePGPPassphraseCache.configKey, false)
} }
}
} else
activity.sharedPrefs.edit {
putBoolean(Feature.EnablePGPPassphraseCache.configKey, false)
}
} else {
activity.sharedPrefs.edit { remove(PreferenceKeys.CLEAR_PASSPHRASE_CACHE) }
activity.lifecycleScope.launch { passphraseCache.clearAllCachedPassphrases(activity) }
} }
true true
} }
@ -64,21 +74,12 @@ class PGPSettings(
dependency = Feature.EnablePGPPassphraseCache.configKey dependency = Feature.EnablePGPPassphraseCache.configKey
titleRes = R.string.pref_passphrase_cache_auto_clear_title titleRes = R.string.pref_passphrase_cache_auto_clear_title
summaryRes = R.string.pref_passphrase_cache_auto_clear_summary summaryRes = R.string.pref_passphrase_cache_auto_clear_summary
defaultValue = false defaultValue = true
/* clear cache once when unchecking; this is to prevent a malicious user /* clear cache once when unchecking; this is to prevent a malicious user
* from bypassing cache clearing via the settings */ * from bypassing cache clearing via the settings */
onCheckedChange { checked -> onCheckedChange { checked ->
if (!checked && BiometricAuthenticator.canAuthenticate(activity)) { if (!checked)
BiometricAuthenticator.authenticate( activity.lifecycleScope.launch { passphraseCache.clearAllCachedPassphrases(activity) }
activity,
R.string.pref_passphrase_cache_authenticate_clear,
) {
if (it is BiometricAuthenticator.Result.Success)
activity.lifecycleScope.launch {
passphraseCache.clearAllCachedPassphrases(activity)
}
}
}
true true
} }
} }

View file

@ -120,7 +120,7 @@
<string name="pref_pgp_ascii_armor_title">Cifrar co modo ASCII armor</string> <string name="pref_pgp_ascii_armor_title">Cifrar co modo ASCII armor</string>
<string name="pref_passphrase_cache_title">Permitir usar a caché para frase de paso</string> <string name="pref_passphrase_cache_title">Permitir usar a caché para frase de paso</string>
<string name="pref_passphrase_cache_summary">AVISO: esta característica funciona ben pero é experimental. Require que a pantalla estea bloqueada.</string> <string name="pref_passphrase_cache_summary">AVISO: esta característica funciona ben pero é experimental. Require que a pantalla estea bloqueada.</string>
<string name="pref_passphrase_cache_authenticate_clear">Autenticarse para poder baleirar a cache</string> <string name="pref_passphrase_cache_authenticate_enable">Autenticarse para activar a caché</string>
<string name="pref_passphrase_cache_auto_clear_title">Limpar automáticamente a frase de paso da caché</string> <string name="pref_passphrase_cache_auto_clear_title">Limpar automáticamente a frase de paso da caché</string>
<string name="pref_passphrase_cache_auto_clear_summary">Retira automáticamente a frase de paso da caché ao apagarse a pantalla</string> <string name="pref_passphrase_cache_auto_clear_summary">Retira automáticamente a frase de paso da caché ao apagarse a pantalla</string>
<!-- PasswordGenerator fragment --> <!-- PasswordGenerator fragment -->

View file

@ -116,7 +116,7 @@
<string name="pref_pgp_key_manager_title">Menedżer kluczy</string> <string name="pref_pgp_key_manager_title">Menedżer kluczy</string>
<string name="pref_pgp_ascii_armor_title">Szyfruj w trybie ASCII-armor</string> <string name="pref_pgp_ascii_armor_title">Szyfruj w trybie ASCII-armor</string>
<string name="pref_passphrase_cache_summary">UWAGA: ta funkcjonalność powinna działać poprawnie, ale jest bardzo eksperymentalna. Wymaga aktywnej blokady ekranu.</string> <string name="pref_passphrase_cache_summary">UWAGA: ta funkcjonalność powinna działać poprawnie, ale jest bardzo eksperymentalna. Wymaga aktywnej blokady ekranu.</string>
<string name="pref_passphrase_cache_authenticate_clear">Uwierzytelnij aby wyczyścić pamięć podręczną</string> <string name="pref_passphrase_cache_authenticate_enable">Uwierzytelnij aby włączyć pamięć podręczną</string>
<string name="pref_passphrase_cache_auto_clear_title">Automatycznie wyczyść pamięć podręczną haseł</string> <string name="pref_passphrase_cache_auto_clear_title">Automatycznie wyczyść pamięć podręczną haseł</string>
<string name="pref_passphrase_cache_auto_clear_summary">Czyści pamięć podręczną haseł po wyłączeniu ekranu</string> <string name="pref_passphrase_cache_auto_clear_summary">Czyści pamięć podręczną haseł po wyłączeniu ekranu</string>
<!-- PasswordGenerator fragment --> <!-- PasswordGenerator fragment -->

View file

@ -137,7 +137,7 @@
<string name="pref_pgp_ascii_armor_title">Encrypt in ASCII armor mode</string> <string name="pref_pgp_ascii_armor_title">Encrypt in ASCII armor mode</string>
<string name="pref_passphrase_cache_title">Enable passphrase caching</string> <string name="pref_passphrase_cache_title">Enable passphrase caching</string>
<string name="pref_passphrase_cache_summary">WARNING: this feature is functional but very experimental. Requires an active screen lock.</string> <string name="pref_passphrase_cache_summary">WARNING: this feature is functional but very experimental. Requires an active screen lock.</string>
<string name="pref_passphrase_cache_authenticate_clear">Authenticate to clear cache</string> <string name="pref_passphrase_cache_authenticate_enable">Authenticate to enable cache</string>
<string name="pref_passphrase_cache_auto_clear_title">Automatically clear passphrase cache</string> <string name="pref_passphrase_cache_auto_clear_title">Automatically clear passphrase cache</string>
<string name="pref_passphrase_cache_auto_clear_summary">Clears the passphrase cache when the screen is turned off</string> <string name="pref_passphrase_cache_auto_clear_summary">Clears the passphrase cache when the screen is turned off</string>