2021-10-07 15:48:52 +02:00
|
|
|
// SPDX-FileCopyrightText: 2021 Paul Schaub <vanitasvitae@fsfe.org>
|
|
|
|
//
|
|
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
|
2021-06-10 14:25:00 +02:00
|
|
|
package org.pgpainless.encryption_signing;
|
|
|
|
|
|
|
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
|
|
|
import static org.junit.jupiter.api.Assertions.assertNull;
|
|
|
|
import static org.junit.jupiter.api.Assertions.assertThrows;
|
2021-06-10 15:04:21 +02:00
|
|
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
2021-06-10 14:25:00 +02:00
|
|
|
|
2021-06-10 15:04:21 +02:00
|
|
|
import java.security.InvalidAlgorithmParameterException;
|
|
|
|
import java.security.NoSuchAlgorithmException;
|
2023-09-03 17:55:46 +02:00
|
|
|
import java.util.ArrayList;
|
2021-06-10 15:04:21 +02:00
|
|
|
import java.util.Arrays;
|
|
|
|
import java.util.Collections;
|
|
|
|
import java.util.Iterator;
|
|
|
|
import java.util.List;
|
|
|
|
import java.util.Set;
|
|
|
|
|
|
|
|
import org.bouncycastle.openpgp.PGPException;
|
|
|
|
import org.bouncycastle.openpgp.PGPPublicKey;
|
|
|
|
import org.bouncycastle.openpgp.PGPPublicKeyRing;
|
|
|
|
import org.bouncycastle.openpgp.PGPPublicKeyRingCollection;
|
|
|
|
import org.bouncycastle.openpgp.PGPSecretKeyRing;
|
2023-09-03 17:55:46 +02:00
|
|
|
import org.jetbrains.annotations.NotNull;
|
2021-06-10 15:04:21 +02:00
|
|
|
import org.junit.jupiter.api.BeforeAll;
|
2021-06-10 14:25:00 +02:00
|
|
|
import org.junit.jupiter.api.Test;
|
2021-06-10 15:04:21 +02:00
|
|
|
import org.pgpainless.PGPainless;
|
|
|
|
import org.pgpainless.algorithm.KeyFlag;
|
2021-06-10 14:25:00 +02:00
|
|
|
import org.pgpainless.algorithm.SymmetricKeyAlgorithm;
|
2022-03-15 14:04:59 +01:00
|
|
|
import org.pgpainless.exception.KeyException;
|
2021-06-10 15:04:21 +02:00
|
|
|
import org.pgpainless.key.SubkeyIdentifier;
|
|
|
|
import org.pgpainless.key.generation.KeySpec;
|
|
|
|
import org.pgpainless.key.generation.type.KeyType;
|
2024-02-21 14:57:02 +01:00
|
|
|
import org.pgpainless.key.generation.type.eddsa_legacy.EdDSALegacyCurve;
|
2021-06-10 15:04:21 +02:00
|
|
|
import org.pgpainless.key.generation.type.xdh.XDHSpec;
|
|
|
|
import org.pgpainless.key.util.KeyRingUtils;
|
|
|
|
import org.pgpainless.util.Passphrase;
|
2021-06-10 14:25:00 +02:00
|
|
|
|
2023-05-03 14:38:52 +02:00
|
|
|
import javax.annotation.Nonnull;
|
|
|
|
|
2021-06-10 14:25:00 +02:00
|
|
|
public class EncryptionOptionsTest {
|
|
|
|
|
2021-06-10 15:04:21 +02:00
|
|
|
private static PGPSecretKeyRing secretKeys;
|
|
|
|
private static PGPPublicKeyRing publicKeys;
|
|
|
|
private static SubkeyIdentifier primaryKey;
|
|
|
|
private static SubkeyIdentifier encryptComms;
|
|
|
|
private static SubkeyIdentifier encryptStorage;
|
|
|
|
|
|
|
|
@BeforeAll
|
|
|
|
public static void generateKey() throws PGPException, InvalidAlgorithmParameterException, NoSuchAlgorithmException {
|
2021-11-02 12:23:05 +01:00
|
|
|
secretKeys = PGPainless.buildKeyRing()
|
2024-02-21 14:57:02 +01:00
|
|
|
.setPrimaryKey(KeySpec.getBuilder(KeyType.EDDSA_LEGACY(EdDSALegacyCurve._Ed25519), KeyFlag.CERTIFY_OTHER)
|
2021-09-13 19:20:19 +02:00
|
|
|
.build())
|
2021-09-20 12:30:03 +02:00
|
|
|
.addSubkey(KeySpec.getBuilder(KeyType.XDH(XDHSpec._X25519), KeyFlag.ENCRYPT_COMMS)
|
2021-09-13 19:20:19 +02:00
|
|
|
.build())
|
2021-09-20 12:30:03 +02:00
|
|
|
.addSubkey(KeySpec.getBuilder(KeyType.XDH(XDHSpec._X25519), KeyFlag.ENCRYPT_STORAGE)
|
2021-09-13 19:20:19 +02:00
|
|
|
.build())
|
2021-09-20 12:30:03 +02:00
|
|
|
.addUserId("test@pgpainless.org")
|
2021-06-10 15:04:21 +02:00
|
|
|
.build();
|
|
|
|
|
|
|
|
publicKeys = KeyRingUtils.publicKeyRingFrom(secretKeys);
|
|
|
|
|
|
|
|
Iterator<PGPPublicKey> iterator = publicKeys.iterator();
|
|
|
|
primaryKey = new SubkeyIdentifier(publicKeys, iterator.next().getKeyID());
|
|
|
|
encryptComms = new SubkeyIdentifier(publicKeys, iterator.next().getKeyID());
|
|
|
|
encryptStorage = new SubkeyIdentifier(publicKeys, iterator.next().getKeyID());
|
|
|
|
}
|
|
|
|
|
2021-06-10 14:25:00 +02:00
|
|
|
@Test
|
|
|
|
public void testOverrideEncryptionAlgorithmFailsForNULL() {
|
|
|
|
EncryptionOptions options = new EncryptionOptions();
|
|
|
|
assertNull(options.getEncryptionAlgorithmOverride());
|
|
|
|
|
|
|
|
assertThrows(IllegalArgumentException.class, () -> options.overrideEncryptionAlgorithm(SymmetricKeyAlgorithm.NULL));
|
|
|
|
|
|
|
|
assertNull(options.getEncryptionAlgorithmOverride());
|
|
|
|
}
|
|
|
|
|
|
|
|
@Test
|
|
|
|
public void testOverrideEncryptionOptions() {
|
|
|
|
EncryptionOptions options = new EncryptionOptions();
|
|
|
|
assertNull(options.getEncryptionAlgorithmOverride());
|
|
|
|
options.overrideEncryptionAlgorithm(SymmetricKeyAlgorithm.AES_128);
|
|
|
|
|
|
|
|
assertEquals(SymmetricKeyAlgorithm.AES_128, options.getEncryptionAlgorithmOverride());
|
|
|
|
}
|
2021-06-10 15:04:21 +02:00
|
|
|
|
|
|
|
@Test
|
|
|
|
public void testAddRecipients_EncryptCommunications() {
|
|
|
|
EncryptionOptions options = EncryptionOptions.encryptCommunications();
|
|
|
|
options.addRecipient(publicKeys);
|
|
|
|
|
|
|
|
Set<SubkeyIdentifier> encryptionKeys = options.getEncryptionKeyIdentifiers();
|
|
|
|
assertEquals(1, encryptionKeys.size());
|
|
|
|
assertEquals(encryptComms, encryptionKeys.iterator().next());
|
|
|
|
}
|
|
|
|
|
|
|
|
@Test
|
|
|
|
public void testAddRecipients_EncryptDataAtRest() {
|
|
|
|
EncryptionOptions options = EncryptionOptions.encryptDataAtRest();
|
|
|
|
options.addRecipient(publicKeys);
|
|
|
|
|
|
|
|
Set<SubkeyIdentifier> encryptionKeys = options.getEncryptionKeyIdentifiers();
|
|
|
|
assertEquals(1, encryptionKeys.size());
|
|
|
|
assertEquals(encryptStorage, encryptionKeys.iterator().next());
|
|
|
|
}
|
|
|
|
|
|
|
|
@Test
|
|
|
|
public void testAddRecipients_AllKeys() {
|
|
|
|
EncryptionOptions options = new EncryptionOptions();
|
|
|
|
options.addRecipient(publicKeys, EncryptionOptions.encryptToAllCapableSubkeys());
|
|
|
|
|
|
|
|
Set<SubkeyIdentifier> encryptionKeys = options.getEncryptionKeyIdentifiers();
|
|
|
|
|
|
|
|
assertEquals(2, encryptionKeys.size());
|
|
|
|
assertTrue(encryptionKeys.contains(encryptComms));
|
|
|
|
assertTrue(encryptionKeys.contains(encryptStorage));
|
|
|
|
}
|
|
|
|
|
2022-04-29 22:49:45 +02:00
|
|
|
@Test
|
|
|
|
public void testAddEmptyRecipientsFails() {
|
|
|
|
EncryptionOptions options = new EncryptionOptions();
|
|
|
|
assertThrows(IllegalArgumentException.class, () -> options.addRecipients(Collections.emptyList()));
|
|
|
|
assertThrows(IllegalArgumentException.class, () -> options.addRecipients(Collections.emptyList(),
|
2023-09-03 17:55:46 +02:00
|
|
|
ArrayList::new));
|
2022-04-29 22:49:45 +02:00
|
|
|
}
|
|
|
|
|
2021-06-10 15:04:21 +02:00
|
|
|
@Test
|
|
|
|
public void testAddEmptyPassphraseFails() {
|
|
|
|
EncryptionOptions options = new EncryptionOptions();
|
|
|
|
assertThrows(IllegalArgumentException.class, () ->
|
|
|
|
options.addPassphrase(Passphrase.emptyPassphrase()));
|
|
|
|
}
|
|
|
|
|
|
|
|
@Test
|
|
|
|
public void testAddRecipient_KeyWithoutEncryptionKeyFails() throws PGPException, InvalidAlgorithmParameterException, NoSuchAlgorithmException {
|
|
|
|
EncryptionOptions options = new EncryptionOptions();
|
2021-11-02 12:23:05 +01:00
|
|
|
PGPSecretKeyRing secretKeys = PGPainless.buildKeyRing()
|
2024-02-21 14:57:02 +01:00
|
|
|
.setPrimaryKey(KeySpec.getBuilder(KeyType.EDDSA_LEGACY(EdDSALegacyCurve._Ed25519), KeyFlag.CERTIFY_OTHER, KeyFlag.SIGN_DATA))
|
2021-09-20 12:30:03 +02:00
|
|
|
.addUserId("test@pgpainless.org")
|
|
|
|
.build();
|
2021-06-10 15:04:21 +02:00
|
|
|
PGPPublicKeyRing publicKeys = KeyRingUtils.publicKeyRingFrom(secretKeys);
|
|
|
|
|
2022-03-15 14:04:59 +01:00
|
|
|
assertThrows(KeyException.UnacceptableEncryptionKeyException.class, () -> options.addRecipient(publicKeys));
|
2021-06-10 15:04:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
@Test
|
|
|
|
public void testEncryptionKeySelectionStrategyEmpty_ThrowsAssertionError() {
|
|
|
|
EncryptionOptions options = new EncryptionOptions();
|
|
|
|
|
2022-03-15 14:04:59 +01:00
|
|
|
assertThrows(KeyException.UnacceptableEncryptionKeyException.class,
|
2021-06-10 15:04:21 +02:00
|
|
|
() -> options.addRecipient(publicKeys, new EncryptionOptions.EncryptionKeySelector() {
|
2023-09-03 17:55:46 +02:00
|
|
|
@NotNull
|
2021-06-10 15:04:21 +02:00
|
|
|
@Override
|
2023-09-03 17:55:46 +02:00
|
|
|
public List<PGPPublicKey> selectEncryptionSubkeys(@NotNull List<? extends PGPPublicKey> encryptionCapableKeys) {
|
2021-06-10 15:04:21 +02:00
|
|
|
return Collections.emptyList();
|
|
|
|
}
|
|
|
|
}));
|
|
|
|
|
2022-03-15 14:04:59 +01:00
|
|
|
assertThrows(KeyException.UnacceptableEncryptionKeyException.class,
|
2021-06-10 15:04:21 +02:00
|
|
|
() -> options.addRecipient(publicKeys, "test@pgpainless.org", new EncryptionOptions.EncryptionKeySelector() {
|
|
|
|
@Override
|
2023-09-03 17:55:46 +02:00
|
|
|
public List<PGPPublicKey> selectEncryptionSubkeys(@Nonnull List<? extends PGPPublicKey> encryptionCapableKeys) {
|
2021-06-10 15:04:21 +02:00
|
|
|
return Collections.emptyList();
|
|
|
|
}
|
|
|
|
}));
|
|
|
|
}
|
|
|
|
|
|
|
|
@Test
|
2022-09-29 13:02:22 +02:00
|
|
|
public void testAddRecipients_PGPPublicKeyRingCollection() throws PGPException, InvalidAlgorithmParameterException, NoSuchAlgorithmException {
|
2021-06-10 15:04:21 +02:00
|
|
|
PGPPublicKeyRing secondKeyRing = KeyRingUtils.publicKeyRingFrom(
|
2022-06-09 00:42:06 +02:00
|
|
|
PGPainless.generateKeyRing().modernKeyRing("other@pgpainless.org"));
|
2021-06-10 15:04:21 +02:00
|
|
|
|
|
|
|
PGPPublicKeyRingCollection collection = new PGPPublicKeyRingCollection(
|
|
|
|
Arrays.asList(publicKeys, secondKeyRing));
|
|
|
|
|
|
|
|
EncryptionOptions options = new EncryptionOptions();
|
2021-08-04 16:38:17 +02:00
|
|
|
options.addRecipients(collection, EncryptionOptions.encryptToFirstSubkey());
|
2021-06-10 15:04:21 +02:00
|
|
|
assertEquals(2, options.getEncryptionKeyIdentifiers().size());
|
|
|
|
}
|
2021-06-10 15:18:31 +02:00
|
|
|
|
|
|
|
@Test
|
|
|
|
public void testAddRecipient_withValidUserId() {
|
|
|
|
EncryptionOptions options = new EncryptionOptions();
|
2021-08-04 16:38:17 +02:00
|
|
|
options.addRecipient(publicKeys, "test@pgpainless.org", EncryptionOptions.encryptToFirstSubkey());
|
2021-06-10 15:18:31 +02:00
|
|
|
|
|
|
|
assertEquals(1, options.getEncryptionMethods().size());
|
|
|
|
}
|
|
|
|
|
|
|
|
@Test
|
|
|
|
public void testAddRecipient_withInvalidUserId() {
|
|
|
|
EncryptionOptions options = new EncryptionOptions();
|
2022-03-15 14:04:59 +01:00
|
|
|
assertThrows(KeyException.UnboundUserIdException.class, () -> options.addRecipient(publicKeys, "invalid@user.id"));
|
2021-06-10 15:18:31 +02:00
|
|
|
}
|
2021-06-10 14:25:00 +02:00
|
|
|
}
|