diff --git a/pgpainless-core/src/main/java/org/pgpainless/encryption_signing/EncryptionStream.java b/pgpainless-core/src/main/java/org/pgpainless/encryption_signing/EncryptionStream.java index 50f5cb5f..27d35ea5 100644 --- a/pgpainless-core/src/main/java/org/pgpainless/encryption_signing/EncryptionStream.java +++ b/pgpainless-core/src/main/java/org/pgpainless/encryption_signing/EncryptionStream.java @@ -86,7 +86,7 @@ public final class EncryptionStream extends OutputStream { outermostStream = new BufferedOutputStream(outermostStream); LOGGER.debug("Wrap encryption output in ASCII armor"); - armorOutputStream = ArmoredOutputStreamFactory.get(outermostStream); + armorOutputStream = ArmoredOutputStreamFactory.get(outermostStream, options); if (options.hasComment()) { String[] commentLines = options.getComment().split("\n"); for (String commentLine : commentLines) { diff --git a/pgpainless-core/src/main/java/org/pgpainless/encryption_signing/ProducerOptions.java b/pgpainless-core/src/main/java/org/pgpainless/encryption_signing/ProducerOptions.java index a015a581..4948a7fe 100644 --- a/pgpainless-core/src/main/java/org/pgpainless/encryption_signing/ProducerOptions.java +++ b/pgpainless-core/src/main/java/org/pgpainless/encryption_signing/ProducerOptions.java @@ -22,6 +22,7 @@ public final class ProducerOptions { private StreamEncoding encodingField = StreamEncoding.BINARY; private boolean applyCRLFEncoding = false; private boolean cleartextSigned = false; + private boolean hideArmorHeaders = false; private CompressionAlgorithm compressionAlgorithmOverride = PGPainless.getPolicy().getCompressionAlgorithmPolicy() .defaultCompressionAlgorithm(); @@ -302,4 +303,22 @@ public final class ProducerOptions { public @Nullable SigningOptions getSigningOptions() { return signingOptions; } + + public boolean isHideArmorHeaders() { + return hideArmorHeaders; + } + + /** + * If set to
true
, armor headers like version or comments will be omitted from armored output. + * By default, armor headers are not hidden. + * Note: If comments are added via {@link #setComment(String)}, those are not omitted, even if + * {@link #hideArmorHeaders} is set to
true
. + * + * @param hideArmorHeaders true or false + * @return this + */ + public ProducerOptions setHideArmorHeaders(boolean hideArmorHeaders) { + this.hideArmorHeaders = hideArmorHeaders; + return this; + } } diff --git a/pgpainless-core/src/main/java/org/pgpainless/util/ArmoredOutputStreamFactory.java b/pgpainless-core/src/main/java/org/pgpainless/util/ArmoredOutputStreamFactory.java index 2e1377a0..403115ba 100644 --- a/pgpainless-core/src/main/java/org/pgpainless/util/ArmoredOutputStreamFactory.java +++ b/pgpainless-core/src/main/java/org/pgpainless/util/ArmoredOutputStreamFactory.java @@ -7,6 +7,7 @@ package org.pgpainless.util; import java.io.OutputStream; import org.bouncycastle.bcpg.ArmoredOutputStream; +import org.pgpainless.encryption_signing.ProducerOptions; /** * Factory to create configured {@link ArmoredOutputStream ArmoredOutputStreams}. @@ -37,6 +38,16 @@ public final class ArmoredOutputStreamFactory { return armoredOutputStream; } + public static ArmoredOutputStream get(OutputStream outputStream, ProducerOptions options) { + if (options.isHideArmorHeaders()) { + ArmoredOutputStream armorOut = new ArmoredOutputStream(outputStream); + armorOut.clearHeaders(); + return armorOut; + } else { + return get(outputStream); + } + } + /** * Overwrite the version header of ASCII armors with a custom value. * Newlines in the version info string result in multiple version header entries. diff --git a/pgpainless-core/src/test/java/org/pgpainless/encryption_signing/HideArmorHeadersTest.java b/pgpainless-core/src/test/java/org/pgpainless/encryption_signing/HideArmorHeadersTest.java new file mode 100644 index 00000000..242b430b --- /dev/null +++ b/pgpainless-core/src/test/java/org/pgpainless/encryption_signing/HideArmorHeadersTest.java @@ -0,0 +1,34 @@ +// SPDX-FileCopyrightText: 2022 Paul Schaub +// +// SPDX-License-Identifier: Apache-2.0 + +package org.pgpainless.encryption_signing; + +import org.bouncycastle.openpgp.PGPException; +import org.junit.jupiter.api.Test; +import org.pgpainless.PGPainless; +import org.pgpainless.util.Passphrase; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; + +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class HideArmorHeadersTest { + + @Test + public void testVersionHeaderIsOmitted() throws PGPException, IOException { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + EncryptionStream encryptionStream = PGPainless.encryptAndOrSign() + .onOutputStream(out) + .withOptions(ProducerOptions.encrypt( + EncryptionOptions.get() + .addPassphrase(Passphrase.fromPassword("sw0rdf1sh"))) + .setHideArmorHeaders(true)); + + encryptionStream.write("Hello, World!\n".getBytes()); + encryptionStream.close(); + + assertTrue(out.toString().startsWith("-----BEGIN PGP MESSAGE-----\n\n")); // No "Version: PGPainless" + } +}