diff --git a/pgpainless-core/src/main/java/org/pgpainless/decryption_verification/OpenPgpMetadata.java b/pgpainless-core/src/main/java/org/pgpainless/decryption_verification/OpenPgpMetadata.java index bff32fdf..624ae3ca 100644 --- a/pgpainless-core/src/main/java/org/pgpainless/decryption_verification/OpenPgpMetadata.java +++ b/pgpainless-core/src/main/java/org/pgpainless/decryption_verification/OpenPgpMetadata.java @@ -156,12 +156,12 @@ public class OpenPgpMetadata { public static final String FOR_YOUR_EYES_ONLY = PGPLiteralData.CONSOLE; protected final String fileName; - protected final Date modicationDate; + protected final Date modificationDate; protected final StreamEncoding streamEncoding; - public FileInfo(String fileName, Date modicationDate, StreamEncoding streamEncoding) { + public FileInfo(String fileName, Date modificationDate, StreamEncoding streamEncoding) { this.fileName = fileName == null ? "" : fileName; - this.modicationDate = modicationDate == null ? PGPLiteralData.NOW : modicationDate; + this.modificationDate = modificationDate == null ? PGPLiteralData.NOW : modificationDate; this.streamEncoding = streamEncoding; } @@ -182,7 +182,7 @@ public class OpenPgpMetadata { } public Date getModificationDate() { - return modicationDate; + return modificationDate; } public StreamEncoding getStreamFormat() { diff --git a/pgpainless-core/src/main/java/org/pgpainless/encryption_signing/EncryptionBuilder.java b/pgpainless-core/src/main/java/org/pgpainless/encryption_signing/EncryptionBuilder.java index 8c1b70e2..00a9ac82 100644 --- a/pgpainless-core/src/main/java/org/pgpainless/encryption_signing/EncryptionBuilder.java +++ b/pgpainless-core/src/main/java/org/pgpainless/encryption_signing/EncryptionBuilder.java @@ -27,18 +27,15 @@ import org.pgpainless.PGPainless; import org.pgpainless.algorithm.CompressionAlgorithm; import org.pgpainless.algorithm.SymmetricKeyAlgorithm; import org.pgpainless.algorithm.negotiation.SymmetricKeyAlgorithmNegotiator; -import org.pgpainless.decryption_verification.OpenPgpMetadata; import org.pgpainless.key.SubkeyIdentifier; public class EncryptionBuilder implements EncryptionBuilderInterface { private OutputStream outputStream; - private OpenPgpMetadata.FileInfo fileInfo; @Override - public WithOptions onOutputStream(@Nonnull OutputStream outputStream, OpenPgpMetadata.FileInfo fileInfo) { + public WithOptions onOutputStream(@Nonnull OutputStream outputStream) { this.outputStream = outputStream; - this.fileInfo = fileInfo; return new WithOptionsImpl(); } @@ -48,7 +45,7 @@ public class EncryptionBuilder implements EncryptionBuilderInterface { if (options == null) { throw new NullPointerException("ProducerOptions cannot be null."); } - return new EncryptionStream(outputStream, options, fileInfo); + return new EncryptionStream(outputStream, options); } } diff --git a/pgpainless-core/src/main/java/org/pgpainless/encryption_signing/EncryptionBuilderInterface.java b/pgpainless-core/src/main/java/org/pgpainless/encryption_signing/EncryptionBuilderInterface.java index 7f1d60cb..9b8abf59 100644 --- a/pgpainless-core/src/main/java/org/pgpainless/encryption_signing/EncryptionBuilderInterface.java +++ b/pgpainless-core/src/main/java/org/pgpainless/encryption_signing/EncryptionBuilderInterface.java @@ -17,12 +17,9 @@ package org.pgpainless.encryption_signing; import java.io.IOException; import java.io.OutputStream; -import java.util.Date; import javax.annotation.Nonnull; import org.bouncycastle.openpgp.PGPException; -import org.pgpainless.algorithm.StreamEncoding; -import org.pgpainless.decryption_verification.OpenPgpMetadata; public interface EncryptionBuilderInterface { @@ -33,47 +30,7 @@ public interface EncryptionBuilderInterface { * @param outputStream output stream of the plain data. * @return api handle */ - default WithOptions onOutputStream(@Nonnull OutputStream outputStream) { - return onOutputStream(outputStream, OpenPgpMetadata.FileInfo.binaryStream()); - } - /** - * Create a {@link EncryptionStream} on an {@link OutputStream} that contains the plain data which shall - * be encrypted and/or signed. - * - * @param outputStream outputStream - * @param forYourEyesOnly flag indicating that the data is intended for the recipients eyes only - * @return api handle - * - * @deprecated use {@link #onOutputStream(OutputStream, OpenPgpMetadata.FileInfo)} instead. - */ - default WithOptions onOutputStream(@Nonnull OutputStream outputStream, boolean forYourEyesOnly) { - return onOutputStream(outputStream, forYourEyesOnly ? OpenPgpMetadata.FileInfo.forYourEyesOnly() : OpenPgpMetadata.FileInfo.binaryStream()); - } - - /** - * Creates a {@link EncryptionStream} on an {@link OutputStream} that contains the plain data which shall - * be encrypted and/or signed. - * - * @param outputStream outputStream - * @param fileName name of the file (or "" if the encrypted data is not a file) - * @param forYourEyesOnly flag indicating that the data is intended for the recipients eyes only - * @return api handle - * - * @deprecated use {@link #onOutputStream(OutputStream, OpenPgpMetadata.FileInfo)} instead. - */ - default WithOptions onOutputStream(@Nonnull OutputStream outputStream, String fileName, boolean forYourEyesOnly) { - return onOutputStream(outputStream, new OpenPgpMetadata.FileInfo(forYourEyesOnly ? "_CONSOLE" : fileName, new Date(), StreamEncoding.BINARY)); - } - - /** - * Create an {@link EncryptionStream} on an {@link OutputStream} that contains the plain data which shall - * be encrypted and/or signed. - * - * @param outputStream outputStream - * @param fileInfo file information - * @return api handle - */ - WithOptions onOutputStream(@Nonnull OutputStream outputStream, OpenPgpMetadata.FileInfo fileInfo); + WithOptions onOutputStream(@Nonnull OutputStream outputStream); interface WithOptions { diff --git a/pgpainless-core/src/main/java/org/pgpainless/encryption_signing/EncryptionOptions.java b/pgpainless-core/src/main/java/org/pgpainless/encryption_signing/EncryptionOptions.java index 5d08ba65..78ea155c 100644 --- a/pgpainless-core/src/main/java/org/pgpainless/encryption_signing/EncryptionOptions.java +++ b/pgpainless-core/src/main/java/org/pgpainless/encryption_signing/EncryptionOptions.java @@ -33,8 +33,8 @@ import org.pgpainless.algorithm.EncryptionPurpose; import org.pgpainless.algorithm.SymmetricKeyAlgorithm; import org.pgpainless.implementation.ImplementationFactory; import org.pgpainless.key.SubkeyIdentifier; -import org.pgpainless.key.info.KeyRingInfo; import org.pgpainless.key.info.KeyAccessor; +import org.pgpainless.key.info.KeyRingInfo; import org.pgpainless.util.Passphrase; /** 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 90635869..8b9b9a19 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 @@ -62,8 +62,7 @@ public final class EncryptionStream extends OutputStream { private OutputStream literalDataStream; EncryptionStream(@Nonnull OutputStream targetOutputStream, - @Nonnull ProducerOptions options, - @Nonnull OpenPgpMetadata.FileInfo fileInfo) + @Nonnull ProducerOptions options) throws IOException, PGPException { this.options = options; outermostStream = targetOutputStream; @@ -72,7 +71,7 @@ public final class EncryptionStream extends OutputStream { prepareEncryption(); prepareCompression(); prepareOnePassSignatures(); - prepareLiteralDataProcessing(fileInfo); + prepareLiteralDataProcessing(); } private void prepareArmor() { @@ -146,15 +145,17 @@ public final class EncryptionStream extends OutputStream { } } - private void prepareLiteralDataProcessing(@Nonnull OpenPgpMetadata.FileInfo fileInfo) throws IOException { + private void prepareLiteralDataProcessing() throws IOException { literalDataGenerator = new PGPLiteralDataGenerator(); literalDataStream = literalDataGenerator.open(outermostStream, - fileInfo.getStreamFormat().getCode(), - fileInfo.getFileName(), - fileInfo.getModificationDate(), + options.getEncoding().getCode(), + options.getFileName(), + options.getModificationDate(), new byte[BUFFER_SIZE]); outermostStream = literalDataStream; - resultBuilder.setFileInfo(fileInfo); + + resultBuilder.setFileInfo(new OpenPgpMetadata.FileInfo( + options.getFileName(), options.getModificationDate(), options.getEncoding())); } @Override 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 0bf1411e..851ee56c 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 @@ -15,15 +15,22 @@ */ package org.pgpainless.encryption_signing; +import java.util.Date; +import javax.annotation.Nonnull; import javax.annotation.Nullable; +import org.bouncycastle.openpgp.PGPLiteralData; import org.pgpainless.PGPainless; import org.pgpainless.algorithm.CompressionAlgorithm; +import org.pgpainless.algorithm.StreamEncoding; public final class ProducerOptions { private final EncryptionOptions encryptionOptions; private final SigningOptions signingOptions; + private String fileName = ""; + private Date modificationDate = PGPLiteralData.NOW; + private StreamEncoding streamEncoding = StreamEncoding.BINARY; private CompressionAlgorithm compressionAlgorithmOverride = PGPainless.getPolicy().getCompressionAlgorithmPolicy() .defaultCompressionAlgorithm(); @@ -86,20 +93,6 @@ public final class ProducerOptions { } } - /** - * Override which compression algorithm shall be used. - * - * @param compressionAlgorithm compression algorithm override - * @return builder - */ - public ProducerOptions overrideCompressionAlgorithm(CompressionAlgorithm compressionAlgorithm) { - if (compressionAlgorithm == null) { - throw new NullPointerException("Compression algorithm cannot be null."); - } - this.compressionAlgorithmOverride = compressionAlgorithm; - return this; - } - /** * Specify, whether or not the result of the encryption/signing operation shall be ascii armored. * The default value is true. @@ -121,6 +114,89 @@ public final class ProducerOptions { return asciiArmor; } + /** + * Set the name of the encrypted file. + * Note: This option cannot be used simultaneously with {@link #setForYourEyesOnly()}. + * + * @param fileName name of the encrypted file + * @return this + */ + public ProducerOptions setFileName(@Nonnull String fileName) { + this.fileName = fileName; + return this; + } + + /** + * Return the encrypted files name. + * + * @return file name + */ + public String getFileName() { + return fileName; + } + + /** + * Mark the encrypted message as for-your-eyes-only by setting a special file name. + * Note: Therefore this method cannot be used simultaneously with {@link #setFileName(String)}. + * + * @return this + */ + public ProducerOptions setForYourEyesOnly() { + this.fileName = PGPLiteralData.CONSOLE; + return this; + } + + /** + * Set the modification date of the encrypted file. + * + * @param modificationDate Modification date of the encrypted file. + * @return this + */ + public ProducerOptions setModificationDate(@Nonnull Date modificationDate) { + this.modificationDate = modificationDate; + return this; + } + + /** + * Return the modification date of the encrypted file. + * + * @return modification date + */ + public Date getModificationDate() { + return modificationDate; + } + + /** + * Set the format of the literal data packet. + * Defaults to {@link StreamEncoding#BINARY}. + * + * @see RFC4880 ยง5.9. Literal Data Packet + * + * @param encoding encoding + * @return this + */ + public ProducerOptions setEncoding(@Nonnull StreamEncoding encoding) { + this.streamEncoding = encoding; + return this; + } + + public StreamEncoding getEncoding() { + return streamEncoding; + } + /** + * Override which compression algorithm shall be used. + * + * @param compressionAlgorithm compression algorithm override + * @return builder + */ + public ProducerOptions overrideCompressionAlgorithm(CompressionAlgorithm compressionAlgorithm) { + if (compressionAlgorithm == null) { + throw new NullPointerException("Compression algorithm cannot be null."); + } + this.compressionAlgorithmOverride = compressionAlgorithm; + return this; + } + public CompressionAlgorithm getCompressionAlgorithmOverride() { return compressionAlgorithmOverride; } diff --git a/pgpainless-core/src/test/java/org/pgpainless/encryption_signing/FileInfoTest.java b/pgpainless-core/src/test/java/org/pgpainless/encryption_signing/FileInfoTest.java index 9009d8de..ad83cdc6 100644 --- a/pgpainless-core/src/test/java/org/pgpainless/encryption_signing/FileInfoTest.java +++ b/pgpainless-core/src/test/java/org/pgpainless/encryption_signing/FileInfoTest.java @@ -66,11 +66,14 @@ public class FileInfoTest { ByteArrayInputStream dataIn = new ByteArrayInputStream(data.getBytes(StandardCharsets.UTF_8)); ByteArrayOutputStream dataOut = new ByteArrayOutputStream(); EncryptionStream encryptionStream = PGPainless.encryptAndOrSign() - .onOutputStream(dataOut, fileInfo) + .onOutputStream(dataOut) .withOptions(ProducerOptions.encrypt( EncryptionOptions .encryptCommunications() .addRecipient(publicKeys)) + .setEncoding(fileInfo.getStreamFormat()) + .setFileName(fileInfo.getFileName()) + .setModificationDate(fileInfo.getModificationDate()) ); Streams.pipeAll(dataIn, encryptionStream);