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:
parent
7e2c89b1b3
commit
89a0adddd8
29 changed files with 1454 additions and 631 deletions
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue