From 50bcb6a1357d9390a81595bce7acfe96c68986cc Mon Sep 17 00:00:00 2001 From: Paul Schaub Date: Thu, 31 Mar 2022 21:56:24 +0200 Subject: [PATCH] Fix changelog and change method signature --- CHANGELOG.md | 4 +- .../CRLFGeneratorStream.java | 15 ----- .../encryption_signing/ProducerOptions.java | 9 ++- .../CanonicalizedDataEncryptionTest.java | 64 ++++++++++++++++--- 4 files changed, 60 insertions(+), 32 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 797d7d64..44686127 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,9 +7,9 @@ SPDX-License-Identifier: CC0-1.0 ## 1.1.5-SNAPSHOT - SOP encrypt: match signature type when using `encrypt --as=` option -- `ProducerOptions.setEncoding()`: The encoding is henceforth only considered metadata and will no longer trigger CRLF encoding +- `ProducerOptions.setEncoding()`: The encoding is henceforth only considered metadata and will no longer trigger CRLF encoding. - This fixes broken signature generation for mismatching (`StreamEncoding`,`DocumentSignatureType`) tuples. - - Applications that rely on CRLF-encoding must now apply that encoding themselves (see [#264](https://github.com/pgpainless/pgpainless/issues/264#issuecomment-1083206738) for details). + - Applications that rely on CRLF-encoding can request PGPainless to apply this encoding by calling `ProducerOptions.applyCRLFEncoding(true)`. ## 1.1.4 - Add utility method `KeyRingUtils.removeSecretKey()` to remove secret key part from key ring diff --git a/pgpainless-core/src/main/java/org/pgpainless/encryption_signing/CRLFGeneratorStream.java b/pgpainless-core/src/main/java/org/pgpainless/encryption_signing/CRLFGeneratorStream.java index f5b13f2a..9743f6f9 100644 --- a/pgpainless-core/src/main/java/org/pgpainless/encryption_signing/CRLFGeneratorStream.java +++ b/pgpainless-core/src/main/java/org/pgpainless/encryption_signing/CRLFGeneratorStream.java @@ -12,21 +12,6 @@ import java.io.OutputStream; /** * {@link OutputStream} which applies CR-LF encoding of its input data, based on the desired {@link StreamEncoding}. - * - * - * If you need PGPainless to CRLF encode signed data for you, you could do the following: - * {@code - *
- *     InputStream plaintext = ...
- *     EncryptionStream signerOrEncryptor = PGPainless.signAndOrEncrypt(...);
- *     CRLFGeneratorStream crlfOut = new CRLFGeneratorStream(signerOrEncryptor, streamEncoding);
- *
- *     Streams.pipeAll(plaintext, crlfOut);
- *     crlfOut.close;
- *
- *     EncryptionResult result = signerOrEncryptor.getResult();
- * 
- * } * This implementation originates from the Bouncy Castle library. */ public class CRLFGeneratorStream extends OutputStream { 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 41d9ca85..ae335db4 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 @@ -249,17 +249,16 @@ public final class ProducerOptions { /** * Apply special encoding of line endings to the input data. - * By default, this is set to
false
, which means that the data is not altered. + * By default, this is disabled, which means that the data is not altered. * - * Setting it to
true
will change the line endings to CR/LF. + * Enabling it will change the line endings to CR/LF. * Note: The encoding will not be reversed when decrypting, so applying CR/LF encoding will result in * the identity "decrypt(encrypt(data)) == data == verify(sign(data))". * - * @param applyCRLFEncoding apply crlf encoding * @return this */ - public ProducerOptions applyCRLFEncoding(boolean applyCRLFEncoding) { - this.applyCRLFEncoding = applyCRLFEncoding; + public ProducerOptions applyCRLFEncoding() { + this.applyCRLFEncoding = true; return this; } diff --git a/pgpainless-core/src/test/java/org/pgpainless/decryption_verification/CanonicalizedDataEncryptionTest.java b/pgpainless-core/src/test/java/org/pgpainless/decryption_verification/CanonicalizedDataEncryptionTest.java index e1722343..c427af99 100644 --- a/pgpainless-core/src/test/java/org/pgpainless/decryption_verification/CanonicalizedDataEncryptionTest.java +++ b/pgpainless-core/src/test/java/org/pgpainless/decryption_verification/CanonicalizedDataEncryptionTest.java @@ -288,6 +288,47 @@ public class CanonicalizedDataEncryptionTest { } } + @Test + public void resultOfDecryptionIsCRLFEncoded() throws PGPException, IOException { + String before = "Foo\nBar!\n"; + String after = "Foo\r\nBar!\r\n"; + + String encrypted = encryptAndSign(before, DocumentSignatureType.BINARY_DOCUMENT, StreamEncoding.TEXT, true); + + ByteArrayInputStream in = new ByteArrayInputStream(encrypted.getBytes(StandardCharsets.UTF_8)); + DecryptionStream decryptionStream = PGPainless.decryptAndOrVerify() + .onInputStream(in) + .withOptions(new ConsumerOptions() + .addDecryptionKey(secretKeys, SecretKeyRingProtector.unprotectedKeys()) + .addVerificationCert(publicKeys)); + + ByteArrayOutputStream decrypted = new ByteArrayOutputStream(); + Streams.pipeAll(decryptionStream, decrypted); + decryptionStream.close(); + + assertArrayEquals(after.getBytes(StandardCharsets.UTF_8), decrypted.toByteArray()); + } + + @Test + public void resultOfDecryptionIsNotCRLFEncoded() throws PGPException, IOException { + String beforeAndAfter = "Foo\nBar!\n"; + + String encrypted = encryptAndSign(beforeAndAfter, DocumentSignatureType.BINARY_DOCUMENT, StreamEncoding.TEXT, false); + + ByteArrayInputStream in = new ByteArrayInputStream(encrypted.getBytes(StandardCharsets.UTF_8)); + DecryptionStream decryptionStream = PGPainless.decryptAndOrVerify() + .onInputStream(in) + .withOptions(new ConsumerOptions() + .addDecryptionKey(secretKeys, SecretKeyRingProtector.unprotectedKeys()) + .addVerificationCert(publicKeys)); + + ByteArrayOutputStream decrypted = new ByteArrayOutputStream(); + Streams.pipeAll(decryptionStream, decrypted); + decryptionStream.close(); + + assertArrayEquals(beforeAndAfter.getBytes(StandardCharsets.UTF_8), decrypted.toByteArray()); + } + private String encryptAndSign(String message, DocumentSignatureType sigType, StreamEncoding dataFormat, @@ -295,18 +336,21 @@ public class CanonicalizedDataEncryptionTest { throws PGPException, IOException { ByteArrayOutputStream out = new ByteArrayOutputStream(); + ProducerOptions options = ProducerOptions + .signAndEncrypt( + EncryptionOptions.encryptCommunications() + .addRecipient(publicKeys), + SigningOptions.get() + .addInlineSignature(SecretKeyRingProtector.unprotectedKeys(), secretKeys, sigType) + ) + .setEncoding(dataFormat); + if (applyCRLFEncoding) { + options.applyCRLFEncoding(); + } + EncryptionStream encryptionStream = PGPainless.encryptAndOrSign() .onOutputStream(out) - .withOptions(ProducerOptions - .signAndEncrypt( - EncryptionOptions.encryptCommunications() - .addRecipient(publicKeys), - SigningOptions.get() - .addInlineSignature(SecretKeyRingProtector.unprotectedKeys(), secretKeys, sigType) - ) - .setEncoding(dataFormat) - .applyCRLFEncoding(applyCRLFEncoding) - ); + .withOptions(options); ByteArrayInputStream inputStream = new ByteArrayInputStream(message.getBytes(StandardCharsets.UTF_8)); Streams.pipeAll(inputStream, encryptionStream);