@@ -9,6 +9,7 @@ import kotlinx.coroutines.Dispatchers
9
9
import kotlinx.coroutines.withContext
10
10
import org.bouncycastle.bcpg.ArmoredInputStream
11
11
import org.bouncycastle.openpgp.PGPException
12
+ import org.bouncycastle.openpgp.PGPPublicKey
12
13
import org.bouncycastle.openpgp.PGPPublicKeyRing
13
14
import org.bouncycastle.openpgp.PGPPublicKeyRingCollection
14
15
import org.bouncycastle.openpgp.PGPSignatureList
@@ -20,7 +21,6 @@ import java.io.ByteArrayInputStream
20
21
import java.nio.file.Files
21
22
import java.nio.file.Path
22
23
23
-
24
24
class GPGVerifier (
25
25
private val context : CoderToolboxContext ,
26
26
) {
@@ -38,42 +38,42 @@ class GPGVerifier(
38
38
val (cliBytes, signatureBytes, publicKeyRing) = withContext(Dispatchers .IO ) {
39
39
val cliBytes = Files .readAllBytes(cli)
40
40
val signatureBytes = Files .readAllBytes(signature)
41
- val publicKeyRing = getCoderPublicKeyRing ()
41
+ val publicKeyRing = getCoderPublicKeyRings ()
42
42
43
43
Triple (cliBytes, signatureBytes, publicKeyRing)
44
44
}
45
45
return verifyDetachedSignature(
46
46
cliBytes = cliBytes,
47
47
signatureBytes = signatureBytes,
48
- publicKeyRing = publicKeyRing
48
+ publicKeyRings = publicKeyRing
49
49
)
50
50
} catch (e: Exception ) {
51
51
context.logger.error(e, " GPG signature verification failed" )
52
52
Failed (e)
53
53
}
54
54
}
55
55
56
- private fun getCoderPublicKeyRing (): PGPPublicKeyRing {
56
+ private fun getCoderPublicKeyRings (): List < PGPPublicKeyRing > {
57
57
try {
58
58
val coderPublicKey = javaClass.getResourceAsStream(" /META-INF/trusted-keys/pgp-public.key" )
59
59
?.readAllBytes() ? : throw IllegalStateException (" Trusted public key not found" )
60
- return loadPublicKeyRing (coderPublicKey)
60
+ return loadPublicKeyRings (coderPublicKey)
61
61
} catch (e: Exception ) {
62
62
throw PGPException (" Failed to load Coder public GPG key" , e)
63
63
}
64
64
}
65
65
66
66
/* *
67
- * Load public key ring from bytes
67
+ * Load public key rings from bytes
68
68
*/
69
- fun loadPublicKeyRing (publicKeyBytes : ByteArray ): PGPPublicKeyRing {
69
+ fun loadPublicKeyRings (publicKeyBytes : ByteArray ): List < PGPPublicKeyRing > {
70
70
return try {
71
71
val keyInputStream = ArmoredInputStream (ByteArrayInputStream (publicKeyBytes))
72
72
val keyRingCollection = PGPPublicKeyRingCollection (
73
73
PGPUtil .getDecoderStream(keyInputStream),
74
74
JcaKeyFingerprintCalculator ()
75
75
)
76
- keyRingCollection.keyRings.next ()
76
+ keyRingCollection.keyRings.asSequence().toList ()
77
77
} catch (e: Exception ) {
78
78
throw PGPException (" Failed to load public key ring" , e)
79
79
}
@@ -85,7 +85,7 @@ class GPGVerifier(
85
85
fun verifyDetachedSignature (
86
86
cliBytes : ByteArray ,
87
87
signatureBytes : ByteArray ,
88
- publicKeyRing : PGPPublicKeyRing
88
+ publicKeyRings : List < PGPPublicKeyRing >
89
89
): VerificationResult {
90
90
try {
91
91
val signatureInputStream = ArmoredInputStream (ByteArrayInputStream (signatureBytes))
@@ -98,7 +98,7 @@ class GPGVerifier(
98
98
}
99
99
100
100
val signature = signatureList[0 ]
101
- val publicKey = publicKeyRing.getPublicKey( signature.keyID)
101
+ val publicKey = findPublicKey(publicKeyRings, signature.keyID)
102
102
? : throw PGPException (" Public key not found for signature" )
103
103
104
104
signature.init (JcaPGPContentVerifierBuilderProvider (), publicKey)
@@ -115,4 +115,17 @@ class GPGVerifier(
115
115
return Failed (e)
116
116
}
117
117
}
118
+
119
+ /* *
120
+ * Find a public key across all key rings in the collection
121
+ */
122
+ private fun findPublicKey (
123
+ keyRings : List <PGPPublicKeyRing >,
124
+ keyId : Long
125
+ ): PGPPublicKey ? {
126
+ keyRings.forEach { keyRing ->
127
+ keyRing.getPublicKey(keyId)?.let { return it }
128
+ }
129
+ return null
130
+ }
118
131
}
0 commit comments