1
0
Fork 0
mirror of https://github.com/pgpainless/pgpainless.git synced 2025-09-09 02:09:38 +02:00

Migrate from MissingPublicKeyCallback to OpenPGPCertifcateProvider

This commit is contained in:
Paul Schaub 2025-02-24 12:33:04 +01:00
parent 0fc9ee716e
commit 1379942c07
Signed by: vanitasvitae
GPG key ID: 62BEE9264BF17311
4 changed files with 15 additions and 42 deletions

View file

@ -12,6 +12,7 @@ import org.bouncycastle.openpgp.*
import org.bouncycastle.openpgp.api.OpenPGPCertificate
import org.bouncycastle.openpgp.api.OpenPGPImplementation
import org.bouncycastle.openpgp.api.OpenPGPKey
import org.bouncycastle.openpgp.api.OpenPGPKeyMaterialProvider.OpenPGPCertificateProvider
import org.bouncycastle.openpgp.api.OpenPGPSignature.OpenPGPDocumentSignature
import org.bouncycastle.openpgp.operator.PublicKeyDataDecryptorFactory
import org.pgpainless.PGPainless
@ -34,7 +35,7 @@ class ConsumerOptions {
private val certificates = CertificateSource()
private val detachedSignatures = mutableSetOf<PGPSignature>()
private var missingCertificateCallback: MissingPublicKeyCallback? = null
private var missingCertificateCallback: OpenPGPCertificateProvider? = null
private var sessionKey: SessionKey? = null
private val customDecryptorFactories =
@ -164,9 +165,10 @@ class ConsumerOptions {
* @param callback callback
* @return options
*/
fun setMissingCertificateCallback(callback: MissingPublicKeyCallback): ConsumerOptions = apply {
this.missingCertificateCallback = callback
}
fun setMissingCertificateCallback(callback: OpenPGPCertificateProvider): ConsumerOptions =
apply {
this.missingCertificateCallback = callback
}
/**
* Attempt decryption using a session key.
@ -283,7 +285,7 @@ class ConsumerOptions {
*
* @return missing public key callback
*/
fun getMissingCertificateCallback(): MissingPublicKeyCallback? = missingCertificateCallback
fun getMissingCertificateCallback(): OpenPGPCertificateProvider? = missingCertificateCallback
/**
* Return the [SecretKeyRingProtector] for the given [PGPSecretKeyRing].

View file

@ -1,28 +0,0 @@
// SPDX-FileCopyrightText: 2023 Paul Schaub <vanitasvitae@fsfe.org>
//
// SPDX-License-Identifier: Apache-2.0
package org.pgpainless.decryption_verification
import org.bouncycastle.bcpg.KeyIdentifier
import org.bouncycastle.openpgp.api.OpenPGPCertificate
fun interface MissingPublicKeyCallback {
/**
* This method gets called if we encounter a signature made by a key which was not provided for
* signature verification. If you cannot provide the requested key, it is safe to return null
* here. PGPainless will then continue verification with the next signature.
*
* Note: The key-id might belong to a subkey, so be aware that when looking up the
* [OpenPGPCertificate], you may not only search for the key-id on the key rings primary key!
*
* It would be super cool to provide the OpenPgp fingerprint here, but unfortunately
* one-pass-signatures only contain the key id.
*
* @param keyIdentifier ID of the missing signing (sub)key
* @return keyring containing the key or null
* @see <a href="https://datatracker.ietf.org/doc/html/rfc4880#section-5.4">RFC</a>
*/
fun onMissingPublicKeyEncountered(keyIdentifier: KeyIdentifier): OpenPGPCertificate?
}

View file

@ -912,7 +912,7 @@ class OpenPgpMessageInputStream(
if (options.getMissingCertificateCallback() != null) {
return options
.getMissingCertificateCallback()!!
.onMissingPublicKeyEncountered(signature.keyIdentifiers.first())
.provide(signature.keyIdentifiers.first())
}
return null // TODO: Missing cert for sig
}
@ -924,9 +924,7 @@ class OpenPgpMessageInputStream(
}
if (options.getMissingCertificateCallback() != null) {
return options
.getMissingCertificateCallback()!!
.onMissingPublicKeyEncountered(signature.keyIdentifier)
return options.getMissingCertificateCallback()!!.provide(signature.keyIdentifier)
}
return null // TODO: Missing cert for sig
}

View file

@ -18,6 +18,7 @@ import org.bouncycastle.openpgp.PGPException;
import org.bouncycastle.openpgp.PGPPublicKeyRing;
import org.bouncycastle.openpgp.api.OpenPGPCertificate;
import org.bouncycastle.openpgp.api.OpenPGPKey;
import org.bouncycastle.openpgp.api.OpenPGPKeyMaterialProvider;
import org.bouncycastle.util.io.Streams;
import org.junit.jupiter.api.Test;
import org.pgpainless.PGPainless;
@ -32,9 +33,9 @@ import org.pgpainless.key.protection.SecretKeyRingProtector;
import javax.annotation.Nonnull;
/**
* Test functionality of the {@link MissingPublicKeyCallback} which is called when during signature verification,
* a signature is encountered which was made by a key that was not provided in
* {@link ConsumerOptions#addVerificationCert(PGPPublicKeyRing)}.
* Test functionality of the {@link org.bouncycastle.openpgp.api.OpenPGPKeyMaterialProvider.OpenPGPCertificateProvider}
* which is called when during signature verification, a signature is encountered which was made by a key that was
* not provided in {@link ConsumerOptions#addVerificationCert(PGPPublicKeyRing)}.
*/
public class VerifyWithMissingPublicKeyCallbackTest {
@ -63,9 +64,9 @@ public class VerifyWithMissingPublicKeyCallbackTest {
.onInputStream(new ByteArrayInputStream(signOut.toByteArray()))
.withOptions(new ConsumerOptions()
.addVerificationCert(unrelatedKeys)
.setMissingCertificateCallback(new MissingPublicKeyCallback() {
.setMissingCertificateCallback(new OpenPGPKeyMaterialProvider.OpenPGPCertificateProvider() {
@Override
public OpenPGPCertificate onMissingPublicKeyEncountered(@Nonnull KeyIdentifier keyIdentifier) {
public OpenPGPCertificate provide(@Nonnull KeyIdentifier keyIdentifier) {
assertEquals(signingKey.getKeyIdentifier(), keyIdentifier, "Signing key-ID mismatch.");
return signingPubKeys;
}