diff options
| author | Danilo M. <danix@danix.xyz> | 2026-11-04 20:08:46 +0100 |
|---|---|---|
| committer | Danilo M. <danix@danix.xyz> | 2026-11-04 20:08:46 +0100 |
| commit | 2702264af333aec83b72f056ea0739fb97717ebb (patch) | |
| tree | 1cf608ec49704b543c0ea623195be93fb8b53974 | |
| parent | 756754ac6f95deec3b3efea05a4a01a3a7a59550 (diff) | |
| download | HardenedPass-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>
| -rw-r--r-- | app/src/main/java/app/passwordstore/ui/autofill/AutofillDecryptActivity.kt | 19 |
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 { |
