feat: Add configuration to specify public key id

This commit is contained in:
oSumAtrIX 2024-07-13 00:27:54 +02:00
parent 97a5d119ec
commit ad7d4b226f
No known key found for this signature in database
GPG Key ID: A9B3094ACDB604B4
3 changed files with 24 additions and 25 deletions

View File

@ -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,
)
}

View File

@ -92,6 +92,7 @@ internal class PatchesService(
patchesFile,
signatureDownloadUrl,
configurationRepository.patches.publicKeyFile,
configurationRepository.patches.publicKeyId,
)
) {
PatchBundleLoader.Jar(patchesFile)

View File

@ -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()
}
}