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

Commit 3b838c4

Browse files
committed
crypto-pgp: make key lookups more robust
1 parent 78a6e37 commit 3b838c4

File tree

1 file changed

+43
-10
lines changed

1 file changed

+43
-10
lines changed

crypto-pgp/src/main/kotlin/dev/msfjarvis/aps/data/crypto/GPGKeyManager.kt

Lines changed: 43 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package dev.msfjarvis.aps.data.crypto
22

33
import com.github.michaelbull.result.Err
44
import com.github.michaelbull.result.Result
5+
import com.github.michaelbull.result.expect
56
import com.github.michaelbull.result.map
67
import com.github.michaelbull.result.runCatching
78
import com.proton.Gopenpgp.crypto.Crypto
@@ -62,15 +63,11 @@ public class GPGKeyManager(
6263
if (!keyDirExists())
6364
return@withContext Err(IllegalStateException("Key directory does not exist"))
6465

65-
return@withContext runCatching {
66-
keyDir.listFiles()?.forEach { file ->
67-
if (file.isFile && file.nameWithoutExtension.lowercase() == id.lowercase()) {
68-
val fileContent = file.readText()
69-
return@runCatching keyFactory.create(Key(fileContent))
70-
}
71-
}
72-
73-
error("Key with id: $id not found in directory")
66+
runCatching {
67+
val keys = getGopenpgpKeys().expect { "Failed to get PGP keys" }
68+
return@runCatching keyFactory.create(keys.first { key ->
69+
return@first getKeyIdentities(key).matches(id)
70+
})
7471
}
7572
}
7673

@@ -99,14 +96,50 @@ public class GPGKeyManager(
9996
}
10097

10198
override fun canHandle(fileName: String): Boolean {
102-
println("Checking in " + javaClass.simpleName)
10399
return fileName.split('.').last() == "gpg"
104100
}
105101

102+
private suspend fun getGopenpgpKeys(): Result<List<Key>, Throwable> = runCatching {
103+
withContext(dispatcher) {
104+
(keyDir.listFiles() ?: emptyArray()).map { file -> Crypto.newKeyFromArmored(file.readText()) }
105+
}
106+
}
107+
108+
private fun getKeyIdentities(key: Key): KeyIdentities {
109+
val keyId = key.hexKeyID
110+
val fingerprint = key.fingerprint
111+
val email = key.userEmail
112+
return KeyIdentities.create(keyId, fingerprint, email)
113+
}
114+
106115
private fun keyDirExists(): Boolean {
107116
return keyDir.exists() || keyDir.mkdir()
108117
}
109118

119+
/**
120+
* Container class for identifying properties of a GPG key
121+
*/
122+
private class KeyIdentities private constructor(val keyId: String, val fingerprint: String, val email: String) {
123+
fun matches(identifier: String): Boolean {
124+
val ident = identifier.lowercase()
125+
return ident == keyId || ident == fingerprint || ident == email || ident == "<$email>"
126+
}
127+
128+
companion object {
129+
fun create(
130+
keyId: String,
131+
fingerprint: String,
132+
email: String,
133+
): KeyIdentities {
134+
return KeyIdentities(
135+
keyId.lowercase(),
136+
fingerprint.lowercase(),
137+
email.lowercase(),
138+
)
139+
}
140+
}
141+
}
142+
110143
private companion object {
111144

112145
private const val KeyDir = "gpg-keys"

0 commit comments

Comments
 (0)