mirror of
https://github.com/pgpainless/pgpainless.git
synced 2025-01-08 19:27:57 +01:00
Add new ProducerOption setComment() for Ascii armored EncryptionStreams. (#254)
* Add new ProducerOption setComment() for Ascii armored EncryptionStreams.
This commit is contained in:
parent
1753cef10e
commit
928fa12b51
3 changed files with 106 additions and 0 deletions
|
@ -23,6 +23,7 @@ import org.pgpainless.algorithm.CompressionAlgorithm;
|
|||
import org.pgpainless.algorithm.SymmetricKeyAlgorithm;
|
||||
import org.pgpainless.implementation.ImplementationFactory;
|
||||
import org.pgpainless.key.SubkeyIdentifier;
|
||||
import org.pgpainless.util.ArmorUtils;
|
||||
import org.pgpainless.util.ArmoredOutputStreamFactory;
|
||||
import org.pgpainless.util.StreamGeneratorWrapper;
|
||||
import org.slf4j.Logger;
|
||||
|
@ -74,6 +75,9 @@ public final class EncryptionStream extends OutputStream {
|
|||
|
||||
LOGGER.debug("Wrap encryption output in ASCII armor");
|
||||
armorOutputStream = ArmoredOutputStreamFactory.get(outermostStream);
|
||||
if (options.hasComment()) {
|
||||
ArmorUtils.addCommentHeader(armorOutputStream, options.getComment());
|
||||
}
|
||||
outermostStream = armorOutputStream;
|
||||
}
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@ public final class ProducerOptions {
|
|||
private CompressionAlgorithm compressionAlgorithmOverride = PGPainless.getPolicy().getCompressionAlgorithmPolicy()
|
||||
.defaultCompressionAlgorithm();
|
||||
private boolean asciiArmor = true;
|
||||
private String comment = null;
|
||||
|
||||
private ProducerOptions(EncryptionOptions encryptionOptions, SigningOptions signingOptions) {
|
||||
this.encryptionOptions = encryptionOptions;
|
||||
|
@ -107,6 +108,40 @@ public final class ProducerOptions {
|
|||
return asciiArmor;
|
||||
}
|
||||
|
||||
/**
|
||||
* set the comment for header in ascii armored output.
|
||||
* The default value is null, which means no comment header is added.
|
||||
* Multiline comments are possible using '\\n'.
|
||||
*
|
||||
* @param comment comment header text
|
||||
* @return builder
|
||||
*/
|
||||
public ProducerOptions setComment(String comment) {
|
||||
if (!asciiArmor) {
|
||||
throw new IllegalArgumentException("Comment can only be set when ASCII armoring is enabled.");
|
||||
}
|
||||
this.comment = comment;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return comment set for header in ascii armored output.
|
||||
*
|
||||
* @return comment
|
||||
*/
|
||||
public String getComment() {
|
||||
return comment;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether a comment was set (!= null).
|
||||
*
|
||||
* @return comment
|
||||
*/
|
||||
public boolean hasComment() {
|
||||
return comment != null;
|
||||
}
|
||||
|
||||
public ProducerOptions setCleartextSigned() {
|
||||
if (signingOptions == null) {
|
||||
throw new IllegalArgumentException("Signing Options cannot be null if cleartext signing is enabled.");
|
||||
|
|
|
@ -129,4 +129,71 @@ public class Encrypt {
|
|||
|
||||
assertEquals(message, plaintext.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* In this example, Alice is sending a signed and encrypted message to Bob.
|
||||
* She encrypts the message to both bobs certificate and her own.
|
||||
* A comment header with the text "This comment was added using options." is added
|
||||
* using the fluent ProducerOption syntax.
|
||||
*
|
||||
* Bob subsequently decrypts the message using his key.
|
||||
*/
|
||||
@Test
|
||||
public void encryptWithCommentHeader() throws PGPException, InvalidAlgorithmParameterException, NoSuchAlgorithmException, IOException {
|
||||
// Prepare keys
|
||||
PGPSecretKeyRing keyAlice = PGPainless.generateKeyRing()
|
||||
.modernKeyRing("alice@pgpainless.org", null);
|
||||
PGPPublicKeyRing certificateAlice = KeyRingUtils.publicKeyRingFrom(keyAlice);
|
||||
|
||||
PGPSecretKeyRing keyBob = PGPainless.generateKeyRing()
|
||||
.modernKeyRing("bob@pgpainless.org", null);
|
||||
PGPPublicKeyRing certificateBob = KeyRingUtils.publicKeyRingFrom(keyBob);
|
||||
SecretKeyRingProtector protectorBob = SecretKeyRingProtector.unprotectedKeys();
|
||||
|
||||
// plaintext message to encrypt
|
||||
String message = "Hello, World!\n";
|
||||
String comment = "This comment was added using options.";
|
||||
ByteArrayOutputStream ciphertext = new ByteArrayOutputStream();
|
||||
// Encrypt and sign
|
||||
EncryptionStream encryptor = PGPainless.encryptAndOrSign()
|
||||
.onOutputStream(ciphertext)
|
||||
.withOptions(ProducerOptions.encrypt(
|
||||
// we want to encrypt communication (affects key selection based on key flags)
|
||||
EncryptionOptions.encryptCommunications()
|
||||
.addRecipient(certificateBob)
|
||||
.addRecipient(certificateAlice)
|
||||
).setAsciiArmor(true)
|
||||
.setComment(comment)
|
||||
);
|
||||
|
||||
// Pipe data trough and CLOSE the stream (important)
|
||||
Streams.pipeAll(new ByteArrayInputStream(message.getBytes(StandardCharsets.UTF_8)), encryptor);
|
||||
encryptor.close();
|
||||
String encryptedMessage = ciphertext.toString();
|
||||
|
||||
// check that comment header was added after "BEGIN PGP" and "Version:"
|
||||
assertEquals(encryptedMessage.split("\n")[2].trim(), "Comment: " + comment);
|
||||
|
||||
// also test, that decryption still works...
|
||||
|
||||
// Decrypt and verify signatures
|
||||
DecryptionStream decryptor = PGPainless.decryptAndOrVerify()
|
||||
.onInputStream(new ByteArrayInputStream(encryptedMessage.getBytes(StandardCharsets.UTF_8)))
|
||||
.withOptions(new ConsumerOptions()
|
||||
.addDecryptionKey(keyBob, protectorBob)
|
||||
.addVerificationCert(certificateAlice)
|
||||
);
|
||||
|
||||
ByteArrayOutputStream plaintext = new ByteArrayOutputStream();
|
||||
|
||||
Streams.pipeAll(decryptor, plaintext);
|
||||
decryptor.close();
|
||||
|
||||
// Check the metadata to see how the message was encrypted/signed
|
||||
OpenPgpMetadata metadata = decryptor.getResult();
|
||||
assertTrue(metadata.isEncrypted());
|
||||
assertEquals(message, plaintext.toString());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue