@@ -2,6 +2,7 @@ package dev.msfjarvis.aps.data.crypto
2
2
3
3
import com.github.michaelbull.result.Err
4
4
import com.github.michaelbull.result.Result
5
+ import com.github.michaelbull.result.expect
5
6
import com.github.michaelbull.result.map
6
7
import com.github.michaelbull.result.runCatching
7
8
import com.proton.Gopenpgp.crypto.Crypto
@@ -62,15 +63,11 @@ public class GPGKeyManager(
62
63
if (! keyDirExists())
63
64
return @withContext Err (IllegalStateException (" Key directory does not exist" ))
64
65
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
+ })
74
71
}
75
72
}
76
73
@@ -99,14 +96,50 @@ public class GPGKeyManager(
99
96
}
100
97
101
98
override fun canHandle (fileName : String ): Boolean {
102
- println (" Checking in " + javaClass.simpleName)
103
99
return fileName.split(' .' ).last() == " gpg"
104
100
}
105
101
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
+
106
115
private fun keyDirExists (): Boolean {
107
116
return keyDir.exists() || keyDir.mkdir()
108
117
}
109
118
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
+
110
143
private companion object {
111
144
112
145
private const val KeyDir = " gpg-keys"
0 commit comments