Skip to content

Commit d5ae289

Browse files
committed
fix: find the key id in multiple key rings
previous implementation was selecting only the first key ring from the public key file which turns out to be wrong. Instead, we should keep all the key rings and search signature key id in all the key rings.
1 parent 270b949 commit d5ae289

File tree

1 file changed

+23
-10
lines changed

1 file changed

+23
-10
lines changed

src/main/kotlin/com/coder/toolbox/cli/gpg/GPGVerifier.kt

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import kotlinx.coroutines.Dispatchers
99
import kotlinx.coroutines.withContext
1010
import org.bouncycastle.bcpg.ArmoredInputStream
1111
import org.bouncycastle.openpgp.PGPException
12+
import org.bouncycastle.openpgp.PGPPublicKey
1213
import org.bouncycastle.openpgp.PGPPublicKeyRing
1314
import org.bouncycastle.openpgp.PGPPublicKeyRingCollection
1415
import org.bouncycastle.openpgp.PGPSignatureList
@@ -20,7 +21,6 @@ import java.io.ByteArrayInputStream
2021
import java.nio.file.Files
2122
import java.nio.file.Path
2223

23-
2424
class 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

Comments
 (0)