Skip to content
This repository was archived by the owner on Oct 15, 2024. It is now read-only.

Commit b313c42

Browse files
committed
fix(app): ensure decryption errors are captured by UI
1 parent f778eab commit b313c42

File tree

2 files changed

+36
-35
lines changed

2 files changed

+36
-35
lines changed

app/src/main/java/app/passwordstore/data/crypto/CryptoRepository.kt

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ package app.passwordstore.data.crypto
88
import app.passwordstore.crypto.GpgIdentifier
99
import app.passwordstore.crypto.PGPKeyManager
1010
import app.passwordstore.crypto.PGPainlessCryptoHandler
11+
import app.passwordstore.crypto.errors.CryptoHandlerException
12+
import com.github.michaelbull.result.Result
1113
import com.github.michaelbull.result.getAll
1214
import com.github.michaelbull.result.unwrap
1315
import java.io.ByteArrayInputStream
@@ -27,34 +29,30 @@ constructor(
2729
password: String,
2830
message: ByteArrayInputStream,
2931
out: ByteArrayOutputStream,
30-
) {
31-
withContext(Dispatchers.IO) { decryptPgp(password, message, out) }
32-
}
32+
) = withContext(Dispatchers.IO) { decryptPgp(password, message, out) }
3333

3434
suspend fun encrypt(
3535
identities: List<GpgIdentifier>,
3636
content: ByteArrayInputStream,
3737
out: ByteArrayOutputStream,
38-
) {
39-
withContext(Dispatchers.IO) { encryptPgp(identities, content, out) }
40-
}
38+
) = withContext(Dispatchers.IO) { encryptPgp(identities, content, out) }
4139

4240
private suspend fun decryptPgp(
4341
password: String,
4442
message: ByteArrayInputStream,
4543
out: ByteArrayOutputStream,
46-
) {
44+
): Result<Unit, CryptoHandlerException> {
4745
val keys = pgpKeyManager.getAllKeys().unwrap()
48-
pgpCryptoHandler.decrypt(keys, password, message, out)
46+
return pgpCryptoHandler.decrypt(keys, password, message, out)
4947
}
5048

5149
private suspend fun encryptPgp(
5250
identities: List<GpgIdentifier>,
5351
content: ByteArrayInputStream,
5452
out: ByteArrayOutputStream,
55-
) {
56-
val keys = identities.map { ident -> pgpKeyManager.getKeyById(ident) }.getAll()
57-
pgpCryptoHandler.encrypt(
53+
): Result<Unit, CryptoHandlerException> {
54+
val keys = identities.map { id -> pgpKeyManager.getKeyById(id) }.getAll()
55+
return pgpCryptoHandler.encrypt(
5856
keys,
5957
content,
6058
out,

app/src/main/java/app/passwordstore/ui/crypto/DecryptActivity.kt

Lines changed: 27 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,13 @@ import app.passwordstore.data.password.FieldItem
1717
import app.passwordstore.databinding.DecryptLayoutBinding
1818
import app.passwordstore.ui.adapters.FieldItemAdapter
1919
import app.passwordstore.util.extensions.getString
20-
import app.passwordstore.util.extensions.isErr
2120
import app.passwordstore.util.extensions.unsafeLazy
2221
import app.passwordstore.util.extensions.viewBinding
2322
import app.passwordstore.util.settings.Constants
2423
import app.passwordstore.util.settings.PreferenceKeys
24+
import com.github.michaelbull.result.Err
25+
import com.github.michaelbull.result.Ok
2526
import com.github.michaelbull.result.runCatching
26-
import com.github.michaelbull.result.unwrapError
2727
import dagger.hilt.android.AndroidEntryPoint
2828
import java.io.ByteArrayOutputStream
2929
import java.io.File
@@ -66,7 +66,7 @@ class DecryptActivity : BasePgpActivity() {
6666
true
6767
}
6868
}
69-
decrypt(isError = false)
69+
askPassphrase(isError = false)
7070
}
7171

7272
override fun onCreateOptionsMenu(menu: Menu): Boolean {
@@ -137,7 +137,7 @@ class DecryptActivity : BasePgpActivity() {
137137
)
138138
}
139139

140-
private fun decrypt(isError: Boolean) {
140+
private fun askPassphrase(isError: Boolean) {
141141
if (retries < MAX_RETRIES) {
142142
retries += 1
143143
} else {
@@ -150,37 +150,40 @@ class DecryptActivity : BasePgpActivity() {
150150
lifecycleScope.launch(Dispatchers.Main) {
151151
dialog.password.collectLatest { value ->
152152
if (value != null) {
153-
val res = runCatching { decrypt(value) }
154-
if (res.isErr()) {
155-
logcat(ERROR) { res.unwrapError().stackTraceToString() }
156-
decrypt(isError = true)
153+
when (val result = decryptWithPassphrase(value)) {
154+
is Ok -> {
155+
val entry = passwordEntryFactory.create(result.value.toByteArray())
156+
passwordEntry = entry
157+
createPasswordUI(entry)
158+
startAutoDismissTimer()
159+
}
160+
is Err -> {
161+
logcat(ERROR) { result.error.stackTraceToString() }
162+
askPassphrase(isError = true)
163+
}
157164
}
158165
}
159166
}
160167
}
161168
dialog.show(supportFragmentManager, "PASSWORD_DIALOG")
162169
}
163170

164-
private suspend fun decrypt(password: String) {
171+
private suspend fun decryptWithPassphrase(password: String) = runCatching {
165172
val message = withContext(Dispatchers.IO) { File(fullPath).readBytes().inputStream() }
173+
val outputStream = ByteArrayOutputStream()
166174
val result =
167-
withContext(Dispatchers.IO) {
168-
val outputStream = ByteArrayOutputStream()
169-
repository.decrypt(
170-
password,
171-
message,
172-
outputStream,
173-
)
174-
outputStream
175-
}
176-
startAutoDismissTimer()
177-
178-
val entry = passwordEntryFactory.create(result.toByteArray())
179-
passwordEntry = entry
180-
createPasswordUi(entry)
175+
repository.decrypt(
176+
password,
177+
message,
178+
outputStream,
179+
)
180+
when (result) {
181+
is Ok -> outputStream
182+
is Err -> throw result.error
183+
}
181184
}
182185

183-
private suspend fun createPasswordUi(entry: PasswordEntry) =
186+
private suspend fun createPasswordUI(entry: PasswordEntry) =
184187
withContext(Dispatchers.Main) {
185188
val showPassword = settings.getBoolean(PreferenceKeys.SHOW_PASSWORD, true)
186189
invalidateOptionsMenu()

0 commit comments

Comments
 (0)