refactor: improve passphrase cache save logic
This commit is contained in:
parent
5082df2f93
commit
69bdd1518c
1 changed files with 26 additions and 32 deletions
|
@ -19,7 +19,7 @@ import app.passwordstore.data.password.FieldItem
|
||||||
import app.passwordstore.databinding.DecryptLayoutBinding
|
import app.passwordstore.databinding.DecryptLayoutBinding
|
||||||
import app.passwordstore.ui.adapters.FieldItemAdapter
|
import app.passwordstore.ui.adapters.FieldItemAdapter
|
||||||
import app.passwordstore.util.auth.BiometricAuthenticator
|
import app.passwordstore.util.auth.BiometricAuthenticator
|
||||||
import app.passwordstore.util.auth.BiometricAuthenticator.Result
|
import app.passwordstore.util.auth.BiometricAuthenticator.Result as BiometricResult
|
||||||
import app.passwordstore.util.extensions.getString
|
import app.passwordstore.util.extensions.getString
|
||||||
import app.passwordstore.util.extensions.unsafeLazy
|
import app.passwordstore.util.extensions.unsafeLazy
|
||||||
import app.passwordstore.util.extensions.viewBinding
|
import app.passwordstore.util.extensions.viewBinding
|
||||||
|
@ -78,7 +78,7 @@ class DecryptActivity : BasePGPActivity() {
|
||||||
requireKeysExist { decrypt(isError = false, authResult) }
|
requireKeysExist { decrypt(isError = false, authResult) }
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
requireKeysExist { decrypt(isError = false, Result.CanceledByUser) }
|
requireKeysExist { decrypt(isError = false, BiometricResult.CanceledByUser) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -151,24 +151,24 @@ class DecryptActivity : BasePGPActivity() {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun decrypt(isError: Boolean, authResult: Result) {
|
private fun decrypt(isError: Boolean, authResult: BiometricResult) {
|
||||||
val gpgIdentifiers = getPGPIdentifiers("") ?: return
|
val gpgIdentifiers = getPGPIdentifiers("") ?: return
|
||||||
lifecycleScope.launch(dispatcherProvider.main()) {
|
lifecycleScope.launch(dispatcherProvider.main()) {
|
||||||
when (authResult) {
|
when (authResult) {
|
||||||
// Internally handled by the prompt dialog
|
// Internally handled by the prompt dialog
|
||||||
is Result.Retry -> {}
|
is BiometricResult.Retry -> {}
|
||||||
// If the dialog is dismissed for any reason, prompt for passphrase
|
// If the dialog is dismissed for any reason, prompt for passphrase
|
||||||
is Result.CanceledByUser,
|
is BiometricResult.CanceledByUser,
|
||||||
is Result.CanceledBySystem,
|
is BiometricResult.CanceledBySystem,
|
||||||
is Result.Failure,
|
is BiometricResult.Failure,
|
||||||
is Result.HardwareUnavailableOrDisabled ->
|
is BiometricResult.HardwareUnavailableOrDisabled ->
|
||||||
askPassphrase(isError, gpgIdentifiers, authResult)
|
askPassphrase(isError, gpgIdentifiers, authResult)
|
||||||
//
|
//
|
||||||
is Result.Success -> {
|
is BiometricResult.Success -> {
|
||||||
val cachedPassphrase =
|
val cachedPassphrase =
|
||||||
passphraseCache.retrieveCachedPassphrase(this@DecryptActivity, gpgIdentifiers.first())
|
passphraseCache.retrieveCachedPassphrase(this@DecryptActivity, gpgIdentifiers.first())
|
||||||
if (cachedPassphrase != null) {
|
if (cachedPassphrase != null) {
|
||||||
decryptWithCachedPassphrase(cachedPassphrase, gpgIdentifiers, authResult)
|
decryptWithPassphrase(cachedPassphrase, gpgIdentifiers, authResult)
|
||||||
} else {
|
} else {
|
||||||
askPassphrase(isError, gpgIdentifiers, authResult)
|
askPassphrase(isError, gpgIdentifiers, authResult)
|
||||||
}
|
}
|
||||||
|
@ -180,7 +180,7 @@ class DecryptActivity : BasePGPActivity() {
|
||||||
private fun askPassphrase(
|
private fun askPassphrase(
|
||||||
isError: Boolean,
|
isError: Boolean,
|
||||||
gpgIdentifiers: List<PGPIdentifier>,
|
gpgIdentifiers: List<PGPIdentifier>,
|
||||||
authResult: Result,
|
authResult: BiometricResult,
|
||||||
) {
|
) {
|
||||||
if (retries < MAX_RETRIES) {
|
if (retries < MAX_RETRIES) {
|
||||||
retries += 1
|
retries += 1
|
||||||
|
@ -194,39 +194,33 @@ class DecryptActivity : BasePGPActivity() {
|
||||||
dialog.show(supportFragmentManager, "PASSWORD_DIALOG")
|
dialog.show(supportFragmentManager, "PASSWORD_DIALOG")
|
||||||
dialog.setFragmentResultListener(PasswordDialog.PASSWORD_RESULT_KEY) { key, bundle ->
|
dialog.setFragmentResultListener(PasswordDialog.PASSWORD_RESULT_KEY) { key, bundle ->
|
||||||
if (key == PasswordDialog.PASSWORD_RESULT_KEY) {
|
if (key == PasswordDialog.PASSWORD_RESULT_KEY) {
|
||||||
val value = bundle.getString(PasswordDialog.PASSWORD_RESULT_KEY)!!
|
val passphrase = bundle.getString(PasswordDialog.PASSWORD_RESULT_KEY)!!
|
||||||
lifecycleScope.launch(dispatcherProvider.main()) {
|
lifecycleScope.launch(dispatcherProvider.main()) {
|
||||||
when (val result = decryptWithPassphrase(value, gpgIdentifiers)) {
|
decryptWithPassphrase(passphrase, gpgIdentifiers, authResult) {
|
||||||
is Ok -> {
|
passphraseCache.cachePassphrase(
|
||||||
val entry = passwordEntryFactory.create(result.value.toByteArray())
|
this@DecryptActivity,
|
||||||
passwordEntry = entry
|
gpgIdentifiers.first(),
|
||||||
createPasswordUI(entry)
|
passphrase
|
||||||
startAutoDismissTimer()
|
)
|
||||||
if (authResult is Result.Success) {
|
|
||||||
passphraseCache.cachePassphrase(this@DecryptActivity, gpgIdentifiers.first(), value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
is Err -> {
|
|
||||||
logcat(ERROR) { result.error.stackTraceToString() }
|
|
||||||
askPassphrase(isError = true, gpgIdentifiers, authResult)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun decryptWithCachedPassphrase(
|
private suspend fun decryptWithPassphrase(
|
||||||
passphrase: String,
|
passphrase: String,
|
||||||
identifiers: List<PGPIdentifier>,
|
identifiers: List<PGPIdentifier>,
|
||||||
authResult: Result,
|
authResult: BiometricResult,
|
||||||
|
onSuccess: suspend () -> Unit = {},
|
||||||
) {
|
) {
|
||||||
when (val result = decryptWithPassphrase(passphrase, identifiers)) {
|
when (val result = decryptPGPStream(passphrase, identifiers)) {
|
||||||
is Ok -> {
|
is Ok -> {
|
||||||
val entry = passwordEntryFactory.create(result.value.toByteArray())
|
val entry = passwordEntryFactory.create(result.value.toByteArray())
|
||||||
passwordEntry = entry
|
passwordEntry = entry
|
||||||
createPasswordUI(entry)
|
createPasswordUI(entry)
|
||||||
startAutoDismissTimer()
|
startAutoDismissTimer()
|
||||||
|
onSuccess()
|
||||||
}
|
}
|
||||||
is Err -> {
|
is Err -> {
|
||||||
logcat(ERROR) { result.error.stackTraceToString() }
|
logcat(ERROR) { result.error.stackTraceToString() }
|
||||||
|
@ -235,15 +229,15 @@ class DecryptActivity : BasePGPActivity() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun decryptWithPassphrase(
|
private suspend fun decryptPGPStream(
|
||||||
password: String,
|
passphrase: String,
|
||||||
gpgIdentifiers: List<PGPIdentifier>,
|
gpgIdentifiers: List<PGPIdentifier>,
|
||||||
) = runCatching {
|
) = runCatching {
|
||||||
val message = withContext(dispatcherProvider.io()) { File(fullPath).readBytes().inputStream() }
|
val message = withContext(dispatcherProvider.io()) { File(fullPath).readBytes().inputStream() }
|
||||||
val outputStream = ByteArrayOutputStream()
|
val outputStream = ByteArrayOutputStream()
|
||||||
val result =
|
val result =
|
||||||
repository.decrypt(
|
repository.decrypt(
|
||||||
password,
|
passphrase,
|
||||||
gpgIdentifiers,
|
gpgIdentifiers,
|
||||||
message,
|
message,
|
||||||
outputStream,
|
outputStream,
|
||||||
|
|
Loading…
Reference in a new issue