1
0
Fork 0
mirror of https://github.com/pgpainless/pgpainless.git synced 2025-09-14 12:49:39 +02:00

Reworking encryption/decryption API.

This commit is contained in:
Paul Schaub 2021-05-06 00:04:03 +02:00
parent 7e2c89b1b3
commit 89a0adddd8
29 changed files with 1454 additions and 631 deletions

View file

@ -17,18 +17,23 @@ package org.bouncycastle;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.security.InvalidAlgorithmParameterException;
import java.security.NoSuchAlgorithmException;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import org.bouncycastle.openpgp.PGPException;
import org.bouncycastle.openpgp.PGPPublicKey;
import org.bouncycastle.openpgp.PGPPublicKeyRing;
import org.bouncycastle.openpgp.PGPSecretKeyRing;
import org.bouncycastle.openpgp.PGPSignature;
import org.junit.jupiter.api.Test;
import org.pgpainless.PGPainless;
import org.pgpainless.key.util.KeyRingUtils;
import org.pgpainless.util.CollectionUtils;
public class PGPPublicKeyRingTest {
@ -57,4 +62,21 @@ public class PGPPublicKeyRingTest {
}
}
}
@Test
public void removeUserIdTest() throws PGPException, InvalidAlgorithmParameterException, NoSuchAlgorithmException {
String userId = "alice@wonderland.lit";
PGPSecretKeyRing secretKeyRing = PGPainless.generateKeyRing().simpleEcKeyRing(userId);
PGPPublicKeyRing publicKeys = KeyRingUtils.publicKeyRingFrom(secretKeyRing);
List<String> userIds = CollectionUtils.iteratorToList(publicKeys.getPublicKey().getUserIDs());
assertTrue(userIds.contains(userId));
PGPPublicKey publicKey = publicKeys.getPublicKey();
PGPSignature cert = publicKey.getSignaturesForID(userId).next();
publicKey = PGPPublicKey.removeCertification(publicKey, cert);
userIds = CollectionUtils.iteratorToList(publicKey.getUserIDs());
assertFalse(userIds.contains(userId));
}
}

View file

@ -41,12 +41,13 @@ import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;
import org.pgpainless.PGPainless;
import org.pgpainless.algorithm.DocumentSignatureType;
import org.pgpainless.algorithm.KeyFlag;
import org.pgpainless.algorithm.SymmetricKeyAlgorithm;
import org.pgpainless.decryption_verification.DecryptionStream;
import org.pgpainless.decryption_verification.OpenPgpMetadata;
import org.pgpainless.implementation.ImplementationFactory;
import org.pgpainless.key.OpenPgpV4Fingerprint;
import org.pgpainless.key.SubkeyIdentifier;
import org.pgpainless.key.TestKeys;
import org.pgpainless.key.generation.KeySpec;
import org.pgpainless.key.generation.type.KeyType;
@ -155,26 +156,20 @@ public class EncryptDecryptTest {
EncryptionStream encryptor = PGPainless.encryptAndOrSign()
.onOutputStream(envelope)
.toRecipients(recipientPub)
.usingSecureAlgorithms()
.signWith(keyDecryptor, senderSec)
.signBinaryDocument()
.toRecipient(recipientPub)
.and()
.signInlineWith(keyDecryptor, senderSec, null, DocumentSignatureType.BINARY_DOCUMENT)
.noArmor();
Streams.pipeAll(new ByteArrayInputStream(secretMessage), encryptor);
encryptor.close();
byte[] encryptedSecretMessage = envelope.toByteArray();
OpenPgpMetadata encryptionResult = encryptor.getResult();
EncryptionResult encryptionResult = encryptor.getResult();
assertFalse(encryptionResult.getSignatures().isEmpty());
for (OpenPgpV4Fingerprint fingerprint : encryptionResult.getVerifiedSignatures().keySet()) {
assertTrue(BCUtil.keyRingContainsKeyWithId(senderPub, fingerprint.getKeyId()));
}
assertFalse(encryptionResult.getRecipientKeyIds().isEmpty());
for (long keyId : encryptionResult.getRecipientKeyIds()) {
assertTrue(BCUtil.keyRingContainsKeyWithId(recipientPub, keyId));
assertFalse(encryptionResult.getRecipients().isEmpty());
for (SubkeyIdentifier encryptionKey : encryptionResult.getRecipients()) {
assertTrue(BCUtil.keyRingContainsKeyWithId(recipientPub, encryptionKey.getKeyId()));
}
assertEquals(SymmetricKeyAlgorithm.AES_256, encryptionResult.getSymmetricKeyAlgorithm());
@ -214,15 +209,14 @@ public class EncryptDecryptTest {
ByteArrayOutputStream dummyOut = new ByteArrayOutputStream();
EncryptionStream signer = PGPainless.encryptAndOrSign().onOutputStream(dummyOut)
.doNotEncrypt()
.createDetachedSignature()
.signWith(keyRingProtector, signingKeys)
.signBinaryDocument()
.signDetachedWith(keyRingProtector, signingKeys)
.noArmor();
Streams.pipeAll(inputStream, signer);
signer.close();
OpenPgpMetadata metadata = signer.getResult();
Set<PGPSignature> signatureSet = metadata.getSignatures();
EncryptionResult metadata = signer.getResult();
Set<PGPSignature> signatureSet = metadata.getDetachedSignatures().get(metadata.getDetachedSignatures().keySet().iterator().next());
ByteArrayOutputStream sigOut = new ByteArrayOutputStream();
ArmoredOutputStream armorOut = ArmoredOutputStreamFactory.get(sigOut);
signatureSet.iterator().next().encode(armorOut);
@ -244,8 +238,8 @@ public class EncryptDecryptTest {
Streams.pipeAll(verifier, dummyOut);
verifier.close();
metadata = verifier.getResult();
assertFalse(metadata.getVerifiedSignatures().isEmpty());
OpenPgpMetadata decryptionResult = verifier.getResult();
assertFalse(decryptionResult.getVerifiedSignatures().isEmpty());
}
@ParameterizedTest
@ -259,8 +253,7 @@ public class EncryptDecryptTest {
ByteArrayOutputStream signOut = new ByteArrayOutputStream();
EncryptionStream signer = PGPainless.encryptAndOrSign().onOutputStream(signOut)
.doNotEncrypt()
.signWith(keyRingProtector, signingKeys)
.signBinaryDocument()
.signInlineWith(keyRingProtector, signingKeys)
.asciiArmor();
Streams.pipeAll(inputStream, signer);
signer.close();
@ -344,6 +337,6 @@ public class EncryptDecryptTest {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
assertThrows(IllegalArgumentException.class, () ->
PGPainless.encryptAndOrSign().onOutputStream(outputStream)
.toRecipients(publicKeys));
.toRecipient(publicKeys));
}
}

View file

@ -37,8 +37,8 @@ public class EncryptionStreamClosedTest {
OutputStream out = new ByteArrayOutputStream();
EncryptionStream stream = PGPainless.encryptAndOrSign()
.onOutputStream(out)
.forPassphrases(Passphrase.fromPassword("dummy"))
.usingSecureAlgorithms()
.forPassphrase(Passphrase.fromPassword("dummy"))
.and()
.doNotSign()
.asciiArmor();

View file

@ -69,8 +69,8 @@ public class FileInfoTest {
ByteArrayOutputStream dataOut = new ByteArrayOutputStream();
EncryptionStream encryptionStream = PGPainless.encryptAndOrSign()
.onOutputStream(dataOut, fileInfo)
.toRecipients(publicKeys)
.usingSecureAlgorithms()
.toRecipient(publicKeys)
.and()
.doNotSign()
.noArmor();

View file

@ -31,6 +31,7 @@ import org.bouncycastle.openpgp.PGPPublicKeyRing;
import org.bouncycastle.openpgp.PGPSecretKeyRing;
import org.bouncycastle.util.io.Streams;
import org.pgpainless.PGPainless;
import org.pgpainless.algorithm.DocumentSignatureType;
import org.pgpainless.key.TestKeys;
import org.pgpainless.key.generation.type.rsa.RsaLength;
import org.pgpainless.key.protection.SecretKeyRingProtector;
@ -111,11 +112,9 @@ public class LengthTest {
OutputStream encryptor = PGPainless.encryptAndOrSign()
.onOutputStream(envelope)
.toRecipients(recipientPub)
// .doNotEncrypt()
.usingSecureAlgorithms()
.signWith(keyDecryptor, senderSec)
.signBinaryDocument()
.toRecipient(recipientPub)
.and()
.signInlineWith(keyDecryptor, senderSec, "simplejid@server.tld", DocumentSignatureType.BINARY_DOCUMENT)
.noArmor();
Streams.pipeAll(new ByteArrayInputStream(secretMessage), encryptor);

View file

@ -37,7 +37,7 @@ import org.bouncycastle.util.io.Streams;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;
import org.pgpainless.PGPainless;
import org.pgpainless.algorithm.CompressionAlgorithm;
import org.pgpainless.algorithm.DocumentSignatureType;
import org.pgpainless.algorithm.HashAlgorithm;
import org.pgpainless.algorithm.SymmetricKeyAlgorithm;
import org.pgpainless.decryption_verification.DecryptionStream;
@ -70,10 +70,11 @@ public class SigningTest {
EncryptionStream encryptionStream = PGPainless.encryptAndOrSign(EncryptionStream.Purpose.STORAGE)
.onOutputStream(out)
.toRecipients(keys)
.andToSelf(KeyRingUtils.publicKeyRingFrom(cryptieKeys))
.usingAlgorithms(SymmetricKeyAlgorithm.AES_192, HashAlgorithm.SHA384, CompressionAlgorithm.ZIP)
.signWith(SecretKeyRingProtector.unlockSingleKeyWith(TestKeys.CRYPTIE_PASSPHRASE, cryptieSigningKey), cryptieKeys)
.signCanonicalText()
.and()
.toRecipient(KeyRingUtils.publicKeyRingFrom(cryptieKeys))
.and()
.signInlineWith(SecretKeyRingProtector.unlockSingleKeyWith(TestKeys.CRYPTIE_PASSPHRASE, cryptieSigningKey),
cryptieKeys, TestKeys.CRYPTIE_UID, DocumentSignatureType.CANONICAL_TEXT_DOCUMENT)
.asciiArmor();
byte[] messageBytes = "This message is signed and encrypted to Romeo and Juliet.".getBytes(StandardCharsets.UTF_8);

View file

@ -193,8 +193,7 @@ public class ChangeSecretKeyRingPassphraseTest {
ByteArrayOutputStream dummy = new ByteArrayOutputStream();
EncryptionStream stream = PGPainless.encryptAndOrSign().onOutputStream(dummy)
.doNotEncrypt()
.signWith(PasswordBasedSecretKeyRingProtector.forKey(keyRing, passphrase), keyRing)
.signBinaryDocument()
.signInlineWith(PasswordBasedSecretKeyRingProtector.forKey(keyRing, passphrase), keyRing)
.noArmor();
Streams.pipeAll(new ByteArrayInputStream(dummyMessage.getBytes()), stream);

View file

@ -36,7 +36,7 @@ public class MultiPassphraseSymmetricEncryptionTest {
@ParameterizedTest
@MethodSource("org.pgpainless.util.TestUtil#provideImplementationFactories")
@Disabled
public void test(ImplementationFactory implementationFactory) throws IOException, PGPException {
public void encryptDecryptWithMultiplePassphrases(ImplementationFactory implementationFactory) throws IOException, PGPException {
ImplementationFactory.setFactoryImplementation(implementationFactory);
String message = "Here we test if during decryption of a message that was encrypted with two passphrases, " +
"the decryptor finds the session key encrypted for the right passphrase.";
@ -44,8 +44,10 @@ public class MultiPassphraseSymmetricEncryptionTest {
ByteArrayOutputStream ciphertextOut = new ByteArrayOutputStream();
EncryptionStream encryptor = PGPainless.encryptAndOrSign()
.onOutputStream(ciphertextOut)
.forPassphrases(Passphrase.fromPassword("p1"), Passphrase.fromPassword("p2"))
.usingSecureAlgorithms()
.forPassphrase(Passphrase.fromPassword("p1"))
.and()
.forPassphrase(Passphrase.fromPassword("p2"))
.and()
.doNotSign()
.noArmor();

View file

@ -30,6 +30,7 @@ import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;
import org.pgpainless.PGPainless;
import org.pgpainless.decryption_verification.DecryptionStream;
import org.pgpainless.encryption_signing.EncryptionBuilderInterface;
import org.pgpainless.encryption_signing.EncryptionStream;
import org.pgpainless.implementation.ImplementationFactory;
import org.pgpainless.key.TestKeys;
@ -46,7 +47,7 @@ public class SymmetricEncryptionTest {
@ParameterizedTest
@MethodSource("org.pgpainless.util.TestUtil#provideImplementationFactories")
public void test(ImplementationFactory implementationFactory) throws IOException, PGPException {
public void encryptWithKeyAndPassphrase_DecryptWithKey(ImplementationFactory implementationFactory) throws IOException, PGPException {
ImplementationFactory.setFactoryImplementation(implementationFactory);
byte[] plaintext = "This is a secret message".getBytes(StandardCharsets.UTF_8);
ByteArrayInputStream plaintextIn = new ByteArrayInputStream(plaintext);
@ -54,12 +55,13 @@ public class SymmetricEncryptionTest {
Passphrase encryptionPassphrase = Passphrase.fromPassword("greenBeans");
ByteArrayOutputStream ciphertextOut = new ByteArrayOutputStream();
EncryptionStream encryptor = PGPainless.encryptAndOrSign().onOutputStream(ciphertextOut)
.forPassphrases(encryptionPassphrase)
EncryptionBuilderInterface.Armor armor = PGPainless.encryptAndOrSign().onOutputStream(ciphertextOut)
.forPassphrase(encryptionPassphrase)
.and()
.toRecipients(encryptionKey)
.usingSecureAlgorithms()
.doNotSign()
.toRecipient(encryptionKey)
.and()
.doNotSign();
EncryptionStream encryptor = armor
.noArmor();
Streams.pipeAll(plaintextIn, encryptor);

View file

@ -56,6 +56,6 @@ public class TestEncryptCommsStorageFlagsDifferentiated {
.onOutputStream(out);
// since the key does not carry the flag ENCRYPT_COMMS, it cannot be used by the stream.
assertThrows(IllegalArgumentException.class, () -> builder.toRecipients(publicKeys));
assertThrows(IllegalArgumentException.class, () -> builder.toRecipient(publicKeys));
}
}

View file

@ -28,7 +28,7 @@ import org.bouncycastle.openpgp.PGPSecretKeyRing;
import org.bouncycastle.util.io.Streams;
import org.junit.jupiter.api.Test;
import org.pgpainless.PGPainless;
import org.pgpainless.decryption_verification.OpenPgpMetadata;
import org.pgpainless.encryption_signing.EncryptionResult;
import org.pgpainless.encryption_signing.EncryptionStream;
import org.pgpainless.key.WeirdKeys;
import org.pgpainless.key.util.KeyRingUtils;
@ -57,16 +57,16 @@ public class TestTwoSubkeysEncryption {
ByteArrayOutputStream out = new ByteArrayOutputStream();
EncryptionStream encryptionStream = PGPainless.encryptAndOrSign(EncryptionStream.Purpose.STORAGE)
.onOutputStream(out)
.toRecipients(publicKeys)
.usingSecureAlgorithms()
.toRecipient(publicKeys)
.and()
.doNotSign()
.noArmor();
Streams.pipeAll(getPlainIn(), encryptionStream);
encryptionStream.close();
OpenPgpMetadata metadata = encryptionStream.getResult();
EncryptionResult metadata = encryptionStream.getResult();
assertEquals(2, metadata.getRecipientKeyIds().size());
assertEquals(2, metadata.getRecipients().size());
}
}