2022-03-24 14:16:46 +01:00
|
|
|
// SPDX-FileCopyrightText: 2022 Paul Schaub <vanitasvitae@fsfe.org>
|
|
|
|
//
|
|
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
|
2022-03-31 15:03:50 +02:00
|
|
|
package org.pgpainless.decryption_verification;
|
2022-03-24 14:16:46 +01:00
|
|
|
|
2022-03-30 16:13:08 +02:00
|
|
|
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
|
|
|
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
2022-03-24 14:16:46 +01:00
|
|
|
import static org.junit.jupiter.api.Assertions.fail;
|
|
|
|
|
|
|
|
import java.io.ByteArrayInputStream;
|
|
|
|
import java.io.ByteArrayOutputStream;
|
|
|
|
import java.io.IOException;
|
2022-03-30 16:13:08 +02:00
|
|
|
import java.io.OutputStream;
|
2022-03-24 14:16:46 +01:00
|
|
|
import java.nio.charset.StandardCharsets;
|
|
|
|
|
2022-03-30 16:13:08 +02:00
|
|
|
import org.bouncycastle.bcpg.ArmoredOutputStream;
|
|
|
|
import org.bouncycastle.bcpg.CompressionAlgorithmTags;
|
|
|
|
import org.bouncycastle.openpgp.PGPCompressedDataGenerator;
|
2022-03-24 14:16:46 +01:00
|
|
|
import org.bouncycastle.openpgp.PGPException;
|
2022-03-30 16:13:08 +02:00
|
|
|
import org.bouncycastle.openpgp.PGPLiteralData;
|
|
|
|
import org.bouncycastle.openpgp.PGPLiteralDataGenerator;
|
|
|
|
import org.bouncycastle.openpgp.PGPOnePassSignature;
|
|
|
|
import org.bouncycastle.openpgp.PGPPrivateKey;
|
2022-03-24 14:16:46 +01:00
|
|
|
import org.bouncycastle.openpgp.PGPPublicKeyRing;
|
|
|
|
import org.bouncycastle.openpgp.PGPSecretKeyRing;
|
2022-03-30 16:13:08 +02:00
|
|
|
import org.bouncycastle.openpgp.PGPSignature;
|
|
|
|
import org.bouncycastle.openpgp.PGPSignatureGenerator;
|
|
|
|
import org.bouncycastle.openpgp.operator.bc.BcPGPContentSignerBuilder;
|
2022-03-24 14:16:46 +01:00
|
|
|
import org.bouncycastle.util.io.Streams;
|
|
|
|
import org.junit.jupiter.api.BeforeAll;
|
|
|
|
import org.junit.jupiter.api.Test;
|
|
|
|
import org.pgpainless.PGPainless;
|
|
|
|
import org.pgpainless.algorithm.DocumentSignatureType;
|
2022-03-30 16:13:08 +02:00
|
|
|
import org.pgpainless.algorithm.HashAlgorithm;
|
2022-03-24 14:16:46 +01:00
|
|
|
import org.pgpainless.algorithm.StreamEncoding;
|
2022-03-30 16:13:08 +02:00
|
|
|
import org.pgpainless.encryption_signing.CRLFGeneratorStream;
|
2022-03-24 14:16:46 +01:00
|
|
|
import org.pgpainless.encryption_signing.EncryptionOptions;
|
|
|
|
import org.pgpainless.encryption_signing.EncryptionStream;
|
|
|
|
import org.pgpainless.encryption_signing.ProducerOptions;
|
|
|
|
import org.pgpainless.encryption_signing.SigningOptions;
|
|
|
|
import org.pgpainless.key.protection.SecretKeyRingProtector;
|
2022-03-30 16:13:08 +02:00
|
|
|
import org.pgpainless.key.protection.UnlockSecretKey;
|
2022-03-24 14:16:46 +01:00
|
|
|
|
|
|
|
public class CanonicalizedDataEncryptionTest {
|
|
|
|
|
|
|
|
private static final String KEY = "-----BEGIN PGP PRIVATE KEY BLOCK-----\n" +
|
|
|
|
"Version: PGPainless\n" +
|
|
|
|
"Comment: 9AF4 29C4 C389 CC11 1739 98E9 9F8E E9C5 3AE5 C1A4\n" +
|
|
|
|
"Comment: Test <test@vanitasvi.tae>\n" +
|
|
|
|
"\n" +
|
|
|
|
"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\n" +
|
|
|
|
"=EyDf\n" +
|
|
|
|
"-----END PGP PRIVATE KEY BLOCK-----\n";
|
|
|
|
|
|
|
|
String message = "Hello, World!\n";
|
|
|
|
|
|
|
|
private static PGPSecretKeyRing secretKeys;
|
|
|
|
private static PGPPublicKeyRing publicKeys;
|
|
|
|
|
|
|
|
@BeforeAll
|
|
|
|
public static void readKeys() throws IOException {
|
|
|
|
secretKeys = PGPainless.readKeyRing().secretKeyRing(KEY);
|
|
|
|
publicKeys = PGPainless.extractCertificate(secretKeys);
|
2022-03-30 12:21:53 +02:00
|
|
|
// CHECKSTYLE:OFF
|
2022-03-24 14:16:46 +01:00
|
|
|
System.out.println(PGPainless.asciiArmor(secretKeys));
|
2022-03-30 12:21:53 +02:00
|
|
|
// CHECKSTYLE:ON
|
2022-03-24 14:16:46 +01:00
|
|
|
}
|
|
|
|
|
2022-03-31 15:03:50 +02:00
|
|
|
// NO CR/LF ENCODING PRIOR TO PROCESSING
|
|
|
|
|
|
|
|
@Test
|
|
|
|
public void noInputEncodingBinaryDataBinarySig() throws PGPException, IOException {
|
|
|
|
String msg = encryptAndSign(message, DocumentSignatureType.BINARY_DOCUMENT, StreamEncoding.BINARY, false);
|
|
|
|
OpenPgpMetadata metadata = decryptAndVerify(msg);
|
|
|
|
|
|
|
|
if (!metadata.isVerified()) {
|
|
|
|
// CHECKSTYLE:OFF
|
|
|
|
System.out.println("Not verified. Session-Key: " + metadata.getSessionKey());
|
|
|
|
System.out.println(msg);
|
|
|
|
// CHECKSTYLE:ON
|
|
|
|
fail();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Test
|
|
|
|
public void noInputEncodingBinaryDataTextSig() throws PGPException, IOException {
|
|
|
|
String msg = encryptAndSign(message, DocumentSignatureType.CANONICAL_TEXT_DOCUMENT, StreamEncoding.BINARY, false);
|
|
|
|
OpenPgpMetadata metadata = decryptAndVerify(msg);
|
|
|
|
|
|
|
|
if (!metadata.isVerified()) {
|
|
|
|
// CHECKSTYLE:OFF
|
|
|
|
System.out.println("Not verified. Session-Key: " + metadata.getSessionKey());
|
|
|
|
System.out.println(msg);
|
|
|
|
// CHECKSTYLE:ON
|
|
|
|
fail();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Test
|
|
|
|
public void noInputEncodingTextDataBinarySig() throws PGPException, IOException {
|
|
|
|
String msg = encryptAndSign(message, DocumentSignatureType.BINARY_DOCUMENT, StreamEncoding.TEXT, false);
|
|
|
|
OpenPgpMetadata metadata = decryptAndVerify(msg);
|
|
|
|
|
|
|
|
if (!metadata.isVerified()) {
|
|
|
|
// CHECKSTYLE:OFF
|
|
|
|
System.out.println("Not verified. Session-Key: " + metadata.getSessionKey());
|
|
|
|
System.out.println(msg);
|
|
|
|
// CHECKSTYLE:ON
|
|
|
|
fail();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Test
|
|
|
|
public void noInputEncodingTextDataTextSig() throws PGPException, IOException {
|
|
|
|
String msg = encryptAndSign(message, DocumentSignatureType.CANONICAL_TEXT_DOCUMENT, StreamEncoding.TEXT, false);
|
|
|
|
OpenPgpMetadata metadata = decryptAndVerify(msg);
|
|
|
|
|
|
|
|
if (!metadata.isVerified()) {
|
|
|
|
// CHECKSTYLE:OFF
|
|
|
|
System.out.println("Not verified. Session-Key: " + metadata.getSessionKey());
|
|
|
|
System.out.println(msg);
|
|
|
|
// CHECKSTYLE:ON
|
|
|
|
fail();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Test
|
|
|
|
public void noInputEncodingUtf8DataBinarySig() throws PGPException, IOException {
|
|
|
|
String msg = encryptAndSign(message, DocumentSignatureType.BINARY_DOCUMENT, StreamEncoding.UTF8, false);
|
|
|
|
OpenPgpMetadata metadata = decryptAndVerify(msg);
|
|
|
|
|
|
|
|
if (!metadata.isVerified()) {
|
|
|
|
// CHECKSTYLE:OFF
|
|
|
|
System.out.println("Not verified. Session-Key: " + metadata.getSessionKey());
|
|
|
|
System.out.println(msg);
|
|
|
|
// CHECKSTYLE:ON
|
|
|
|
fail();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Test
|
|
|
|
public void noInputEncodingUtf8DataTextSig() throws PGPException, IOException {
|
|
|
|
String msg = encryptAndSign(message, DocumentSignatureType.CANONICAL_TEXT_DOCUMENT, StreamEncoding.UTF8, false);
|
|
|
|
OpenPgpMetadata metadata = decryptAndVerify(msg);
|
|
|
|
|
|
|
|
if (!metadata.isVerified()) {
|
|
|
|
// CHECKSTYLE:OFF
|
|
|
|
System.out.println("Not verified. Session-Key: " + metadata.getSessionKey());
|
|
|
|
System.out.println(msg);
|
|
|
|
// CHECKSTYLE:ON
|
|
|
|
fail();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// APPLY CR/LF ENCODING PRIOR TO PROCESSING
|
|
|
|
|
2022-03-24 14:16:46 +01:00
|
|
|
@Test
|
2022-03-31 15:03:50 +02:00
|
|
|
public void inputEncodingBinaryDataBinarySig() throws PGPException, IOException {
|
|
|
|
String msg = encryptAndSign(message, DocumentSignatureType.BINARY_DOCUMENT, StreamEncoding.BINARY, true);
|
2022-03-24 14:16:46 +01:00
|
|
|
OpenPgpMetadata metadata = decryptAndVerify(msg);
|
|
|
|
|
|
|
|
if (!metadata.isVerified()) {
|
2022-03-30 12:21:53 +02:00
|
|
|
// CHECKSTYLE:OFF
|
2022-03-24 14:16:46 +01:00
|
|
|
System.out.println("Not verified. Session-Key: " + metadata.getSessionKey());
|
|
|
|
System.out.println(msg);
|
2022-03-30 12:21:53 +02:00
|
|
|
// CHECKSTYLE:ON
|
2022-03-24 14:16:46 +01:00
|
|
|
fail();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Test
|
2022-03-31 15:03:50 +02:00
|
|
|
public void inputEncodingBinaryDataTextSig() throws PGPException, IOException {
|
|
|
|
String msg = encryptAndSign(message, DocumentSignatureType.CANONICAL_TEXT_DOCUMENT, StreamEncoding.BINARY, true);
|
2022-03-24 14:16:46 +01:00
|
|
|
OpenPgpMetadata metadata = decryptAndVerify(msg);
|
|
|
|
|
|
|
|
if (!metadata.isVerified()) {
|
2022-03-30 12:21:53 +02:00
|
|
|
// CHECKSTYLE:OFF
|
2022-03-24 14:16:46 +01:00
|
|
|
System.out.println("Not verified. Session-Key: " + metadata.getSessionKey());
|
|
|
|
System.out.println(msg);
|
2022-03-30 12:21:53 +02:00
|
|
|
// CHECKSTYLE:ON
|
2022-03-24 14:16:46 +01:00
|
|
|
fail();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Test
|
2022-03-31 15:03:50 +02:00
|
|
|
public void inputEncodingTextDataBinarySig() throws PGPException, IOException {
|
|
|
|
String msg = encryptAndSign(message, DocumentSignatureType.BINARY_DOCUMENT, StreamEncoding.TEXT, true);
|
2022-03-24 14:16:46 +01:00
|
|
|
OpenPgpMetadata metadata = decryptAndVerify(msg);
|
|
|
|
|
|
|
|
if (!metadata.isVerified()) {
|
2022-03-30 12:21:53 +02:00
|
|
|
// CHECKSTYLE:OFF
|
2022-03-24 14:16:46 +01:00
|
|
|
System.out.println("Not verified. Session-Key: " + metadata.getSessionKey());
|
|
|
|
System.out.println(msg);
|
2022-03-30 12:21:53 +02:00
|
|
|
// CHECKSTYLE:ON
|
2022-03-24 14:16:46 +01:00
|
|
|
fail();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Test
|
2022-03-31 15:03:50 +02:00
|
|
|
public void inputEncodingTextDataTextSig() throws PGPException, IOException {
|
|
|
|
String msg = encryptAndSign(message, DocumentSignatureType.CANONICAL_TEXT_DOCUMENT, StreamEncoding.TEXT, true);
|
2022-03-24 14:16:46 +01:00
|
|
|
OpenPgpMetadata metadata = decryptAndVerify(msg);
|
|
|
|
|
|
|
|
if (!metadata.isVerified()) {
|
2022-03-30 12:21:53 +02:00
|
|
|
// CHECKSTYLE:OFF
|
2022-03-24 14:16:46 +01:00
|
|
|
System.out.println("Not verified. Session-Key: " + metadata.getSessionKey());
|
|
|
|
System.out.println(msg);
|
2022-03-30 12:21:53 +02:00
|
|
|
// CHECKSTYLE:ON
|
2022-03-24 14:16:46 +01:00
|
|
|
fail();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Test
|
2022-03-31 15:03:50 +02:00
|
|
|
public void inputEncodingUtf8DataBinarySig() throws PGPException, IOException {
|
|
|
|
String msg = encryptAndSign(message, DocumentSignatureType.BINARY_DOCUMENT, StreamEncoding.UTF8, true);
|
2022-03-24 14:16:46 +01:00
|
|
|
OpenPgpMetadata metadata = decryptAndVerify(msg);
|
|
|
|
|
|
|
|
if (!metadata.isVerified()) {
|
2022-03-30 12:21:53 +02:00
|
|
|
// CHECKSTYLE:OFF
|
2022-03-24 14:16:46 +01:00
|
|
|
System.out.println("Not verified. Session-Key: " + metadata.getSessionKey());
|
|
|
|
System.out.println(msg);
|
2022-03-30 12:21:53 +02:00
|
|
|
// CHECKSTYLE:ON
|
2022-03-24 14:16:46 +01:00
|
|
|
fail();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Test
|
2022-03-31 15:03:50 +02:00
|
|
|
public void inputEncodingUtf8DataTextSig() throws PGPException, IOException {
|
|
|
|
String msg = encryptAndSign(message, DocumentSignatureType.CANONICAL_TEXT_DOCUMENT, StreamEncoding.UTF8, true);
|
2022-03-24 14:16:46 +01:00
|
|
|
OpenPgpMetadata metadata = decryptAndVerify(msg);
|
|
|
|
|
|
|
|
if (!metadata.isVerified()) {
|
2022-03-30 12:21:53 +02:00
|
|
|
// CHECKSTYLE:OFF
|
2022-03-24 14:16:46 +01:00
|
|
|
System.out.println("Not verified. Session-Key: " + metadata.getSessionKey());
|
|
|
|
System.out.println(msg);
|
2022-03-30 12:21:53 +02:00
|
|
|
// CHECKSTYLE:ON
|
2022-03-24 14:16:46 +01:00
|
|
|
fail();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-03-31 21:56:24 +02:00
|
|
|
@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());
|
|
|
|
}
|
|
|
|
|
2022-03-31 15:03:50 +02:00
|
|
|
private String encryptAndSign(String message,
|
|
|
|
DocumentSignatureType sigType,
|
|
|
|
StreamEncoding dataFormat,
|
|
|
|
boolean applyCRLFEncoding)
|
2022-03-24 14:16:46 +01:00
|
|
|
throws PGPException, IOException {
|
|
|
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
|
|
|
|
2022-03-31 21:56:24 +02:00
|
|
|
ProducerOptions options = ProducerOptions
|
|
|
|
.signAndEncrypt(
|
|
|
|
EncryptionOptions.encryptCommunications()
|
|
|
|
.addRecipient(publicKeys),
|
|
|
|
SigningOptions.get()
|
|
|
|
.addInlineSignature(SecretKeyRingProtector.unprotectedKeys(), secretKeys, sigType)
|
|
|
|
)
|
|
|
|
.setEncoding(dataFormat);
|
|
|
|
if (applyCRLFEncoding) {
|
|
|
|
options.applyCRLFEncoding();
|
|
|
|
}
|
|
|
|
|
2022-03-24 14:16:46 +01:00
|
|
|
EncryptionStream encryptionStream = PGPainless.encryptAndOrSign()
|
|
|
|
.onOutputStream(out)
|
2022-03-31 21:56:24 +02:00
|
|
|
.withOptions(options);
|
2022-03-24 14:16:46 +01:00
|
|
|
|
|
|
|
ByteArrayInputStream inputStream = new ByteArrayInputStream(message.getBytes(StandardCharsets.UTF_8));
|
|
|
|
Streams.pipeAll(inputStream, encryptionStream);
|
|
|
|
encryptionStream.close();
|
|
|
|
|
|
|
|
String msg = out.toString();
|
|
|
|
return msg;
|
|
|
|
}
|
|
|
|
|
|
|
|
private OpenPgpMetadata decryptAndVerify(String msg) throws PGPException, IOException {
|
|
|
|
ByteArrayInputStream in = new ByteArrayInputStream(msg.getBytes(StandardCharsets.UTF_8));
|
|
|
|
DecryptionStream decryptionStream = PGPainless.decryptAndOrVerify()
|
|
|
|
.onInputStream(in)
|
|
|
|
.withOptions(new ConsumerOptions()
|
|
|
|
.addDecryptionKey(secretKeys, SecretKeyRingProtector.unprotectedKeys())
|
|
|
|
.addVerificationCert(publicKeys));
|
|
|
|
|
|
|
|
Streams.drain(decryptionStream);
|
|
|
|
decryptionStream.close();
|
|
|
|
|
|
|
|
return decryptionStream.getResult();
|
|
|
|
}
|
2022-03-30 16:13:08 +02:00
|
|
|
|
|
|
|
@Test
|
|
|
|
public void testManualSignWithAllCombinations() throws PGPException, IOException {
|
|
|
|
for (StreamEncoding streamEncoding : StreamEncoding.values()) {
|
|
|
|
for (DocumentSignatureType sigType : DocumentSignatureType.values()) {
|
|
|
|
manualSignAndVerify(sigType, streamEncoding);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public void manualSignAndVerify(DocumentSignatureType sigType, StreamEncoding streamEncoding)
|
|
|
|
throws IOException, PGPException {
|
|
|
|
PGPPrivateKey privateKey = UnlockSecretKey.unlockSecretKey(secretKeys.getSecretKey(), SecretKeyRingProtector.unprotectedKeys());
|
|
|
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
|
|
|
ArmoredOutputStream armorOut = new ArmoredOutputStream(out);
|
|
|
|
|
|
|
|
PGPCompressedDataGenerator compressor = new PGPCompressedDataGenerator(CompressionAlgorithmTags.ZLIB);
|
|
|
|
OutputStream compressedOut = compressor.open(armorOut);
|
|
|
|
|
|
|
|
PGPSignatureGenerator signer = new PGPSignatureGenerator(
|
|
|
|
new BcPGPContentSignerBuilder(
|
|
|
|
secretKeys.getPublicKey().getAlgorithm(),
|
|
|
|
HashAlgorithm.SHA256.getAlgorithmId()));
|
|
|
|
signer.init(sigType.getSignatureType().getCode(), privateKey);
|
|
|
|
|
|
|
|
PGPOnePassSignature ops = signer.generateOnePassVersion(false);
|
|
|
|
ops.encode(compressedOut);
|
|
|
|
|
|
|
|
PGPLiteralDataGenerator author = new PGPLiteralDataGenerator();
|
|
|
|
OutputStream literalOut = author.open(compressedOut, streamEncoding.getCode(), "", PGPLiteralData.NOW, new byte[4096]);
|
|
|
|
|
|
|
|
byte[] msg = message.getBytes(StandardCharsets.UTF_8);
|
|
|
|
|
|
|
|
ByteArrayOutputStream crlfed = new ByteArrayOutputStream();
|
|
|
|
CRLFGeneratorStream crlfOut = new CRLFGeneratorStream(crlfed, streamEncoding);
|
|
|
|
crlfOut.write(msg);
|
|
|
|
msg = crlfed.toByteArray();
|
|
|
|
|
|
|
|
for (byte b : msg) {
|
|
|
|
literalOut.write(b);
|
|
|
|
signer.update(b);
|
|
|
|
}
|
|
|
|
|
|
|
|
literalOut.close();
|
|
|
|
PGPSignature signature = signer.generate();
|
|
|
|
|
|
|
|
signature.encode(compressedOut);
|
|
|
|
compressor.close();
|
|
|
|
|
|
|
|
armorOut.close();
|
|
|
|
|
|
|
|
String ciphertext = out.toString();
|
|
|
|
// CHECKSTYLE:OFF
|
|
|
|
System.out.println(sigType + " " + streamEncoding);
|
|
|
|
System.out.println(ciphertext);
|
|
|
|
// CHECKSTYLE:ON
|
|
|
|
|
|
|
|
ByteArrayInputStream cipherIn = new ByteArrayInputStream(ciphertext.getBytes(StandardCharsets.UTF_8));
|
|
|
|
ByteArrayOutputStream decrypted = new ByteArrayOutputStream();
|
|
|
|
DecryptionStream decryptionStream = PGPainless.decryptAndOrVerify()
|
|
|
|
.onInputStream(cipherIn)
|
|
|
|
.withOptions(new ConsumerOptions()
|
|
|
|
.addVerificationCert(publicKeys));
|
|
|
|
|
|
|
|
Streams.pipeAll(decryptionStream, decrypted);
|
|
|
|
decryptionStream.close();
|
|
|
|
OpenPgpMetadata metadata = decryptionStream.getResult();
|
|
|
|
assertTrue(metadata.isVerified(), "Not verified! Sig Type: " + sigType + " StreamEncoding: " + streamEncoding);
|
|
|
|
|
|
|
|
assertArrayEquals(msg, decrypted.toByteArray());
|
|
|
|
}
|
2022-03-24 14:16:46 +01:00
|
|
|
}
|