Add logic for MissingPublicKeyCallback

This commit is contained in:
Paul Schaub 2018-07-02 20:46:27 +02:00
parent 07c689b556
commit 975b336699
Signed by: vanitasvitae
GPG Key ID: 62BEE9264BF17311
4 changed files with 40 additions and 16 deletions

View File

@ -33,7 +33,7 @@ public class DecryptionBuilder implements DecryptionBuilderInterface {
private PGPSecretKeyRingCollection decryptionKeys; private PGPSecretKeyRingCollection decryptionKeys;
private SecretKeyRingProtector decryptionKeyDecryptor; private SecretKeyRingProtector decryptionKeyDecryptor;
private Set<PGPPublicKeyRing> verificationKeys = new HashSet<>(); private Set<PGPPublicKeyRing> verificationKeys = new HashSet<>();
private MissingPublicKeyCallback missingPublicKeyCallback = null; private org.pgpainless.pgpainless.decryption_verification.MissingPublicKeyCallback missingPublicKeyCallback = null;
@Override @Override
public DecryptWith onInputStream(InputStream inputStream) { public DecryptWith onInputStream(InputStream inputStream) {
@ -61,8 +61,8 @@ public class DecryptionBuilder implements DecryptionBuilderInterface {
class VerifyWithImpl implements VerifyWith { class VerifyWithImpl implements VerifyWith {
@Override @Override
public MissingPublicKeyFeedback verifyWith(Set<Long> trustedKeyIds, public HandleMissingPublicKeys verifyWith(Set<Long> trustedKeyIds,
PGPPublicKeyRingCollection publicKeyRingCollection) { PGPPublicKeyRingCollection publicKeyRingCollection) {
Set<PGPPublicKeyRing> publicKeyRings = new HashSet<>(); Set<PGPPublicKeyRing> publicKeyRings = new HashSet<>();
for (Iterator<PGPPublicKeyRing> i = publicKeyRingCollection.getKeyRings(); i.hasNext(); ) { for (Iterator<PGPPublicKeyRing> i = publicKeyRingCollection.getKeyRings(); i.hasNext(); ) {
PGPPublicKeyRing p = i.next(); PGPPublicKeyRing p = i.next();
@ -74,9 +74,9 @@ public class DecryptionBuilder implements DecryptionBuilderInterface {
} }
@Override @Override
public MissingPublicKeyFeedback verifyWith(Set<PGPPublicKeyRing> publicKeyRings) { public HandleMissingPublicKeys verifyWith(Set<PGPPublicKeyRing> publicKeyRings) {
DecryptionBuilder.this.verificationKeys = publicKeyRings; DecryptionBuilder.this.verificationKeys = publicKeyRings;
return new MissingPublicKeyFeedbackImpl(); return new HandleMissingPublicKeysImpl();
} }
@Override @Override
@ -86,16 +86,17 @@ public class DecryptionBuilder implements DecryptionBuilderInterface {
} }
} }
class MissingPublicKeyFeedbackImpl implements MissingPublicKeyFeedback { class HandleMissingPublicKeysImpl implements HandleMissingPublicKeys {
@Override @Override
public Build handleMissingPublicKeysWith(MissingPublicKeyCallback callback) { public Build handleMissingPublicKeysWith(org.pgpainless.pgpainless.decryption_verification.MissingPublicKeyCallback callback) {
DecryptionBuilder.this.missingPublicKeyCallback = callback; DecryptionBuilder.this.missingPublicKeyCallback = callback;
return new BuildImpl(); return new BuildImpl();
} }
@Override @Override
public Build ignoreMissingPublicKeys() { public Build ignoreMissingPublicKeys() {
DecryptionBuilder.this.missingPublicKeyCallback = null;
return new BuildImpl(); return new BuildImpl();
} }
} }

View File

@ -39,17 +39,17 @@ public interface DecryptionBuilderInterface {
interface VerifyWith { interface VerifyWith {
MissingPublicKeyFeedback verifyWith(Set<Long> trustedFingerprints, PGPPublicKeyRingCollection publicKeyRings); HandleMissingPublicKeys verifyWith(Set<Long> trustedFingerprints, PGPPublicKeyRingCollection publicKeyRings);
MissingPublicKeyFeedback verifyWith(Set<PGPPublicKeyRing> publicKeyRings); HandleMissingPublicKeys verifyWith(Set<PGPPublicKeyRing> publicKeyRings);
Build doNotVerify(); Build doNotVerify();
} }
interface MissingPublicKeyFeedback { interface HandleMissingPublicKeys {
Build handleMissingPublicKeysWith(MissingPublicKeyCallback callback); Build handleMissingPublicKeysWith(org.pgpainless.pgpainless.decryption_verification.MissingPublicKeyCallback callback);
Build ignoreMissingPublicKeys(); Build ignoreMissingPublicKeys();
} }

View File

@ -197,7 +197,7 @@ public class DecryptionStreamFactory {
while (iterator.hasNext()) { while (iterator.hasNext()) {
PGPOnePassSignature signature = iterator.next(); PGPOnePassSignature signature = iterator.next();
long keyId = signature.getKeyID(); final long keyId = signature.getKeyID();
resultBuilder.addSignatureKeyId(keyId); resultBuilder.addSignatureKeyId(keyId);
LOGGER.log(LEVEL, "Message contains OnePassSignature from " + Long.toHexString(keyId)); LOGGER.log(LEVEL, "Message contains OnePassSignature from " + Long.toHexString(keyId));
@ -212,10 +212,31 @@ public class DecryptionStreamFactory {
} }
} }
if (verificationKey != null) { if (verificationKey == null) {
signature.init(verifierBuilderProvider, verificationKey); LOGGER.log(Level.INFO, "No public key for signature of " + Long.toHexString(keyId) + " found.");
verifiableOnePassSignatures.put(signature.getKeyID(), signature);
if (missingPublicKeyCallback == null) {
LOGGER.log(Level.INFO, "Skip signature of " + Long.toHexString(keyId));
continue;
}
PGPPublicKey missingPublicKey = missingPublicKeyCallback.onMissingPublicKeyEncountered(keyId);
if (missingPublicKey == null) {
LOGGER.log(Level.INFO, "Skip signature of " + Long.toHexString(keyId));
continue;
}
if (missingPublicKey.getKeyID() != keyId) {
throw new IllegalArgumentException("KeyID of the provided public key differs from the signatures keyId. " +
"The signature was created from " + Long.toHexString(keyId) + " while the provided key has ID " +
Long.toHexString(missingPublicKey.getKeyID()));
}
verificationKey = missingPublicKey;
} }
signature.init(verifierBuilderProvider, verificationKey);
verifiableOnePassSignatures.put(keyId, signature);
} }
} }
} }

View File

@ -15,8 +15,10 @@
*/ */
package org.pgpainless.pgpainless.decryption_verification; package org.pgpainless.pgpainless.decryption_verification;
import org.bouncycastle.openpgp.PGPPublicKey;
public interface MissingPublicKeyCallback { public interface MissingPublicKeyCallback {
void onMissingPublicKeyEncountered(Long keyId); PGPPublicKey onMissingPublicKeyEncountered(Long keyId);
} }