From ad7d4b226f71fd965421dc2f2a51825c8e8b3036 Mon Sep 17 00:00:00 2001 From: oSumAtrIX Date: Sat, 13 Jul 2024 00:27:54 +0200 Subject: [PATCH] feat: Add configuration to specify public key id --- .../repository/ConfigurationRepository.kt | 3 ++ .../configuration/services/PatchesService.kt | 1 + .../services/SignatureService.kt | 45 +++++++++---------- 3 files changed, 24 insertions(+), 25 deletions(-) diff --git a/src/main/kotlin/app/revanced/api/configuration/repository/ConfigurationRepository.kt b/src/main/kotlin/app/revanced/api/configuration/repository/ConfigurationRepository.kt index c70b412..bb567f3 100644 --- a/src/main/kotlin/app/revanced/api/configuration/repository/ConfigurationRepository.kt +++ b/src/main/kotlin/app/revanced/api/configuration/repository/ConfigurationRepository.kt @@ -51,6 +51,7 @@ internal class ConfigurationRepository( * @property assetRegex The regex matching the asset name. * @property signatureAssetRegex The regex matching the signature asset name to verify the asset. * @property publicKeyFile The public key file to verify the signature of the asset. + * @property publicKeyId The ID of the public key to verify the signature of the asset. */ @Serializable internal class AssetConfiguration( @@ -64,6 +65,8 @@ internal class ConfigurationRepository( @Serializable(with = FileSerializer::class) @SerialName("public-key-file") val publicKeyFile: File, + @SerialName("public-key-id") + val publicKeyId: Long, ) } diff --git a/src/main/kotlin/app/revanced/api/configuration/services/PatchesService.kt b/src/main/kotlin/app/revanced/api/configuration/services/PatchesService.kt index 31a0670..e24eb26 100644 --- a/src/main/kotlin/app/revanced/api/configuration/services/PatchesService.kt +++ b/src/main/kotlin/app/revanced/api/configuration/services/PatchesService.kt @@ -92,6 +92,7 @@ internal class PatchesService( patchesFile, signatureDownloadUrl, configurationRepository.patches.publicKeyFile, + configurationRepository.patches.publicKeyId, ) ) { PatchBundleLoader.Jar(patchesFile) diff --git a/src/main/kotlin/app/revanced/api/configuration/services/SignatureService.kt b/src/main/kotlin/app/revanced/api/configuration/services/SignatureService.kt index 89ea40e..80eb2d1 100644 --- a/src/main/kotlin/app/revanced/api/configuration/services/SignatureService.kt +++ b/src/main/kotlin/app/revanced/api/configuration/services/SignatureService.kt @@ -1,7 +1,6 @@ package app.revanced.api.configuration.services import com.github.benmanes.caffeine.cache.Caffeine -import org.bouncycastle.jce.provider.BouncyCastleProvider import org.bouncycastle.openpgp.* import org.bouncycastle.openpgp.operator.bc.BcKeyFingerprintCalculator import org.bouncycastle.openpgp.operator.bc.BcPGPContentVerifierBuilderProvider @@ -9,7 +8,6 @@ import java.io.File import java.io.InputStream import java.net.URL import java.security.MessageDigest -import java.security.Security internal class SignatureService { private val signatureCache = Caffeine @@ -21,6 +19,7 @@ internal class SignatureService { file: File, signatureDownloadUrl: String, publicKeyFile: File, + publicKeyId: Long, ): Boolean { val fileBytes = file.readBytes() @@ -28,7 +27,8 @@ internal class SignatureService { verify( fileBytes = fileBytes, signatureInputStream = URL(signatureDownloadUrl).openStream(), - publicKeyInputStream = publicKeyFile.inputStream(), + publicKeyFileInputStream = publicKeyFile.inputStream(), + publicKeyId = publicKeyId, ) } } @@ -36,37 +36,32 @@ internal class SignatureService { private fun verify( fileBytes: ByteArray, signatureInputStream: InputStream, - publicKeyInputStream: InputStream, + publicKeyFileInputStream: InputStream, + publicKeyId: Long, ) = getSignature(signatureInputStream).apply { - init(BcPGPContentVerifierBuilderProvider(), getPublicKey(publicKeyInputStream)) + init(BcPGPContentVerifierBuilderProvider(), getPublicKey(publicKeyFileInputStream, publicKeyId)) update(fileBytes) }.verify() - private fun getPublicKey(publicKeyInputStream: InputStream): PGPPublicKey { - val decoderStream = PGPUtil.getDecoderStream(publicKeyInputStream) + private fun getPublicKey( + publicKeyFileInputStream: InputStream, + publicKeyId: Long, + ): PGPPublicKey { + val decoderStream = PGPUtil.getDecoderStream(publicKeyFileInputStream) + val pgpPublicKeyRingCollection = PGPPublicKeyRingCollection(decoderStream, BcKeyFingerprintCalculator()) + val publicKeyRing = pgpPublicKeyRingCollection.getPublicKeyRing(publicKeyId) + ?: throw IllegalArgumentException("Can't find public key ring with ID $publicKeyId.") - PGPPublicKeyRingCollection(decoderStream, BcKeyFingerprintCalculator()).forEach { keyRing -> - keyRing.publicKeys.forEach { publicKey -> - if (publicKey.isEncryptionKey) { - return publicKey - } - } - } - - throw IllegalArgumentException("Can't find encryption key in key ring.") + return publicKeyRing.getPublicKey(publicKeyId) + ?: throw IllegalArgumentException("Can't find public key with ID $publicKeyId.") } private fun getSignature(inputStream: InputStream): PGPSignature { val decoderStream = PGPUtil.getDecoderStream(inputStream) - val pgpObjectFactory = PGPObjectFactory(decoderStream, BcKeyFingerprintCalculator()) - val signatureList = pgpObjectFactory.nextObject() as PGPSignatureList + val pgpSignatureList = PGPObjectFactory(decoderStream, BcKeyFingerprintCalculator()).first { + it is PGPSignatureList + } as PGPSignatureList - return signatureList.first() - } - - private companion object { - init { - Security.addProvider(BouncyCastleProvider()) - } + return pgpSignatureList.first() } }