diff --git a/src/main/java/name/neuhalfen/projects/crypto/bouncycastle/openpgp/decrypting/MDCValidatingInputStream.java b/src/main/java/name/neuhalfen/projects/crypto/bouncycastle/openpgp/decrypting/MDCValidatingInputStream.java index fc881e7..a7230c3 100644 --- a/src/main/java/name/neuhalfen/projects/crypto/bouncycastle/openpgp/decrypting/MDCValidatingInputStream.java +++ b/src/main/java/name/neuhalfen/projects/crypto/bouncycastle/openpgp/decrypting/MDCValidatingInputStream.java @@ -13,6 +13,10 @@ final class MDCValidatingInputStream extends FilterInputStream { private static final org.slf4j.Logger LOGGER = org.slf4j.LoggerFactory .getLogger(MDCValidatingInputStream.class); + private final PGPPublicKeyEncryptedData pbe; + + private boolean mdcChecked; + /** * Creates a MDCValidatingInputStream by assigning the argument * inputStream to the field this.inputStream and pbe to this.pbe so as to remember it for @@ -21,9 +25,6 @@ final class MDCValidatingInputStream extends FilterInputStream { * @param inputStream the underlying input stream * @param pbe the pgp public key encrypted data to verify message integrity */ - - private final PGPPublicKeyEncryptedData pbe; - MDCValidatingInputStream(InputStream inputStream, PGPPublicKeyEncryptedData pbe) { super(inputStream); this.pbe = pbe; @@ -61,6 +62,11 @@ public int read(@Nonnull byte[] b, int off, int len) throws IOException { * @throws IOException Error while reading input stream or if MDC fails */ private void validateMDC() throws IOException { + if (mdcChecked) { + return; + } + mdcChecked = true; + try { if (pbe.isIntegrityProtected()) { if (!pbe.verify()) { diff --git a/src/test/java/name/neuhalfen/projects/crypto/bouncycastle/openpgp/BuildDecryptionInputStreamAPITest.java b/src/test/java/name/neuhalfen/projects/crypto/bouncycastle/openpgp/BuildDecryptionInputStreamAPITest.java index 58e55b6..f3d767f 100644 --- a/src/test/java/name/neuhalfen/projects/crypto/bouncycastle/openpgp/BuildDecryptionInputStreamAPITest.java +++ b/src/test/java/name/neuhalfen/projects/crypto/bouncycastle/openpgp/BuildDecryptionInputStreamAPITest.java @@ -6,11 +6,12 @@ import static org.junit.Assume.assumeNotNull; import static org.mockito.Mockito.mock; +import java.io.BufferedInputStream; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; -import java.nio.charset.StandardCharsets; + import name.neuhalfen.projects.crypto.bouncycastle.openpgp.keys.keyrings.KeyringConfig; import name.neuhalfen.projects.crypto.bouncycastle.openpgp.testtooling.Configs; import name.neuhalfen.projects.crypto.bouncycastle.openpgp.testtooling.ExampleMessages; @@ -144,6 +145,31 @@ public void decryptNoSignatureValidation_withUnsignedData_works() throws Excepti } } + @Test() + public void decryptNoSignatureValidation_withWrapperStream_works() throws Exception { + + try (InputStream ciphertext = new ByteArrayInputStream( + ExampleMessages.IMPORTANT_QUOTE_NOT_SIGNED_NOT_COMPRESSED.getBytes( + "US-ASCII"))) { + final InputStream plaintextStream = BouncyGPG.decryptAndVerifyStream() + .withConfig(Configs.keyringConfigFromResourceForRecipient()) + .andIgnoreSignatures() + .fromEncryptedInputStream(ciphertext); + + final InputStream wrapperStream = new InputStream() { + @Override + public int read() throws IOException { + return plaintextStream.read(); + } + }; + + final String plainText = inputStreamToText(wrapperStream); + + assertThat(plainText, equalTo(ExampleMessages.IMPORTANT_QUOTE_TEXT)); + plaintextStream.close(); + } + } + @Test(expected = IOException.class) public void decryptAndValidateSignature_withUnsignedData_throws() throws Exception {