From 3994f87c78c6af98bf4494c7991cbc0c5fa01070 Mon Sep 17 00:00:00 2001 From: Paul Schaub Date: Sat, 4 Sep 2021 13:41:06 +0200 Subject: [PATCH] Cleartext Signature Framework: Return OpenPgpMetadata --- .../CleartextSignatureProcessor.java | 36 ++++++++++++------- .../SignatureVerification.java | 5 ++- .../CleartextSignatureVerificationTest.java | 11 ++++-- 3 files changed, 37 insertions(+), 15 deletions(-) diff --git a/pgpainless-core/src/main/java/org/pgpainless/signature/cleartext_signatures/CleartextSignatureProcessor.java b/pgpainless-core/src/main/java/org/pgpainless/signature/cleartext_signatures/CleartextSignatureProcessor.java index 0c749815..5242cbd6 100644 --- a/pgpainless-core/src/main/java/org/pgpainless/signature/cleartext_signatures/CleartextSignatureProcessor.java +++ b/pgpainless-core/src/main/java/org/pgpainless/signature/cleartext_signatures/CleartextSignatureProcessor.java @@ -20,9 +20,6 @@ import static org.pgpainless.signature.SignatureValidator.signatureWasCreatedInB import java.io.File; import java.io.IOException; import java.io.InputStream; -import java.util.HashMap; -import java.util.Map; -import java.util.NoSuchElementException; import java.util.logging.Level; import java.util.logging.Logger; @@ -33,8 +30,13 @@ import org.bouncycastle.openpgp.PGPPublicKeyRing; import org.bouncycastle.openpgp.PGPSignature; import org.bouncycastle.openpgp.PGPSignatureList; import org.pgpainless.PGPainless; +import org.pgpainless.algorithm.CompressionAlgorithm; +import org.pgpainless.algorithm.StreamEncoding; +import org.pgpainless.algorithm.SymmetricKeyAlgorithm; import org.pgpainless.decryption_verification.ConsumerOptions; +import org.pgpainless.decryption_verification.OpenPgpMetadata; import org.pgpainless.exception.SignatureValidationException; +import org.pgpainless.key.SubkeyIdentifier; import org.pgpainless.signature.CertificateValidator; import org.pgpainless.signature.SignatureVerifier; import org.pgpainless.util.ArmoredInputStreamFactory; @@ -76,9 +78,13 @@ public class CleartextSignatureProcessor { * @throws PGPException if the signature cannot be initialized. * @throws SignatureValidationException if the signature is invalid. */ - public PGPSignature process() throws IOException, PGPException { + public OpenPgpMetadata process() throws IOException, PGPException { + OpenPgpMetadata.Builder resultBuilder = OpenPgpMetadata.getBuilder(); + resultBuilder.setCompressionAlgorithm(CompressionAlgorithm.UNCOMPRESSED) + .setSymmetricKeyAlgorithm(SymmetricKeyAlgorithm.NULL) + .setFileEncoding(StreamEncoding.TEXT); + PGPSignatureList signatures = ClearsignedMessageUtil.detachSignaturesFromInbandClearsignedMessage(in, multiPassStrategy.getMessageOutputStream()); - Map signatureValidationExceptions = new HashMap<>(); for (PGPSignature signature : signatures) { PGPPublicKeyRing certificate = null; @@ -90,23 +96,29 @@ public class CleartextSignatureProcessor { break; } } - if (signingKey == null) { - signatureValidationExceptions.put(signature, new NoSuchElementException("Missing verification key with key-id " + Long.toHexString(signature.getKeyID()))); - continue; - } try { + if (signingKey == null) { + throw new SignatureValidationException("Missing verification key with key-id " + Long.toHexString(signature.getKeyID())); + } + + SubkeyIdentifier signingKeyIdentifier = new SubkeyIdentifier(certificate, signingKey.getKeyID()); + signatureWasCreatedInBounds(options.getVerifyNotBefore(), options.getVerifyNotAfter()).verify(signature); SignatureVerifier.initializeSignatureAndUpdateWithSignedData(signature, multiPassStrategy.getMessageInputStream(), signingKey); CertificateValidator.validateCertificateAndVerifyInitializedSignature(signature, certificate, PGPainless.getPolicy()); - return signature; + resultBuilder.addVerifiedInbandSignature(new SignatureVerification(signature, signingKeyIdentifier)); } catch (SignatureValidationException e) { LOGGER.log(Level.INFO, "Cannot verify signature made by key " + Long.toHexString(signature.getKeyID()) + ": " + e.getMessage()); - signatureValidationExceptions.put(signature, e); + SubkeyIdentifier signingKeyIdentifier = null; + if (signingKey != null) { + signingKeyIdentifier = new SubkeyIdentifier(certificate, signingKey.getKeyID()); + } + resultBuilder.addInvalidInbandSignature(new SignatureVerification(signature, signingKeyIdentifier), e); } } - throw new SignatureValidationException("No valid signatures found.", signatureValidationExceptions); + return resultBuilder.build(); } } diff --git a/pgpainless-core/src/main/java/org/pgpainless/signature/cleartext_signatures/SignatureVerification.java b/pgpainless-core/src/main/java/org/pgpainless/signature/cleartext_signatures/SignatureVerification.java index 5c944c95..9b98b998 100644 --- a/pgpainless-core/src/main/java/org/pgpainless/signature/cleartext_signatures/SignatureVerification.java +++ b/pgpainless-core/src/main/java/org/pgpainless/signature/cleartext_signatures/SignatureVerification.java @@ -15,6 +15,8 @@ */ package org.pgpainless.signature.cleartext_signatures; +import javax.annotation.Nullable; + import org.bouncycastle.openpgp.PGPSignature; import org.pgpainless.exception.SignatureValidationException; import org.pgpainless.key.SubkeyIdentifier; @@ -24,7 +26,7 @@ public class SignatureVerification { private final PGPSignature signature; private final SubkeyIdentifier signingKey; - public SignatureVerification(PGPSignature signature, SubkeyIdentifier signingKey) { + public SignatureVerification(PGPSignature signature, @Nullable SubkeyIdentifier signingKey) { this.signature = signature; this.signingKey = signingKey; } @@ -33,6 +35,7 @@ public class SignatureVerification { return signature; } + @Nullable public SubkeyIdentifier getSigningKey() { return signingKey; } diff --git a/pgpainless-core/src/test/java/org/pgpainless/decryption_verification/CleartextSignatureVerificationTest.java b/pgpainless-core/src/test/java/org/pgpainless/decryption_verification/CleartextSignatureVerificationTest.java index c09d3d98..dec9f179 100644 --- a/pgpainless-core/src/test/java/org/pgpainless/decryption_verification/CleartextSignatureVerificationTest.java +++ b/pgpainless-core/src/test/java/org/pgpainless/decryption_verification/CleartextSignatureVerificationTest.java @@ -18,6 +18,7 @@ package org.pgpainless.decryption_verification; import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; @@ -88,7 +89,10 @@ public class CleartextSignatureVerificationTest { .withStrategy(multiPassStrategy) .withOptions(options); - PGPSignature signature = processor.process(); + OpenPgpMetadata result = processor.process(); + assertTrue(result.isVerified()); + + PGPSignature signature = result.getVerifiedSignatures().values().iterator().next(); assertEquals(signature.getKeyID(), signingKeys.getPublicKey().getKeyID()); assertArrayEquals(MESSAGE_BODY, multiPassStrategy.getBytes()); @@ -108,7 +112,10 @@ public class CleartextSignatureVerificationTest { .withStrategy(multiPassStrategy) .withOptions(options); - PGPSignature signature = processor.process(); + OpenPgpMetadata result = processor.process(); + assertTrue(result.isVerified()); + + PGPSignature signature = result.getVerifiedSignatures().values().iterator().next(); assertEquals(signature.getKeyID(), signingKeys.getPublicKey().getKeyID()); FileInputStream fileIn = new FileInputStream(file);