@@ -9,6 +9,7 @@ import kotlinx.coroutines.Dispatchers
99import kotlinx.coroutines.withContext
1010import org.bouncycastle.bcpg.ArmoredInputStream
1111import org.bouncycastle.openpgp.PGPException
12+ import org.bouncycastle.openpgp.PGPPublicKey
1213import org.bouncycastle.openpgp.PGPPublicKeyRing
1314import org.bouncycastle.openpgp.PGPPublicKeyRingCollection
1415import org.bouncycastle.openpgp.PGPSignatureList
@@ -20,7 +21,6 @@ import java.io.ByteArrayInputStream
2021import java.nio.file.Files
2122import java.nio.file.Path
2223
23-
2424class GPGVerifier (
2525 private val context : CoderToolboxContext ,
2626) {
@@ -38,42 +38,42 @@ class GPGVerifier(
3838 val (cliBytes, signatureBytes, publicKeyRing) = withContext(Dispatchers .IO ) {
3939 val cliBytes = Files .readAllBytes(cli)
4040 val signatureBytes = Files .readAllBytes(signature)
41- val publicKeyRing = getCoderPublicKeyRing ()
41+ val publicKeyRing = getCoderPublicKeyRings ()
4242
4343 Triple (cliBytes, signatureBytes, publicKeyRing)
4444 }
4545 return verifyDetachedSignature(
4646 cliBytes = cliBytes,
4747 signatureBytes = signatureBytes,
48- publicKeyRing = publicKeyRing
48+ publicKeyRings = publicKeyRing
4949 )
5050 } catch (e: Exception ) {
5151 context.logger.error(e, " GPG signature verification failed" )
5252 Failed (e)
5353 }
5454 }
5555
56- private fun getCoderPublicKeyRing (): PGPPublicKeyRing {
56+ private fun getCoderPublicKeyRings (): List < PGPPublicKeyRing > {
5757 try {
5858 val coderPublicKey = javaClass.getResourceAsStream(" /META-INF/trusted-keys/pgp-public.key" )
5959 ?.readAllBytes() ? : throw IllegalStateException (" Trusted public key not found" )
60- return loadPublicKeyRing (coderPublicKey)
60+ return loadPublicKeyRings (coderPublicKey)
6161 } catch (e: Exception ) {
6262 throw PGPException (" Failed to load Coder public GPG key" , e)
6363 }
6464 }
6565
6666 /* *
67- * Load public key ring from bytes
67+ * Load public key rings from bytes
6868 */
69- fun loadPublicKeyRing (publicKeyBytes : ByteArray ): PGPPublicKeyRing {
69+ fun loadPublicKeyRings (publicKeyBytes : ByteArray ): List < PGPPublicKeyRing > {
7070 return try {
7171 val keyInputStream = ArmoredInputStream (ByteArrayInputStream (publicKeyBytes))
7272 val keyRingCollection = PGPPublicKeyRingCollection (
7373 PGPUtil .getDecoderStream(keyInputStream),
7474 JcaKeyFingerprintCalculator ()
7575 )
76- keyRingCollection.keyRings.next ()
76+ keyRingCollection.keyRings.asSequence().toList ()
7777 } catch (e: Exception ) {
7878 throw PGPException (" Failed to load public key ring" , e)
7979 }
@@ -85,7 +85,7 @@ class GPGVerifier(
8585 fun verifyDetachedSignature (
8686 cliBytes : ByteArray ,
8787 signatureBytes : ByteArray ,
88- publicKeyRing : PGPPublicKeyRing
88+ publicKeyRings : List < PGPPublicKeyRing >
8989 ): VerificationResult {
9090 try {
9191 val signatureInputStream = ArmoredInputStream (ByteArrayInputStream (signatureBytes))
@@ -98,7 +98,7 @@ class GPGVerifier(
9898 }
9999
100100 val signature = signatureList[0 ]
101- val publicKey = publicKeyRing.getPublicKey( signature.keyID)
101+ val publicKey = findPublicKey(publicKeyRings, signature.keyID)
102102 ? : throw PGPException (" Public key not found for signature" )
103103
104104 signature.init (JcaPGPContentVerifierBuilderProvider (), publicKey)
@@ -115,4 +115,17 @@ class GPGVerifier(
115115 return Failed (e)
116116 }
117117 }
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+ }
118131}
0 commit comments