From e81ee648d8fccbac1beb619d9680a3f33e8afebd Mon Sep 17 00:00:00 2001 From: Paul Schaub Date: Mon, 6 Sep 2021 15:14:13 +0200 Subject: [PATCH] Clean DecryptionStream: We only ever have one IntegrityProtectedInputStream at most --- .../DecryptionStream.java | 24 ++++++++++++------- .../DecryptionStreamFactory.java | 15 ++++++------ 2 files changed, 23 insertions(+), 16 deletions(-) diff --git a/pgpainless-core/src/main/java/org/pgpainless/decryption_verification/DecryptionStream.java b/pgpainless-core/src/main/java/org/pgpainless/decryption_verification/DecryptionStream.java index 62065efd..969d5a45 100644 --- a/pgpainless-core/src/main/java/org/pgpainless/decryption_verification/DecryptionStream.java +++ b/pgpainless-core/src/main/java/org/pgpainless/decryption_verification/DecryptionStream.java @@ -19,15 +19,14 @@ import static org.pgpainless.signature.SignatureValidator.signatureWasCreatedInB import java.io.IOException; import java.io.InputStream; -import java.util.List; import javax.annotation.Nonnull; import org.bouncycastle.openpgp.PGPPublicKeyRing; import org.bouncycastle.util.io.Streams; import org.pgpainless.PGPainless; -import org.pgpainless.signature.DetachedSignature; -import org.pgpainless.signature.CertificateValidator; import org.pgpainless.exception.SignatureValidationException; +import org.pgpainless.signature.CertificateValidator; +import org.pgpainless.signature.DetachedSignature; import org.pgpainless.util.IntegrityProtectedInputStream; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -44,17 +43,26 @@ public class DecryptionStream extends InputStream { private final ConsumerOptions options; private final OpenPgpMetadata.Builder resultBuilder; private boolean isClosed = false; - private List integrityProtectedInputStreamList; + private final IntegrityProtectedInputStream integrityProtectedInputStream; private final InputStream armorStream; + /** + * Create an input stream that handles decryption and - if necessary - integrity protection verification. + * + * @param wrapped underlying input stream + * @param options options for consuming, eg. decryption key... + * @param resultBuilder builder for decryption metadata like algorithms, recipients etc. + * @param integrityProtectedInputStream in case of data encrypted using SEIP packet close this stream to check integrity + * @param armorStream armor stream to verify CRC checksums + */ DecryptionStream(@Nonnull InputStream wrapped, @Nonnull ConsumerOptions options, @Nonnull OpenPgpMetadata.Builder resultBuilder, - List integrityProtectedInputStreamList, + IntegrityProtectedInputStream integrityProtectedInputStream, InputStream armorStream) { this.inputStream = wrapped; this.options = options; this.resultBuilder = resultBuilder; - this.integrityProtectedInputStreamList = integrityProtectedInputStreamList; + this.integrityProtectedInputStream = integrityProtectedInputStream; this.armorStream = armorStream; } @@ -95,8 +103,8 @@ public class DecryptionStream extends InputStream { } inputStream.close(); maybeVerifyDetachedSignatures(); - for (IntegrityProtectedInputStream s : integrityProtectedInputStreamList) { - s.close(); + if (integrityProtectedInputStream != null) { + integrityProtectedInputStream.close(); } this.isClosed = true; } 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 fb900700..23920eee 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 @@ -19,7 +19,6 @@ import java.io.BufferedInputStream; import java.io.EOFException; import java.io.IOException; import java.io.InputStream; -import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; @@ -86,7 +85,7 @@ public final class DecryptionStreamFactory { private static final KeyFingerPrintCalculator keyFingerprintCalculator = ImplementationFactory.getInstance().getKeyFingerprintCalculator(); private final Map verifiableOnePassSignatures = new HashMap<>(); - private final List integrityProtectedStreams = new ArrayList<>(); + private IntegrityProtectedInputStream integrityProtectedEncryptedInputStream; public DecryptionStreamFactory(ConsumerOptions options) { this.options = options; @@ -158,7 +157,7 @@ public final class DecryptionStreamFactory { } } - return new DecryptionStream(inputStream, options, factory.resultBuilder, factory.integrityProtectedStreams, + return new DecryptionStream(inputStream, options, factory.resultBuilder, factory.integrityProtectedEncryptedInputStream, (decoderStream instanceof ArmoredInputStream) ? decoderStream : null); } @@ -262,7 +261,9 @@ public final class DecryptionStreamFactory { throwIfAlgorithmIsRejected(symmetricKeyAlgorithm); resultBuilder.setSymmetricKeyAlgorithm(symmetricKeyAlgorithm); - return decryptedDataStream; + integrityProtectedEncryptedInputStream = new IntegrityProtectedInputStream(decryptedDataStream, pbeEncryptedData); + + return integrityProtectedEncryptedInputStream; } catch (PGPException e) { LOGGER.debug("Probable passphrase mismatch, skip PBE encrypted data block", e); } @@ -341,10 +342,8 @@ public final class DecryptionStreamFactory { throwIfAlgorithmIsRejected(symmetricKeyAlgorithm); resultBuilder.setSymmetricKeyAlgorithm(symmetricKeyAlgorithm); - IntegrityProtectedInputStream integrityProtected = - new IntegrityProtectedInputStream(encryptedSessionKey.getDataStream(dataDecryptor), encryptedSessionKey); - integrityProtectedStreams.add(integrityProtected); - return integrityProtected; + integrityProtectedEncryptedInputStream = new IntegrityProtectedInputStream(encryptedSessionKey.getDataStream(dataDecryptor), encryptedSessionKey); + return integrityProtectedEncryptedInputStream; } private void throwIfAlgorithmIsRejected(SymmetricKeyAlgorithm algorithm) throws UnacceptableAlgorithmException {