From 7bc35dcba388c0fe2abdecf26ab5e4f64668707d Mon Sep 17 00:00:00 2001 From: Paul Schaub Date: Fri, 1 Oct 2021 15:21:42 +0200 Subject: [PATCH] Add regression test for PGPUtil.getDecoderStream mistaking plaintext for base64 encoded data --- .../DecryptionStreamFactory.java | 2 +- .../CleartextSignatureVerificationTest.java | 49 +++++++++++++++++-- 2 files changed, 45 insertions(+), 6 deletions(-) diff --git a/pgpainless-core/src/main/java/org/pgpainless/decryption_verification/DecryptionStreamFactory.java b/pgpainless-core/src/main/java/org/pgpainless/decryption_verification/DecryptionStreamFactory.java index 10496a7d..65c2146f 100644 --- a/pgpainless-core/src/main/java/org/pgpainless/decryption_verification/DecryptionStreamFactory.java +++ b/pgpainless-core/src/main/java/org/pgpainless/decryption_verification/DecryptionStreamFactory.java @@ -153,7 +153,7 @@ public final class DecryptionStreamFactory { bufferedIn.reset(); inputStream = wrapInVerifySignatureStream(bufferedIn); } catch (IOException e) { - if (e.getMessage().contains("invalid armor")) { + if (e.getMessage().contains("invalid armor") || e.getMessage().contains("invalid header encountered")) { // We falsely assumed the data to be armored. LOGGER.debug("The message is apparently not armored."); bufferedIn.reset(); 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 ca86da0a..2b96f039 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 @@ -30,18 +30,24 @@ import java.nio.charset.StandardCharsets; import org.bouncycastle.openpgp.PGPException; import org.bouncycastle.openpgp.PGPPublicKey; import org.bouncycastle.openpgp.PGPPublicKeyRing; +import org.bouncycastle.openpgp.PGPSecretKeyRing; import org.bouncycastle.openpgp.PGPSignature; import org.bouncycastle.util.io.Streams; import org.junit.jupiter.api.Test; import org.pgpainless.PGPainless; -import org.pgpainless.exception.WrongConsumingMethodException; -import org.pgpainless.key.TestKeys; -import org.pgpainless.signature.CertificateValidator; -import org.pgpainless.signature.SignatureUtils; -import org.pgpainless.signature.SignatureVerifier; +import org.pgpainless.algorithm.DocumentSignatureType; import org.pgpainless.decryption_verification.cleartext_signatures.CleartextSignatureProcessor; import org.pgpainless.decryption_verification.cleartext_signatures.InMemoryMultiPassStrategy; import org.pgpainless.decryption_verification.cleartext_signatures.MultiPassStrategy; +import org.pgpainless.encryption_signing.EncryptionStream; +import org.pgpainless.encryption_signing.ProducerOptions; +import org.pgpainless.encryption_signing.SigningOptions; +import org.pgpainless.exception.WrongConsumingMethodException; +import org.pgpainless.key.TestKeys; +import org.pgpainless.key.protection.SecretKeyRingProtector; +import org.pgpainless.signature.CertificateValidator; +import org.pgpainless.signature.SignatureUtils; +import org.pgpainless.signature.SignatureVerifier; import org.pgpainless.util.ArmorUtils; import org.pgpainless.util.TestUtils; @@ -218,4 +224,37 @@ public class CleartextSignatureVerificationTest { .withOptions(options) .getVerificationStream()); } + + @Test + public void getDecoderStreamMistakensPlaintextForBase64RegressionTest() throws PGPException, IOException { + String message = "Foo\nBar"; // PGPUtil.getDecoderStream() would mistaken this for base64 data + ByteArrayInputStream msgIn = new ByteArrayInputStream(message.getBytes(StandardCharsets.UTF_8)); + + PGPSecretKeyRing secretKey = TestKeys.getEmilSecretKeyRing(); + ByteArrayOutputStream signedOut = new ByteArrayOutputStream(); + EncryptionStream signingStream = PGPainless.encryptAndOrSign().onOutputStream(signedOut) + .withOptions(ProducerOptions.sign(SigningOptions.get() + .addDetachedSignature(SecretKeyRingProtector.unprotectedKeys(), secretKey, DocumentSignatureType.CANONICAL_TEXT_DOCUMENT)) + .setCleartextSigned()); + + Streams.pipeAll(msgIn, signingStream); + signingStream.close(); + + String signed = signedOut.toString(); + + ByteArrayInputStream signedIn = new ByteArrayInputStream(signed.getBytes(StandardCharsets.UTF_8)); + DecryptionStream verificationStream = PGPainless.verifyCleartextSignedMessage() + .onInputStream(signedIn) + .withStrategy(new InMemoryMultiPassStrategy()) + .withOptions(new ConsumerOptions() + .addVerificationCert(TestKeys.getEmilPublicKeyRing())) + .getVerificationStream(); + + ByteArrayOutputStream msgOut = new ByteArrayOutputStream(); + Streams.pipeAll(verificationStream, msgOut); + verificationStream.close(); + + OpenPgpMetadata metadata = verificationStream.getResult(); + assertTrue(metadata.isVerified()); + } }