aboutsummaryrefslogtreecommitdiffstats
path: root/app/src
diff options
context:
space:
mode:
authorDanilo M. <danix@danix.xyz>2026-11-04 20:08:46 +0100
committerDanilo M. <danix@danix.xyz>2026-11-04 20:08:46 +0100
commit2702264af333aec83b72f056ea0739fb97717ebb (patch)
tree1cf608ec49704b543c0ea623195be93fb8b53974 /app/src
parent756754ac6f95deec3b3efea05a4a01a3a7a59550 (diff)
downloadHardenedPass-2702264af333aec83b72f056ea0739fb97717ebb.tar.gz
HardenedPass-2702264af333aec83b72f056ea0739fb97717ebb.zip
fix(app): ask again when autofill's cached passphrase fails
A stale cached passphrase (the key's passphrase changed) made every autofill fail until the cache was cleared. A cached passphrase that fails is now not tried again: the passphrase prompt opens with its wrong passphrase message, and the passphrase typed there replaces the cached one, as in the entry view. Not yet tested on a device (autofill cannot be tested on the emulator), so the TODO item stays until it is. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'app/src')
-rw-r--r--app/src/main/java/app/passwordstore/ui/autofill/AutofillDecryptActivity.kt19
1 files changed, 15 insertions, 4 deletions
diff --git a/app/src/main/java/app/passwordstore/ui/autofill/AutofillDecryptActivity.kt b/app/src/main/java/app/passwordstore/ui/autofill/AutofillDecryptActivity.kt
index f6d5df0f..7ba4df74 100644
--- a/app/src/main/java/app/passwordstore/ui/autofill/AutofillDecryptActivity.kt
+++ b/app/src/main/java/app/passwordstore/ui/autofill/AutofillDecryptActivity.kt
@@ -97,6 +97,7 @@ class AutofillDecryptActivity : AppCompatActivity() {
/** The recipients the passphrase dialog asks for; null while it is not shown. */
private var passphraseFor by mutableStateOf<List<PGPIdentifier>?>(null)
+ private var passphraseWrong by mutableStateOf(false)
// The import's activity is still on top when its result arrives: the flow restarts on the next
// window focus, so the screen lock prompt is not shown (and evicted) behind it.
@@ -158,7 +159,7 @@ class AutofillDecryptActivity : AppCompatActivity() {
val identifiers = passphraseFor
if (identifiers != null)
PassphraseDialog(
- wrong = false,
+ wrong = passphraseWrong,
cacheEnabled = features.isEnabled(EnablePGPPassphraseCache),
clearCache = clearCache,
onSubmit = onSubmit@{ passphrase, clear ->
@@ -244,7 +245,7 @@ class AutofillDecryptActivity : AppCompatActivity() {
gpgIdentifiers.first(),
)
if (cachedPassphrase != null) {
- decryptWithPassphrase(gpgIdentifiers, cachedPassphrase)
+ decryptWithPassphrase(gpgIdentifiers, cachedPassphrase, cached = true)
} else {
askPassphrase(gpgIdentifiers)
}
@@ -253,21 +254,31 @@ class AutofillDecryptActivity : AppCompatActivity() {
}
}
- private suspend fun askPassphrase(identifiers: List<PGPIdentifier>) {
+ private suspend fun askPassphrase(identifiers: List<PGPIdentifier>, wrong: Boolean = false) {
if (!repository.isPasswordProtected(identifiers)) {
decryptWithPassphrase(identifiers, password = "")
return
}
+ passphraseWrong = wrong
passphraseFor = identifiers
}
- /** Caches [password] only when the user [typed] it, as the entry view does. */
+ /**
+ * Caches [password] only when the user [typed] it, as the entry view does. A [cached] passphrase
+ * that fails (the key's passphrase changed) is not tried again: the prompt asks for the new one,
+ * which replaces it in the cache.
+ */
private suspend fun decryptWithPassphrase(
identifiers: List<PGPIdentifier>,
password: String,
typed: Boolean = false,
+ cached: Boolean = false,
) {
val credentials = decryptCredential(File(filePath), password, identifiers, typed)
+ if (credentials == null && cached) {
+ askPassphrase(identifiers, wrong = true)
+ return
+ }
if (credentials == null) {
setResult(RESULT_CANCELED)
} else {