mirror of
https://github.com/pgpainless/pgpainless.git
synced 2025-01-09 19:57:57 +01:00
Move file-related encryption-info into ProducerOptions
This commit is contained in:
parent
447c08b446
commit
2ba782c451
7 changed files with 111 additions and 77 deletions
|
@ -156,12 +156,12 @@ public class OpenPgpMetadata {
|
||||||
public static final String FOR_YOUR_EYES_ONLY = PGPLiteralData.CONSOLE;
|
public static final String FOR_YOUR_EYES_ONLY = PGPLiteralData.CONSOLE;
|
||||||
|
|
||||||
protected final String fileName;
|
protected final String fileName;
|
||||||
protected final Date modicationDate;
|
protected final Date modificationDate;
|
||||||
protected final StreamEncoding streamEncoding;
|
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.fileName = fileName == null ? "" : fileName;
|
||||||
this.modicationDate = modicationDate == null ? PGPLiteralData.NOW : modicationDate;
|
this.modificationDate = modificationDate == null ? PGPLiteralData.NOW : modificationDate;
|
||||||
this.streamEncoding = streamEncoding;
|
this.streamEncoding = streamEncoding;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -182,7 +182,7 @@ public class OpenPgpMetadata {
|
||||||
}
|
}
|
||||||
|
|
||||||
public Date getModificationDate() {
|
public Date getModificationDate() {
|
||||||
return modicationDate;
|
return modificationDate;
|
||||||
}
|
}
|
||||||
|
|
||||||
public StreamEncoding getStreamFormat() {
|
public StreamEncoding getStreamFormat() {
|
||||||
|
|
|
@ -27,18 +27,15 @@ import org.pgpainless.PGPainless;
|
||||||
import org.pgpainless.algorithm.CompressionAlgorithm;
|
import org.pgpainless.algorithm.CompressionAlgorithm;
|
||||||
import org.pgpainless.algorithm.SymmetricKeyAlgorithm;
|
import org.pgpainless.algorithm.SymmetricKeyAlgorithm;
|
||||||
import org.pgpainless.algorithm.negotiation.SymmetricKeyAlgorithmNegotiator;
|
import org.pgpainless.algorithm.negotiation.SymmetricKeyAlgorithmNegotiator;
|
||||||
import org.pgpainless.decryption_verification.OpenPgpMetadata;
|
|
||||||
import org.pgpainless.key.SubkeyIdentifier;
|
import org.pgpainless.key.SubkeyIdentifier;
|
||||||
|
|
||||||
public class EncryptionBuilder implements EncryptionBuilderInterface {
|
public class EncryptionBuilder implements EncryptionBuilderInterface {
|
||||||
|
|
||||||
private OutputStream outputStream;
|
private OutputStream outputStream;
|
||||||
private OpenPgpMetadata.FileInfo fileInfo;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WithOptions onOutputStream(@Nonnull OutputStream outputStream, OpenPgpMetadata.FileInfo fileInfo) {
|
public WithOptions onOutputStream(@Nonnull OutputStream outputStream) {
|
||||||
this.outputStream = outputStream;
|
this.outputStream = outputStream;
|
||||||
this.fileInfo = fileInfo;
|
|
||||||
return new WithOptionsImpl();
|
return new WithOptionsImpl();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,7 +45,7 @@ public class EncryptionBuilder implements EncryptionBuilderInterface {
|
||||||
if (options == null) {
|
if (options == null) {
|
||||||
throw new NullPointerException("ProducerOptions cannot be null.");
|
throw new NullPointerException("ProducerOptions cannot be null.");
|
||||||
}
|
}
|
||||||
return new EncryptionStream(outputStream, options, fileInfo);
|
return new EncryptionStream(outputStream, options);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,12 +17,9 @@ package org.pgpainless.encryption_signing;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.util.Date;
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
|
|
||||||
import org.bouncycastle.openpgp.PGPException;
|
import org.bouncycastle.openpgp.PGPException;
|
||||||
import org.pgpainless.algorithm.StreamEncoding;
|
|
||||||
import org.pgpainless.decryption_verification.OpenPgpMetadata;
|
|
||||||
|
|
||||||
public interface EncryptionBuilderInterface {
|
public interface EncryptionBuilderInterface {
|
||||||
|
|
||||||
|
@ -33,47 +30,7 @@ public interface EncryptionBuilderInterface {
|
||||||
* @param outputStream output stream of the plain data.
|
* @param outputStream output stream of the plain data.
|
||||||
* @return api handle
|
* @return api handle
|
||||||
*/
|
*/
|
||||||
default WithOptions onOutputStream(@Nonnull OutputStream outputStream) {
|
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);
|
|
||||||
|
|
||||||
interface WithOptions {
|
interface WithOptions {
|
||||||
|
|
||||||
|
|
|
@ -33,8 +33,8 @@ import org.pgpainless.algorithm.EncryptionPurpose;
|
||||||
import org.pgpainless.algorithm.SymmetricKeyAlgorithm;
|
import org.pgpainless.algorithm.SymmetricKeyAlgorithm;
|
||||||
import org.pgpainless.implementation.ImplementationFactory;
|
import org.pgpainless.implementation.ImplementationFactory;
|
||||||
import org.pgpainless.key.SubkeyIdentifier;
|
import org.pgpainless.key.SubkeyIdentifier;
|
||||||
import org.pgpainless.key.info.KeyRingInfo;
|
|
||||||
import org.pgpainless.key.info.KeyAccessor;
|
import org.pgpainless.key.info.KeyAccessor;
|
||||||
|
import org.pgpainless.key.info.KeyRingInfo;
|
||||||
import org.pgpainless.util.Passphrase;
|
import org.pgpainless.util.Passphrase;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -62,8 +62,7 @@ public final class EncryptionStream extends OutputStream {
|
||||||
private OutputStream literalDataStream;
|
private OutputStream literalDataStream;
|
||||||
|
|
||||||
EncryptionStream(@Nonnull OutputStream targetOutputStream,
|
EncryptionStream(@Nonnull OutputStream targetOutputStream,
|
||||||
@Nonnull ProducerOptions options,
|
@Nonnull ProducerOptions options)
|
||||||
@Nonnull OpenPgpMetadata.FileInfo fileInfo)
|
|
||||||
throws IOException, PGPException {
|
throws IOException, PGPException {
|
||||||
this.options = options;
|
this.options = options;
|
||||||
outermostStream = targetOutputStream;
|
outermostStream = targetOutputStream;
|
||||||
|
@ -72,7 +71,7 @@ public final class EncryptionStream extends OutputStream {
|
||||||
prepareEncryption();
|
prepareEncryption();
|
||||||
prepareCompression();
|
prepareCompression();
|
||||||
prepareOnePassSignatures();
|
prepareOnePassSignatures();
|
||||||
prepareLiteralDataProcessing(fileInfo);
|
prepareLiteralDataProcessing();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void prepareArmor() {
|
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();
|
literalDataGenerator = new PGPLiteralDataGenerator();
|
||||||
literalDataStream = literalDataGenerator.open(outermostStream,
|
literalDataStream = literalDataGenerator.open(outermostStream,
|
||||||
fileInfo.getStreamFormat().getCode(),
|
options.getEncoding().getCode(),
|
||||||
fileInfo.getFileName(),
|
options.getFileName(),
|
||||||
fileInfo.getModificationDate(),
|
options.getModificationDate(),
|
||||||
new byte[BUFFER_SIZE]);
|
new byte[BUFFER_SIZE]);
|
||||||
outermostStream = literalDataStream;
|
outermostStream = literalDataStream;
|
||||||
resultBuilder.setFileInfo(fileInfo);
|
|
||||||
|
resultBuilder.setFileInfo(new OpenPgpMetadata.FileInfo(
|
||||||
|
options.getFileName(), options.getModificationDate(), options.getEncoding()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -15,15 +15,22 @@
|
||||||
*/
|
*/
|
||||||
package org.pgpainless.encryption_signing;
|
package org.pgpainless.encryption_signing;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
import org.bouncycastle.openpgp.PGPLiteralData;
|
||||||
import org.pgpainless.PGPainless;
|
import org.pgpainless.PGPainless;
|
||||||
import org.pgpainless.algorithm.CompressionAlgorithm;
|
import org.pgpainless.algorithm.CompressionAlgorithm;
|
||||||
|
import org.pgpainless.algorithm.StreamEncoding;
|
||||||
|
|
||||||
public final class ProducerOptions {
|
public final class ProducerOptions {
|
||||||
|
|
||||||
private final EncryptionOptions encryptionOptions;
|
private final EncryptionOptions encryptionOptions;
|
||||||
private final SigningOptions signingOptions;
|
private final SigningOptions signingOptions;
|
||||||
|
private String fileName = "";
|
||||||
|
private Date modificationDate = PGPLiteralData.NOW;
|
||||||
|
private StreamEncoding streamEncoding = StreamEncoding.BINARY;
|
||||||
|
|
||||||
private CompressionAlgorithm compressionAlgorithmOverride = PGPainless.getPolicy().getCompressionAlgorithmPolicy()
|
private CompressionAlgorithm compressionAlgorithmOverride = PGPainless.getPolicy().getCompressionAlgorithmPolicy()
|
||||||
.defaultCompressionAlgorithm();
|
.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.
|
* Specify, whether or not the result of the encryption/signing operation shall be ascii armored.
|
||||||
* The default value is true.
|
* The default value is true.
|
||||||
|
@ -121,6 +114,89 @@ public final class ProducerOptions {
|
||||||
return asciiArmor;
|
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 <a href="https://datatracker.ietf.org/doc/html/rfc4880#section-5.9">RFC4880 §5.9. Literal Data Packet</a>
|
||||||
|
*
|
||||||
|
* @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() {
|
public CompressionAlgorithm getCompressionAlgorithmOverride() {
|
||||||
return compressionAlgorithmOverride;
|
return compressionAlgorithmOverride;
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,11 +66,14 @@ public class FileInfoTest {
|
||||||
ByteArrayInputStream dataIn = new ByteArrayInputStream(data.getBytes(StandardCharsets.UTF_8));
|
ByteArrayInputStream dataIn = new ByteArrayInputStream(data.getBytes(StandardCharsets.UTF_8));
|
||||||
ByteArrayOutputStream dataOut = new ByteArrayOutputStream();
|
ByteArrayOutputStream dataOut = new ByteArrayOutputStream();
|
||||||
EncryptionStream encryptionStream = PGPainless.encryptAndOrSign()
|
EncryptionStream encryptionStream = PGPainless.encryptAndOrSign()
|
||||||
.onOutputStream(dataOut, fileInfo)
|
.onOutputStream(dataOut)
|
||||||
.withOptions(ProducerOptions.encrypt(
|
.withOptions(ProducerOptions.encrypt(
|
||||||
EncryptionOptions
|
EncryptionOptions
|
||||||
.encryptCommunications()
|
.encryptCommunications()
|
||||||
.addRecipient(publicKeys))
|
.addRecipient(publicKeys))
|
||||||
|
.setEncoding(fileInfo.getStreamFormat())
|
||||||
|
.setFileName(fileInfo.getFileName())
|
||||||
|
.setModificationDate(fileInfo.getModificationDate())
|
||||||
);
|
);
|
||||||
|
|
||||||
Streams.pipeAll(dataIn, encryptionStream);
|
Streams.pipeAll(dataIn, encryptionStream);
|
||||||
|
|
Loading…
Reference in a new issue