@@ -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,13 @@ 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) )
66
+ runCatching {
67
+ val keys = getGopenpgpKeys(). expect { " Failed to get PGP keys " }
68
+ return @runCatching keyFactory.create(
69
+ keys.first { key ->
70
+ return @first getKeyIdentities(key).matches(id )
70
71
}
71
- }
72
-
73
- error(" Key with id: $id not found in directory" )
72
+ )
74
73
}
75
74
}
76
75
@@ -94,19 +93,52 @@ public class GPGKeyManager(
94
93
}
95
94
96
95
override suspend fun getAllKeyIds (): Result <List <String >, Throwable> =
97
- withContext(dispatcher) {
98
- getAllKeys().map { keys -> keys.map { it.getKeyId() } }
99
- }
96
+ withContext(dispatcher) { getAllKeys().map { keys -> keys.map { it.getKeyId() } } }
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
+ /* * Container class for identifying properties of a GPG key */
120
+ private class KeyIdentities
121
+ private constructor (val keyId: String , val fingerprint: String , val email: String ) {
122
+ fun matches (identifier : String ): Boolean {
123
+ val ident = identifier.lowercase()
124
+ return ident == keyId || ident == fingerprint || ident == email || ident == " <$email >"
125
+ }
126
+
127
+ companion object {
128
+ fun create (
129
+ keyId : String ,
130
+ fingerprint : String ,
131
+ email : String ,
132
+ ): KeyIdentities {
133
+ return KeyIdentities (
134
+ keyId.lowercase(),
135
+ fingerprint.lowercase(),
136
+ email.lowercase(),
137
+ )
138
+ }
139
+ }
140
+ }
141
+
110
142
private companion object {
111
143
112
144
private const val KeyDir = " gpg-keys"
0 commit comments