1
0
Fork 0
mirror of https://github.com/pgpainless/pgpainless.git synced 2024-11-23 04:42:06 +01:00

Simplify KeySpecBuilder

This commit is contained in:
Paul Schaub 2021-09-13 19:20:19 +02:00
parent 5683ee205e
commit 21f424551b
23 changed files with 240 additions and 336 deletions

View file

@ -384,7 +384,7 @@ public final class DecryptionStreamFactory {
} }
private void throwIfAlgorithmIsRejected(SymmetricKeyAlgorithm algorithm) throws UnacceptableAlgorithmException { private void throwIfAlgorithmIsRejected(SymmetricKeyAlgorithm algorithm) throws UnacceptableAlgorithmException {
if (!PGPainless.getPolicy().getSymmetricKeyDecryptionAlgoritmPolicy().isAcceptable(algorithm)) { if (!PGPainless.getPolicy().getSymmetricKeyDecryptionAlgorithmPolicy().isAcceptable(algorithm)) {
throw new UnacceptableAlgorithmException("Data is " throw new UnacceptableAlgorithmException("Data is "
+ (algorithm == SymmetricKeyAlgorithm.NULL ? "unencrypted" : "encrypted with symmetric algorithm " + algorithm) + " which is not acceptable as per PGPainless' policy.\n" + + (algorithm == SymmetricKeyAlgorithm.NULL ? "unencrypted" : "encrypted with symmetric algorithm " + algorithm) + " which is not acceptable as per PGPainless' policy.\n" +
"To mark this algorithm as acceptable, use PGPainless.getPolicy().setSymmetricKeyDecryptionAlgorithmPolicy()."); "To mark this algorithm as acceptable, use PGPainless.getPolicy().setSymmetricKeyDecryptionAlgorithmPolicy().");

View file

@ -127,10 +127,9 @@ public class KeyRingBuilder implements KeyRingBuilderInterface {
public PGPSecretKeyRing simpleRsaKeyRing(@Nonnull String userId, @Nonnull RsaLength length, String password) public PGPSecretKeyRing simpleRsaKeyRing(@Nonnull String userId, @Nonnull RsaLength length, String password)
throws PGPException, NoSuchAlgorithmException, InvalidAlgorithmParameterException { throws PGPException, NoSuchAlgorithmException, InvalidAlgorithmParameterException {
WithAdditionalUserIdOrPassphrase builder = this WithAdditionalUserIdOrPassphrase builder = this
.withPrimaryKey( .withPrimaryKey(KeySpec
KeySpec.getBuilder(KeyType.RSA(length)) .getBuilder(KeyType.RSA(length), KeyFlag.CERTIFY_OTHER, KeyFlag.SIGN_DATA, KeyFlag.ENCRYPT_COMMS)
.withKeyFlags(KeyFlag.CERTIFY_OTHER, KeyFlag.SIGN_DATA, KeyFlag.ENCRYPT_COMMS) .build())
.withDefaultAlgorithms())
.withPrimaryUserId(userId); .withPrimaryUserId(userId);
if (password == null) { if (password == null) {
@ -197,13 +196,11 @@ public class KeyRingBuilder implements KeyRingBuilderInterface {
throws PGPException, NoSuchAlgorithmException, InvalidAlgorithmParameterException { throws PGPException, NoSuchAlgorithmException, InvalidAlgorithmParameterException {
WithAdditionalUserIdOrPassphrase builder = this WithAdditionalUserIdOrPassphrase builder = this
.withSubKey( .withSubKey(
KeySpec.getBuilder(KeyType.XDH(XDHSpec._X25519)) KeySpec.getBuilder(KeyType.XDH(XDHSpec._X25519), KeyFlag.ENCRYPT_STORAGE, KeyFlag.ENCRYPT_COMMS)
.withKeyFlags(KeyFlag.ENCRYPT_STORAGE, KeyFlag.ENCRYPT_COMMS) .build())
.withDefaultAlgorithms())
.withPrimaryKey( .withPrimaryKey(
KeySpec.getBuilder(KeyType.EDDSA(EdDSACurve._Ed25519)) KeySpec.getBuilder(KeyType.EDDSA(EdDSACurve._Ed25519), KeyFlag.CERTIFY_OTHER, KeyFlag.SIGN_DATA)
.withKeyFlags(KeyFlag.CERTIFY_OTHER, KeyFlag.SIGN_DATA) .build())
.withDefaultAlgorithms())
.withPrimaryUserId(userId); .withPrimaryUserId(userId);
if (password == null) { if (password == null) {
@ -225,17 +222,14 @@ public class KeyRingBuilder implements KeyRingBuilderInterface {
throws InvalidAlgorithmParameterException, NoSuchAlgorithmException, PGPException { throws InvalidAlgorithmParameterException, NoSuchAlgorithmException, PGPException {
WithAdditionalUserIdOrPassphrase builder = this WithAdditionalUserIdOrPassphrase builder = this
.withSubKey( .withSubKey(
KeySpec.getBuilder(KeyType.XDH(XDHSpec._X25519)) KeySpec.getBuilder(KeyType.XDH(XDHSpec._X25519), KeyFlag.ENCRYPT_STORAGE, KeyFlag.ENCRYPT_COMMS)
.withKeyFlags(KeyFlag.ENCRYPT_STORAGE, KeyFlag.ENCRYPT_COMMS) .build())
.withDefaultAlgorithms())
.withSubKey( .withSubKey(
KeySpec.getBuilder(KeyType.EDDSA(EdDSACurve._Ed25519)) KeySpec.getBuilder(KeyType.EDDSA(EdDSACurve._Ed25519), KeyFlag.SIGN_DATA)
.withKeyFlags(KeyFlag.SIGN_DATA) .build())
.withDefaultAlgorithms())
.withPrimaryKey( .withPrimaryKey(
KeySpec.getBuilder(KeyType.EDDSA(EdDSACurve._Ed25519)) KeySpec.getBuilder(KeyType.EDDSA(EdDSACurve._Ed25519), KeyFlag.CERTIFY_OTHER)
.withKeyFlags(KeyFlag.CERTIFY_OTHER) .build())
.withDefaultAlgorithms())
.withPrimaryUserId(userId); .withPrimaryUserId(userId);
if (password == null) { if (password == null) {

View file

@ -20,6 +20,7 @@ import javax.annotation.Nullable;
import org.bouncycastle.openpgp.PGPSignatureSubpacketGenerator; import org.bouncycastle.openpgp.PGPSignatureSubpacketGenerator;
import org.bouncycastle.openpgp.PGPSignatureSubpacketVector; import org.bouncycastle.openpgp.PGPSignatureSubpacketVector;
import org.pgpainless.algorithm.KeyFlag;
import org.pgpainless.key.generation.type.KeyType; import org.pgpainless.key.generation.type.KeyType;
public class KeySpec { public class KeySpec {
@ -54,7 +55,7 @@ public class KeySpec {
return inheritedSubPackets; return inheritedSubPackets;
} }
public static KeySpecBuilder getBuilder(KeyType type) { public static KeySpecBuilder getBuilder(KeyType type, KeyFlag... flags) {
return new KeySpecBuilder(type); return new KeySpecBuilder(type, flags);
} }
} }

View file

@ -15,10 +15,14 @@
*/ */
package org.pgpainless.key.generation; package org.pgpainless.key.generation;
import java.util.Arrays;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Set;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import org.bouncycastle.bcpg.sig.Features;
import org.bouncycastle.openpgp.PGPSignatureSubpacketGenerator; import org.bouncycastle.openpgp.PGPSignatureSubpacketGenerator;
import org.pgpainless.PGPainless;
import org.pgpainless.algorithm.AlgorithmSuite; import org.pgpainless.algorithm.AlgorithmSuite;
import org.pgpainless.algorithm.CompressionAlgorithm; import org.pgpainless.algorithm.CompressionAlgorithm;
import org.pgpainless.algorithm.Feature; import org.pgpainless.algorithm.Feature;
@ -30,20 +34,83 @@ import org.pgpainless.key.generation.type.KeyType;
public class KeySpecBuilder implements KeySpecBuilderInterface { public class KeySpecBuilder implements KeySpecBuilderInterface {
private final KeyType type; private final KeyType type;
private final KeyFlag[] keyFlags;
private final PGPSignatureSubpacketGenerator hashedSubPackets = new PGPSignatureSubpacketGenerator(); private final PGPSignatureSubpacketGenerator hashedSubPackets = new PGPSignatureSubpacketGenerator();
private final AlgorithmSuite algorithmSuite = PGPainless.getPolicy().getKeyGenerationAlgorithmSuite();
private Set<CompressionAlgorithm> preferredCompressionAlgorithms = algorithmSuite.getCompressionAlgorithms();
private Set<HashAlgorithm> preferredHashAlgorithms = algorithmSuite.getHashAlgorithms();
private Set<SymmetricKeyAlgorithm> preferredSymmetricAlgorithms = algorithmSuite.getSymmetricKeyAlgorithms();
KeySpecBuilder(@Nonnull KeyType type) { KeySpecBuilder(@Nonnull KeyType type, KeyFlag... flags) {
if (flags == null || flags.length == 0) {
throw new IllegalArgumentException("KeyFlags cannot be empty.");
}
assureKeyCanCarryFlags(type, flags);
this.type = type; this.type = type;
this.keyFlags = flags;
} }
@Override @Override
public WithDetailedConfiguration withKeyFlags(@Nonnull KeyFlag... flags) { public KeySpecBuilder overridePreferredCompressionAlgorithms(@Nonnull CompressionAlgorithm... compressionAlgorithms) {
assureKeyCanCarryFlags(flags); this.preferredCompressionAlgorithms = new LinkedHashSet<>(Arrays.asList(compressionAlgorithms));
this.hashedSubPackets.setKeyFlags(false, KeyFlag.toBitmask(flags)); return this;
return new WithDetailedConfigurationImpl();
} }
private void assureKeyCanCarryFlags(KeyFlag... flags) { @Override
public KeySpecBuilder overridePreferredHashAlgorithms(@Nonnull HashAlgorithm... preferredHashAlgorithms) {
this.preferredHashAlgorithms = new LinkedHashSet<>(Arrays.asList(preferredHashAlgorithms));
return this;
}
@Override
public KeySpecBuilder overridePreferredSymmetricKeyAlgorithms(@Nonnull SymmetricKeyAlgorithm... preferredSymmetricKeyAlgorithms) {
this.preferredSymmetricAlgorithms = new LinkedHashSet<>(Arrays.asList(preferredSymmetricKeyAlgorithms));
return this;
}
@Override
public KeySpec build() {
this.hashedSubPackets.setKeyFlags(false, KeyFlag.toBitmask(keyFlags));
this.hashedSubPackets.setPreferredCompressionAlgorithms(false, getPreferredCompressionAlgorithmIDs());
this.hashedSubPackets.setPreferredHashAlgorithms(false, getPreferredHashAlgorithmIDs());
this.hashedSubPackets.setPreferredSymmetricAlgorithms(false, getPreferredSymmetricKeyAlgorithmIDs());
this.hashedSubPackets.setFeature(false, Feature.MODIFICATION_DETECTION.getFeatureId());
return new KeySpec(
KeySpecBuilder.this.type,
hashedSubPackets,
false);
}
private int[] getPreferredCompressionAlgorithmIDs() {
int[] ids = new int[preferredCompressionAlgorithms.size()];
Iterator<CompressionAlgorithm> iterator = preferredCompressionAlgorithms.iterator();
for (int i = 0; i < ids.length; i++) {
ids[i] = iterator.next().getAlgorithmId();
}
return ids;
}
private int[] getPreferredHashAlgorithmIDs() {
int[] ids = new int[preferredHashAlgorithms.size()];
Iterator<HashAlgorithm> iterator = preferredHashAlgorithms.iterator();
for (int i = 0; i < ids.length; i++) {
ids[i] = iterator.next().getAlgorithmId();
}
return ids;
}
private int[] getPreferredSymmetricKeyAlgorithmIDs() {
int[] ids = new int[preferredSymmetricAlgorithms.size()];
Iterator<SymmetricKeyAlgorithm> iterator = preferredSymmetricAlgorithms.iterator();
for (int i = 0; i < ids.length; i++) {
ids[i] = iterator.next().getAlgorithmId();
}
return ids;
}
private static void assureKeyCanCarryFlags(KeyType type, KeyFlag... flags) {
final int mask = KeyFlag.toBitmask(flags); final int mask = KeyFlag.toBitmask(flags);
if (!type.canCertify() && KeyFlag.hasKeyFlag(mask, KeyFlag.CERTIFY_OTHER)) { if (!type.canCertify() && KeyFlag.hasKeyFlag(mask, KeyFlag.CERTIFY_OTHER)) {
@ -66,120 +133,4 @@ public class KeySpecBuilder implements KeySpecBuilderInterface {
throw new IllegalArgumentException("KeyType " + type.getName() + " cannot carry key flag AUTHENTIACTION."); throw new IllegalArgumentException("KeyType " + type.getName() + " cannot carry key flag AUTHENTIACTION.");
} }
} }
@Override
public KeySpec withInheritedSubPackets() {
return new KeySpec(type, null, true);
}
class WithDetailedConfigurationImpl implements WithDetailedConfiguration {
@Deprecated
@Override
public WithPreferredSymmetricAlgorithms withDetailedConfiguration() {
return new WithPreferredSymmetricAlgorithmsImpl();
}
@Override
public KeySpec withDefaultAlgorithms() {
AlgorithmSuite defaultSuite = AlgorithmSuite.getDefaultAlgorithmSuite();
hashedSubPackets.setPreferredCompressionAlgorithms(false, defaultSuite.getCompressionAlgorithmIds());
hashedSubPackets.setPreferredSymmetricAlgorithms(false, defaultSuite.getSymmetricKeyAlgorithmIds());
hashedSubPackets.setPreferredHashAlgorithms(false, defaultSuite.getHashAlgorithmIds());
hashedSubPackets.setFeature(false, Features.FEATURE_MODIFICATION_DETECTION);
return new KeySpec(
KeySpecBuilder.this.type,
KeySpecBuilder.this.hashedSubPackets,
false);
}
}
class WithPreferredSymmetricAlgorithmsImpl implements WithPreferredSymmetricAlgorithms {
@Override
public WithPreferredHashAlgorithms withPreferredSymmetricAlgorithms(@Nonnull SymmetricKeyAlgorithm... algorithms) {
int[] ids = new int[algorithms.length];
for (int i = 0; i < ids.length; i++) {
ids[i] = algorithms[i].getAlgorithmId();
}
KeySpecBuilder.this.hashedSubPackets.setPreferredSymmetricAlgorithms(false, ids);
return new WithPreferredHashAlgorithmsImpl();
}
@Override
public WithPreferredHashAlgorithms withDefaultSymmetricAlgorithms() {
KeySpecBuilder.this.hashedSubPackets.setPreferredSymmetricAlgorithms(false,
AlgorithmSuite.getDefaultAlgorithmSuite().getSymmetricKeyAlgorithmIds());
return new WithPreferredHashAlgorithmsImpl();
}
@Override
public WithFeatures withDefaultAlgorithms() {
hashedSubPackets.setPreferredSymmetricAlgorithms(false,
AlgorithmSuite.getDefaultAlgorithmSuite().getSymmetricKeyAlgorithmIds());
hashedSubPackets.setPreferredCompressionAlgorithms(false,
AlgorithmSuite.getDefaultAlgorithmSuite().getCompressionAlgorithmIds());
hashedSubPackets.setPreferredHashAlgorithms(false,
AlgorithmSuite.getDefaultAlgorithmSuite().getHashAlgorithmIds());
return new WithFeaturesImpl();
}
}
class WithPreferredHashAlgorithmsImpl implements WithPreferredHashAlgorithms {
@Override
public WithPreferredCompressionAlgorithms withPreferredHashAlgorithms(@Nonnull HashAlgorithm... algorithms) {
int[] ids = new int[algorithms.length];
for (int i = 0; i < ids.length; i++) {
ids[i] = algorithms[i].getAlgorithmId();
}
KeySpecBuilder.this.hashedSubPackets.setPreferredHashAlgorithms(false, ids);
return new WithPreferredCompressionAlgorithmsImpl();
}
@Override
public WithPreferredCompressionAlgorithms withDefaultHashAlgorithms() {
KeySpecBuilder.this.hashedSubPackets.setPreferredHashAlgorithms(false,
AlgorithmSuite.getDefaultAlgorithmSuite().getHashAlgorithmIds());
return new WithPreferredCompressionAlgorithmsImpl();
}
}
class WithPreferredCompressionAlgorithmsImpl implements WithPreferredCompressionAlgorithms {
@Override
public WithFeatures withPreferredCompressionAlgorithms(@Nonnull CompressionAlgorithm... algorithms) {
int[] ids = new int[algorithms.length];
for (int i = 0; i < ids.length; i++) {
ids[i] = algorithms[i].getAlgorithmId();
}
KeySpecBuilder.this.hashedSubPackets.setPreferredCompressionAlgorithms(false, ids);
return new WithFeaturesImpl();
}
@Override
public WithFeatures withDefaultCompressionAlgorithms() {
KeySpecBuilder.this.hashedSubPackets.setPreferredCompressionAlgorithms(false,
AlgorithmSuite.getDefaultAlgorithmSuite().getCompressionAlgorithmIds());
return new WithFeaturesImpl();
}
}
class WithFeaturesImpl implements WithFeatures {
@Override
public WithFeatures withFeature(@Nonnull Feature feature) {
KeySpecBuilder.this.hashedSubPackets.setFeature(false, feature.getFeatureId());
return this;
}
@Override
public KeySpec done() {
return new KeySpec(
KeySpecBuilder.this.type,
hashedSubPackets,
false);
}
}
} }

View file

@ -18,55 +18,16 @@ package org.pgpainless.key.generation;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import org.pgpainless.algorithm.CompressionAlgorithm; import org.pgpainless.algorithm.CompressionAlgorithm;
import org.pgpainless.algorithm.Feature;
import org.pgpainless.algorithm.HashAlgorithm; import org.pgpainless.algorithm.HashAlgorithm;
import org.pgpainless.algorithm.KeyFlag;
import org.pgpainless.algorithm.SymmetricKeyAlgorithm; import org.pgpainless.algorithm.SymmetricKeyAlgorithm;
public interface KeySpecBuilderInterface { public interface KeySpecBuilderInterface {
WithDetailedConfiguration withKeyFlags(@Nonnull KeyFlag... flags); KeySpecBuilder overridePreferredCompressionAlgorithms(@Nonnull CompressionAlgorithm... compressionAlgorithms);
KeySpec withInheritedSubPackets(); KeySpecBuilder overridePreferredHashAlgorithms(@Nonnull HashAlgorithm... preferredHashAlgorithms);
interface WithDetailedConfiguration { KeySpecBuilder overridePreferredSymmetricKeyAlgorithms(@Nonnull SymmetricKeyAlgorithm... preferredSymmetricKeyAlgorithms);
WithPreferredSymmetricAlgorithms withDetailedConfiguration();
KeySpec withDefaultAlgorithms();
}
interface WithPreferredSymmetricAlgorithms {
WithPreferredHashAlgorithms withPreferredSymmetricAlgorithms(@Nonnull SymmetricKeyAlgorithm... algorithms);
WithPreferredHashAlgorithms withDefaultSymmetricAlgorithms();
WithFeatures withDefaultAlgorithms();
}
interface WithPreferredHashAlgorithms {
WithPreferredCompressionAlgorithms withPreferredHashAlgorithms(@Nonnull HashAlgorithm... algorithms);
WithPreferredCompressionAlgorithms withDefaultHashAlgorithms();
}
interface WithPreferredCompressionAlgorithms {
WithFeatures withPreferredCompressionAlgorithms(@Nonnull CompressionAlgorithm... algorithms);
WithFeatures withDefaultCompressionAlgorithms();
}
interface WithFeatures {
WithFeatures withFeature(@Nonnull Feature feature);
KeySpec done();
}
KeySpec build();
} }

View file

@ -21,6 +21,9 @@ import java.util.EnumMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import javax.annotation.Nonnull;
import org.pgpainless.algorithm.AlgorithmSuite;
import org.pgpainless.algorithm.CompressionAlgorithm; import org.pgpainless.algorithm.CompressionAlgorithm;
import org.pgpainless.algorithm.HashAlgorithm; import org.pgpainless.algorithm.HashAlgorithm;
import org.pgpainless.algorithm.PublicKeyAlgorithm; import org.pgpainless.algorithm.PublicKeyAlgorithm;
@ -48,6 +51,8 @@ public final class Policy {
PublicKeyAlgorithmPolicy.defaultPublicKeyAlgorithmPolicy(); PublicKeyAlgorithmPolicy.defaultPublicKeyAlgorithmPolicy();
private final NotationRegistry notationRegistry = new NotationRegistry(); private final NotationRegistry notationRegistry = new NotationRegistry();
private AlgorithmSuite keyGenerationAlgorithmSuite = AlgorithmSuite.getDefaultAlgorithmSuite();
Policy() { Policy() {
} }
@ -122,7 +127,7 @@ public final class Policy {
* *
* @return symmetric algorithm policy for decryption * @return symmetric algorithm policy for decryption
*/ */
public SymmetricKeyAlgorithmPolicy getSymmetricKeyDecryptionAlgoritmPolicy() { public SymmetricKeyAlgorithmPolicy getSymmetricKeyDecryptionAlgorithmPolicy() {
return symmetricKeyDecryptionAlgorithmPolicy; return symmetricKeyDecryptionAlgorithmPolicy;
} }
@ -459,4 +464,21 @@ public final class Policy {
public NotationRegistry getNotationRegistry() { public NotationRegistry getNotationRegistry() {
return notationRegistry; return notationRegistry;
} }
/**
* Return the current {@link AlgorithmSuite} which defines preferred algorithms used during key generation.
* @return current algorithm suite
*/
public @Nonnull AlgorithmSuite getKeyGenerationAlgorithmSuite() {
return keyGenerationAlgorithmSuite;
}
/**
* Set a custom {@link AlgorithmSuite} which defines preferred algorithms used during key generation.
*
* @param algorithmSuite custom algorithm suite
*/
public void setKeyGenerationAlgorithmSuite(@Nonnull AlgorithmSuite algorithmSuite) {
this.keyGenerationAlgorithmSuite = algorithmSuite;
}
} }

View file

@ -88,8 +88,13 @@ public class EncryptDecryptTest {
ImplementationFactory.setFactoryImplementation(implementationFactory); ImplementationFactory.setFactoryImplementation(implementationFactory);
PGPSecretKeyRing sender = PGPainless.generateKeyRing().simpleRsaKeyRing("romeo@montague.lit", RsaLength._3072); PGPSecretKeyRing sender = PGPainless.generateKeyRing().simpleRsaKeyRing("romeo@montague.lit", RsaLength._3072);
PGPSecretKeyRing recipient = PGPainless.generateKeyRing() PGPSecretKeyRing recipient = PGPainless.generateKeyRing()
.withSubKey(KeySpec.getBuilder(ElGamal.withLength(ElGamalLength._3072)).withKeyFlags(KeyFlag.ENCRYPT_STORAGE, KeyFlag.ENCRYPT_COMMS).withDefaultAlgorithms()) .withSubKey(KeySpec.getBuilder(
.withPrimaryKey(KeySpec.getBuilder(KeyType.RSA(RsaLength._4096)).withKeyFlags(KeyFlag.SIGN_DATA, KeyFlag.CERTIFY_OTHER).withDefaultAlgorithms()) ElGamal.withLength(ElGamalLength._3072),
KeyFlag.ENCRYPT_STORAGE, KeyFlag.ENCRYPT_COMMS)
.build())
.withPrimaryKey(KeySpec.getBuilder(
KeyType.RSA(RsaLength._4096),
KeyFlag.SIGN_DATA, KeyFlag.CERTIFY_OTHER).build())
.withPrimaryUserId("juliet@capulet.lit").withoutPassphrase().build(); .withPrimaryUserId("juliet@capulet.lit").withoutPassphrase().build();
encryptDecryptForSecretKeyRings(sender, recipient); encryptDecryptForSecretKeyRings(sender, recipient);

View file

@ -59,13 +59,12 @@ public class EncryptionOptionsTest {
@BeforeAll @BeforeAll
public static void generateKey() throws PGPException, InvalidAlgorithmParameterException, NoSuchAlgorithmException { public static void generateKey() throws PGPException, InvalidAlgorithmParameterException, NoSuchAlgorithmException {
secretKeys = PGPainless.generateKeyRing() secretKeys = PGPainless.generateKeyRing()
.withSubKey(KeySpec.getBuilder(KeyType.XDH(XDHSpec._X25519)) .withSubKey(KeySpec.getBuilder(KeyType.XDH(XDHSpec._X25519), KeyFlag.ENCRYPT_COMMS)
.withKeyFlags(KeyFlag.ENCRYPT_COMMS).withDefaultAlgorithms()) .build())
.withSubKey(KeySpec.getBuilder(KeyType.XDH(XDHSpec._X25519)) .withSubKey(KeySpec.getBuilder(KeyType.XDH(XDHSpec._X25519), KeyFlag.ENCRYPT_STORAGE)
.withKeyFlags(KeyFlag.ENCRYPT_STORAGE).withDefaultAlgorithms()) .build())
.withPrimaryKey(KeySpec.getBuilder(KeyType.EDDSA(EdDSACurve._Ed25519)) .withPrimaryKey(KeySpec.getBuilder(KeyType.EDDSA(EdDSACurve._Ed25519), KeyFlag.CERTIFY_OTHER)
.withKeyFlags(KeyFlag.CERTIFY_OTHER) .build())
.withDefaultAlgorithms())
.withPrimaryUserId("test@pgpainless.org") .withPrimaryUserId("test@pgpainless.org")
.withoutPassphrase() .withoutPassphrase()
.build(); .build();
@ -140,8 +139,8 @@ public class EncryptionOptionsTest {
public void testAddRecipient_KeyWithoutEncryptionKeyFails() throws PGPException, InvalidAlgorithmParameterException, NoSuchAlgorithmException { public void testAddRecipient_KeyWithoutEncryptionKeyFails() throws PGPException, InvalidAlgorithmParameterException, NoSuchAlgorithmException {
EncryptionOptions options = new EncryptionOptions(); EncryptionOptions options = new EncryptionOptions();
PGPSecretKeyRing secretKeys = PGPainless.generateKeyRing() PGPSecretKeyRing secretKeys = PGPainless.generateKeyRing()
.withPrimaryKey(KeySpec.getBuilder(KeyType.EDDSA(EdDSACurve._Ed25519)) .withPrimaryKey(KeySpec.getBuilder(KeyType.EDDSA(EdDSACurve._Ed25519), KeyFlag.CERTIFY_OTHER, KeyFlag.SIGN_DATA)
.withKeyFlags(KeyFlag.CERTIFY_OTHER, KeyFlag.SIGN_DATA).withDefaultAlgorithms()) .build())
.withPrimaryUserId("test@pgpainless.org") .withPrimaryUserId("test@pgpainless.org")
.withoutPassphrase().build(); .withoutPassphrase().build();
PGPPublicKeyRing publicKeys = KeyRingUtils.publicKeyRingFrom(secretKeys); PGPPublicKeyRing publicKeys = KeyRingUtils.publicKeyRingFrom(secretKeys);

View file

@ -27,16 +27,13 @@ import org.bouncycastle.openpgp.PGPPublicKeyRing;
import org.bouncycastle.openpgp.PGPSecretKeyRing; import org.bouncycastle.openpgp.PGPSecretKeyRing;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.pgpainless.PGPainless; import org.pgpainless.PGPainless;
import org.pgpainless.algorithm.AlgorithmSuite;
import org.pgpainless.algorithm.CompressionAlgorithm; import org.pgpainless.algorithm.CompressionAlgorithm;
import org.pgpainless.algorithm.EncryptionPurpose; import org.pgpainless.algorithm.EncryptionPurpose;
import org.pgpainless.algorithm.Feature;
import org.pgpainless.algorithm.HashAlgorithm; import org.pgpainless.algorithm.HashAlgorithm;
import org.pgpainless.algorithm.KeyFlag; import org.pgpainless.algorithm.KeyFlag;
import org.pgpainless.algorithm.PublicKeyAlgorithm; import org.pgpainless.algorithm.PublicKeyAlgorithm;
import org.pgpainless.algorithm.SymmetricKeyAlgorithm; import org.pgpainless.algorithm.SymmetricKeyAlgorithm;
import org.pgpainless.key.generation.KeySpec; import org.pgpainless.key.generation.KeySpec;
import org.pgpainless.key.generation.KeySpecBuilderInterface;
import org.pgpainless.key.generation.type.KeyType; import org.pgpainless.key.generation.type.KeyType;
import org.pgpainless.key.generation.type.ecc.EllipticCurve; import org.pgpainless.key.generation.type.ecc.EllipticCurve;
import org.pgpainless.key.generation.type.eddsa.EdDSACurve; import org.pgpainless.key.generation.type.eddsa.EdDSACurve;
@ -162,24 +159,20 @@ public class GenerateKeys {
* the specifications for the subkeys first (in {@link org.pgpainless.key.generation.KeyRingBuilderInterface#withSubKey(KeySpec)}) * the specifications for the subkeys first (in {@link org.pgpainless.key.generation.KeyRingBuilderInterface#withSubKey(KeySpec)})
* and add the primary key specification last (in {@link org.pgpainless.key.generation.KeyRingBuilderInterface#withPrimaryKey(KeySpec)}. * and add the primary key specification last (in {@link org.pgpainless.key.generation.KeyRingBuilderInterface#withPrimaryKey(KeySpec)}.
* *
* {@link KeySpec} objects can best be obtained by using the {@link KeySpec#getBuilder(KeyType)} method and providing a {@link KeyType}. * {@link KeySpec} objects can best be obtained by using the {@link KeySpec#getBuilder(KeyType, KeyFlag...)} method and providing a {@link KeyType}.
* There are a bunch of factory methods for different {@link KeyType} implementations present in {@link KeyType} itself * There are a bunch of factory methods for different {@link KeyType} implementations present in {@link KeyType} itself
* (such as {@link KeyType#ECDH(EllipticCurve)}. * (such as {@link KeyType#ECDH(EllipticCurve)}. {@link KeyFlag KeyFlags} determine
*
* After that, the {@link org.pgpainless.key.generation.KeySpecBuilder} needs to be further configured.
* First of all, the keys {@link KeyFlag KeyFlags} need to be specified. {@link KeyFlag KeyFlags} determine
* the use of the key, like encryption, signing data or certifying subkeys. * the use of the key, like encryption, signing data or certifying subkeys.
* KeyFlags can be set with {@link org.pgpainless.key.generation.KeySpecBuilder#withKeyFlags(KeyFlag...)}.
* *
* Next is algorithm setup. You can either trust PGPainless' defaults (see {@link AlgorithmSuite#getDefaultAlgorithmSuite()}), * If you so desire, you can now specify your own algorithm preferences.
* or specify your own algorithm preferences. * For that, see {@link org.pgpainless.key.generation.KeySpecBuilder#overridePreferredCompressionAlgorithms(CompressionAlgorithm...)},
* To go with the defaults, call {@link KeySpecBuilderInterface.WithDetailedConfiguration#withDefaultAlgorithms()}, * {@link org.pgpainless.key.generation.KeySpecBuilder#overridePreferredHashAlgorithms(HashAlgorithm...)} or
* otherwise start detailed config with {@link KeySpecBuilderInterface.WithDetailedConfiguration#withDetailedConfiguration()}. * {@link org.pgpainless.key.generation.KeySpecBuilder#overridePreferredSymmetricKeyAlgorithms(SymmetricKeyAlgorithm...)}.
* *
* Note, that if you set preferred algorithms, the preference lists are sorted from high priority to low priority. * Note, that if you set preferred algorithms, the preference lists are sorted from high priority to low priority.
* *
* When setting the primary key spec ({@link org.pgpainless.key.generation.KeyRingBuilder#withPrimaryKey(KeySpec)}), * When setting the primary key spec ({@link org.pgpainless.key.generation.KeyRingBuilder#withPrimaryKey(KeySpec)}),
* make sure that the primary key spec has the {@link KeyFlag} {@link KeyFlag#CERTIFY_OTHER} set, as this is an requirement * make sure that the primary key spec has the {@link KeyFlag} {@link KeyFlag#CERTIFY_OTHER} set, as this is a requirement
* for primary keys. * for primary keys.
* *
* Furthermore you have to set at least the primary user-id via * Furthermore you have to set at least the primary user-id via
@ -187,7 +180,7 @@ public class GenerateKeys {
* but you can also add additional user-ids via * but you can also add additional user-ids via
* {@link org.pgpainless.key.generation.KeyRingBuilderInterface.WithAdditionalUserIdOrPassphrase#withAdditionalUserId(String)}. * {@link org.pgpainless.key.generation.KeyRingBuilderInterface.WithAdditionalUserIdOrPassphrase#withAdditionalUserId(String)}.
* *
* Lastly you can decide whether or not to set a passphrase to protect the secret key. * Lastly you can decide whether to set a passphrase to protect the secret key.
* *
* @throws PGPException * @throws PGPException
* @throws InvalidAlgorithmParameterException * @throws InvalidAlgorithmParameterException
@ -212,37 +205,32 @@ public class GenerateKeys {
.withSubKey( .withSubKey(
KeySpec.getBuilder( KeySpec.getBuilder(
// We choose an ECDH key over the brainpoolp256r1 curve // We choose an ECDH key over the brainpoolp256r1 curve
KeyType.ECDH(EllipticCurve._BRAINPOOLP256R1) KeyType.ECDH(EllipticCurve._BRAINPOOLP256R1),
)
// Our key can encrypt both communication data, as well as data at rest // Our key can encrypt both communication data, as well as data at rest
.withKeyFlags(KeyFlag.ENCRYPT_STORAGE, KeyFlag.ENCRYPT_COMMS) KeyFlag.ENCRYPT_STORAGE, KeyFlag.ENCRYPT_COMMS
)
// Optionally: Configure the subkey with custom algorithm preferences // Optionally: Configure the subkey with custom algorithm preferences
// Is is recommended though to go with PGPainless' defaults which can be found in the // Is is recommended though to go with PGPainless' defaults which can be found in the
// AlgorithmSuite class. // AlgorithmSuite class.
.withDetailedConfiguration() .overridePreferredSymmetricKeyAlgorithms(SymmetricKeyAlgorithm.AES_256, SymmetricKeyAlgorithm.AES_192, SymmetricKeyAlgorithm.AES_128)
.withPreferredSymmetricAlgorithms(SymmetricKeyAlgorithm.AES_256, SymmetricKeyAlgorithm.AES_192, SymmetricKeyAlgorithm.AES_128) .overridePreferredHashAlgorithms(HashAlgorithm.SHA512, HashAlgorithm.SHA384, HashAlgorithm.SHA256)
.withPreferredHashAlgorithms(HashAlgorithm.SHA512, HashAlgorithm.SHA384, HashAlgorithm.SHA256) .overridePreferredCompressionAlgorithms(CompressionAlgorithm.ZIP, CompressionAlgorithm.BZIP2, CompressionAlgorithm.ZLIB)
.withPreferredCompressionAlgorithms(CompressionAlgorithm.ZIP, CompressionAlgorithm.BZIP2, CompressionAlgorithm.ZLIB) .build()
// Modification Detection is highly recommended
.withFeature(Feature.MODIFICATION_DETECTION)
.done()
) )
// Add the second subkey (signing) // Add the second subkey (signing)
.withSubKey( .withSubKey(
KeySpec.getBuilder( KeySpec.getBuilder(
KeyType.ECDSA(EllipticCurve._BRAINPOOLP384R1) KeyType.ECDSA(EllipticCurve._BRAINPOOLP384R1),
)
// This key is used for creating signatures only // This key is used for creating signatures only
.withKeyFlags(KeyFlag.SIGN_DATA) KeyFlag.SIGN_DATA
// Instead of manually specifying algorithm preferences, we can simply use PGPainless' sane defaults ).build()
.withDefaultAlgorithms()
) )
// Lastly we add the primary key (certification only in our case) // Lastly we add the primary key (certification only in our case)
.withPrimaryKey( .withPrimaryKey(
KeySpec.getBuilder(KeyType.EDDSA(EdDSACurve._Ed25519)) KeySpec.getBuilder(KeyType.EDDSA(EdDSACurve._Ed25519),
// The primary key MUST carry the CERTIFY_OTHER flag, but CAN carry additional flags // The primary key MUST carry the CERTIFY_OTHER flag, but CAN carry additional flags
.withKeyFlags(KeyFlag.CERTIFY_OTHER) KeyFlag.CERTIFY_OTHER)
.withDefaultAlgorithms() .build()
) )
// Set primary user-id // Set primary user-id
.withPrimaryUserId(userId) .withPrimaryUserId(userId)

View file

@ -187,9 +187,8 @@ public class ModifyKeys {
Passphrase subkeyPassphrase = Passphrase.fromPassword("subk3yP4ssphr4s3"); Passphrase subkeyPassphrase = Passphrase.fromPassword("subk3yP4ssphr4s3");
secretKey = PGPainless.modifyKeyRing(secretKey) secretKey = PGPainless.modifyKeyRing(secretKey)
.addSubKey( .addSubKey(
KeySpec.getBuilder(KeyType.ECDH(EllipticCurve._BRAINPOOLP512R1)) KeySpec.getBuilder(KeyType.ECDH(EllipticCurve._BRAINPOOLP512R1), KeyFlag.ENCRYPT_COMMS)
.withKeyFlags(KeyFlag.ENCRYPT_COMMS) .build(),
.withDefaultAlgorithms(),
subkeyPassphrase, subkeyPassphrase,
protector) protector)
.done(); .done();

View file

@ -54,12 +54,10 @@ public class BrainpoolKeyGenerationTest {
for (EllipticCurve curve : EllipticCurve.values()) { for (EllipticCurve curve : EllipticCurve.values()) {
PGPSecretKeyRing secretKeys = generateKey( PGPSecretKeyRing secretKeys = generateKey(
KeySpec.getBuilder(KeyType.ECDSA(curve)) KeySpec.getBuilder(
.withKeyFlags(KeyFlag.CERTIFY_OTHER, KeyFlag.SIGN_DATA) KeyType.ECDSA(curve), KeyFlag.CERTIFY_OTHER, KeyFlag.SIGN_DATA).build(),
.withDefaultAlgorithms(), KeySpec.getBuilder(
KeySpec.getBuilder(KeyType.ECDH(curve)) KeyType.ECDH(curve), KeyFlag.ENCRYPT_COMMS, KeyFlag.ENCRYPT_STORAGE).build(),
.withKeyFlags(KeyFlag.ENCRYPT_COMMS, KeyFlag.ENCRYPT_STORAGE)
.withDefaultAlgorithms(),
"Elliptic Curve <elliptic@curve.key>"); "Elliptic Curve <elliptic@curve.key>");
assertEquals(PublicKeyAlgorithm.ECDSA, PublicKeyAlgorithm.fromId(secretKeys.getPublicKey().getAlgorithm())); assertEquals(PublicKeyAlgorithm.ECDSA, PublicKeyAlgorithm.fromId(secretKeys.getPublicKey().getAlgorithm()));
@ -85,18 +83,15 @@ public class BrainpoolKeyGenerationTest {
ImplementationFactory.setFactoryImplementation(implementationFactory); ImplementationFactory.setFactoryImplementation(implementationFactory);
PGPSecretKeyRing secretKeys = PGPainless.generateKeyRing() PGPSecretKeyRing secretKeys = PGPainless.generateKeyRing()
.withSubKey(KeySpec.getBuilder(KeyType.EDDSA(EdDSACurve._Ed25519)) .withSubKey(KeySpec.getBuilder(KeyType.EDDSA(EdDSACurve._Ed25519), KeyFlag.SIGN_DATA).build())
.withKeyFlags(KeyFlag.SIGN_DATA) .withSubKey(KeySpec.getBuilder(
.withDefaultAlgorithms()) KeyType.XDH(XDHSpec._X25519), KeyFlag.ENCRYPT_COMMS, KeyFlag.ENCRYPT_STORAGE)
.withSubKey(KeySpec.getBuilder(KeyType.XDH(XDHSpec._X25519)) .build())
.withKeyFlags(KeyFlag.ENCRYPT_COMMS, KeyFlag.ENCRYPT_STORAGE) .withSubKey(KeySpec.getBuilder(
.withDefaultAlgorithms()) KeyType.RSA(RsaLength._3072), KeyFlag.SIGN_DATA)
.withSubKey(KeySpec.getBuilder(KeyType.RSA(RsaLength._3072)) .build())
.withKeyFlags(KeyFlag.SIGN_DATA) .withPrimaryKey(KeySpec.getBuilder(
.withDefaultAlgorithms()) KeyType.ECDSA(EllipticCurve._BRAINPOOLP384R1), KeyFlag.CERTIFY_OTHER).build())
.withPrimaryKey(KeySpec.getBuilder(KeyType.ECDSA(EllipticCurve._BRAINPOOLP384R1))
.withKeyFlags(KeyFlag.CERTIFY_OTHER)
.withDefaultAlgorithms())
.withPrimaryUserId(UserId.nameAndEmail("Alice", "alice@pgpainless.org")) .withPrimaryUserId(UserId.nameAndEmail("Alice", "alice@pgpainless.org"))
.withPassphrase(Passphrase.fromPassword("passphrase")) .withPassphrase(Passphrase.fromPassword("passphrase"))
.build(); .build();

View file

@ -47,9 +47,8 @@ public class CertificationKeyMustBeAbleToCertifyTest {
assertThrows(IllegalArgumentException.class, () -> PGPainless assertThrows(IllegalArgumentException.class, () -> PGPainless
.generateKeyRing() .generateKeyRing()
.withPrimaryKey(KeySpec .withPrimaryKey(KeySpec
.getBuilder(type) .getBuilder(type, KeyFlag.CERTIFY_OTHER, KeyFlag.SIGN_DATA)
.withKeyFlags(KeyFlag.CERTIFY_OTHER, KeyFlag.SIGN_DATA) .build())
.withDefaultAlgorithms())
.withPrimaryUserId("should@throw.ex") .withPrimaryUserId("should@throw.ex")
.withoutPassphrase().build()); .withoutPassphrase().build());
} }

View file

@ -41,12 +41,11 @@ public class GenerateEllipticCurveKeyTest {
public void generateEllipticCurveKeys(ImplementationFactory implementationFactory) throws InvalidAlgorithmParameterException, NoSuchAlgorithmException, PGPException, IOException { public void generateEllipticCurveKeys(ImplementationFactory implementationFactory) throws InvalidAlgorithmParameterException, NoSuchAlgorithmException, PGPException, IOException {
ImplementationFactory.setFactoryImplementation(implementationFactory); ImplementationFactory.setFactoryImplementation(implementationFactory);
PGPSecretKeyRing keyRing = PGPainless.generateKeyRing() PGPSecretKeyRing keyRing = PGPainless.generateKeyRing()
.withSubKey(KeySpec.getBuilder(KeyType.XDH(XDHSpec._X25519)) .withSubKey(KeySpec.getBuilder(KeyType.XDH(XDHSpec._X25519), KeyFlag.ENCRYPT_COMMS).build())
.withKeyFlags(KeyFlag.ENCRYPT_COMMS) .withPrimaryKey(KeySpec.getBuilder(
.withDefaultAlgorithms()) KeyType.EDDSA(EdDSACurve._Ed25519),
.withPrimaryKey(KeySpec.getBuilder(KeyType.EDDSA(EdDSACurve._Ed25519)) KeyFlag.CERTIFY_OTHER, KeyFlag.SIGN_DATA)
.withKeyFlags(KeyFlag.CERTIFY_OTHER, KeyFlag.SIGN_DATA) .build())
.withDefaultAlgorithms())
.withPrimaryUserId(UserId.onlyEmail("alice@wonderland.lit").toString()) .withPrimaryUserId(UserId.onlyEmail("alice@wonderland.lit").toString())
.withoutPassphrase() .withoutPassphrase()
.build(); .build();

View file

@ -47,9 +47,10 @@ public class GenerateKeyWithAdditionalUserIdTest {
ImplementationFactory.setFactoryImplementation(implementationFactory); ImplementationFactory.setFactoryImplementation(implementationFactory);
Date expiration = new Date(DateUtil.now().getTime() + 60 * 1000); Date expiration = new Date(DateUtil.now().getTime() + 60 * 1000);
PGPSecretKeyRing secretKeys = PGPainless.generateKeyRing() PGPSecretKeyRing secretKeys = PGPainless.generateKeyRing()
.withPrimaryKey(KeySpec.getBuilder(KeyType.RSA(RsaLength._3072)) .withPrimaryKey(KeySpec.getBuilder(
.withKeyFlags(KeyFlag.CERTIFY_OTHER, KeyFlag.SIGN_DATA, KeyFlag.ENCRYPT_COMMS) KeyType.RSA(RsaLength._3072),
.withDefaultAlgorithms()) KeyFlag.CERTIFY_OTHER, KeyFlag.SIGN_DATA, KeyFlag.ENCRYPT_COMMS)
.build())
.withPrimaryUserId(UserId.onlyEmail("primary@user.id")) .withPrimaryUserId(UserId.onlyEmail("primary@user.id"))
.withAdditionalUserId(UserId.onlyEmail("additional@user.id")) .withAdditionalUserId(UserId.onlyEmail("additional@user.id"))
.withAdditionalUserId(UserId.onlyEmail("additional2@user.id")) .withAdditionalUserId(UserId.onlyEmail("additional2@user.id"))

View file

@ -46,9 +46,10 @@ public class GenerateWithEmptyPassphrase {
ImplementationFactory.setFactoryImplementation(implementationFactory); ImplementationFactory.setFactoryImplementation(implementationFactory);
assertNotNull(PGPainless.generateKeyRing() assertNotNull(PGPainless.generateKeyRing()
.withPrimaryKey(KeySpec.getBuilder(KeyType.RSA(RsaLength._3072)) .withPrimaryKey(KeySpec.getBuilder(
.withKeyFlags(KeyFlag.CERTIFY_OTHER, KeyFlag.SIGN_DATA, KeyFlag.ENCRYPT_COMMS) KeyType.RSA(RsaLength._3072),
.withDefaultAlgorithms()) KeyFlag.CERTIFY_OTHER, KeyFlag.SIGN_DATA, KeyFlag.ENCRYPT_COMMS)
.build())
.withPrimaryUserId("primary@user.id") .withPrimaryUserId("primary@user.id")
.withPassphrase(Passphrase.emptyPassphrase()) .withPassphrase(Passphrase.emptyPassphrase())
.build()); .build());

View file

@ -19,7 +19,6 @@ import static org.junit.jupiter.api.Assertions.assertThrows;
import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource; import org.junit.jupiter.params.provider.MethodSource;
import org.pgpainless.PGPainless;
import org.pgpainless.algorithm.KeyFlag; import org.pgpainless.algorithm.KeyFlag;
import org.pgpainless.implementation.ImplementationFactory; import org.pgpainless.implementation.ImplementationFactory;
import org.pgpainless.key.generation.type.KeyType; import org.pgpainless.key.generation.type.KeyType;
@ -32,29 +31,19 @@ public class IllegalKeyFlagsTest {
@MethodSource("org.pgpainless.util.TestImplementationFactoryProvider#provideImplementationFactories") @MethodSource("org.pgpainless.util.TestImplementationFactoryProvider#provideImplementationFactories")
public void testKeyCannotCarryFlagsTest(ImplementationFactory implementationFactory) { public void testKeyCannotCarryFlagsTest(ImplementationFactory implementationFactory) {
ImplementationFactory.setFactoryImplementation(implementationFactory); ImplementationFactory.setFactoryImplementation(implementationFactory);
assertThrows(IllegalArgumentException.class, () -> PGPainless.generateKeyRing() assertThrows(IllegalArgumentException.class, () -> KeySpec.getBuilder(
.withPrimaryKey(KeySpec.getBuilder(KeyType.XDH(XDHSpec._X25519)) KeyType.XDH(XDHSpec._X25519), KeyFlag.SIGN_DATA));
.withKeyFlags(KeyFlag.SIGN_DATA) // <- should throw
.withDefaultAlgorithms()));
assertThrows(IllegalArgumentException.class, () -> PGPainless.generateKeyRing() assertThrows(IllegalArgumentException.class, () -> KeySpec.getBuilder(
.withPrimaryKey(KeySpec.getBuilder(KeyType.XDH(XDHSpec._X25519)) KeyType.XDH(XDHSpec._X25519), KeyFlag.CERTIFY_OTHER));
.withKeyFlags(KeyFlag.CERTIFY_OTHER) // <- should throw
.withDefaultAlgorithms()));
assertThrows(IllegalArgumentException.class, () -> PGPainless.generateKeyRing() assertThrows(IllegalArgumentException.class, () -> KeySpec.getBuilder(
.withPrimaryKey(KeySpec.getBuilder(KeyType.XDH(XDHSpec._X25519)) KeyType.XDH(XDHSpec._X25519), KeyFlag.AUTHENTICATION));
.withKeyFlags(KeyFlag.AUTHENTICATION) // <- should throw
.withDefaultAlgorithms()));
assertThrows(IllegalArgumentException.class, () -> PGPainless.generateKeyRing() assertThrows(IllegalArgumentException.class, () -> KeySpec.getBuilder(
.withPrimaryKey(KeySpec.getBuilder(KeyType.EDDSA(EdDSACurve._Ed25519)) KeyType.EDDSA(EdDSACurve._Ed25519), KeyFlag.ENCRYPT_COMMS));
.withKeyFlags(KeyFlag.ENCRYPT_COMMS) // <- should throw
.withDefaultAlgorithms()));
assertThrows(IllegalArgumentException.class, () -> PGPainless.generateKeyRing() assertThrows(IllegalArgumentException.class, () -> KeySpec.getBuilder(
.withPrimaryKey(KeySpec.getBuilder(KeyType.EDDSA(EdDSACurve._Ed25519)) KeyType.EDDSA(EdDSACurve._Ed25519), KeyFlag.ENCRYPT_STORAGE));
.withKeyFlags(KeyFlag.ENCRYPT_STORAGE) // <- should throw as well
.withDefaultAlgorithms()));
} }
} }

View file

@ -221,9 +221,14 @@ public class KeyRingInfoTest {
ImplementationFactory.setFactoryImplementation(implementationFactory); ImplementationFactory.setFactoryImplementation(implementationFactory);
PGPSecretKeyRing secretKeys = PGPainless.generateKeyRing() PGPSecretKeyRing secretKeys = PGPainless.generateKeyRing()
.withSubKey(KeySpec.getBuilder(KeyType.ECDH(EllipticCurve._BRAINPOOLP384R1)).withKeyFlags(KeyFlag.ENCRYPT_STORAGE).withDefaultAlgorithms()) .withSubKey(KeySpec.getBuilder(
.withSubKey(KeySpec.getBuilder(KeyType.ECDSA(EllipticCurve._BRAINPOOLP384R1)).withKeyFlags(KeyFlag.SIGN_DATA).withDefaultAlgorithms()) KeyType.ECDH(EllipticCurve._BRAINPOOLP384R1),
.withPrimaryKey(KeySpec.getBuilder(KeyType.EDDSA(EdDSACurve._Ed25519)).withKeyFlags(KeyFlag.CERTIFY_OTHER).withDefaultAlgorithms()) KeyFlag.ENCRYPT_STORAGE).build())
.withSubKey(KeySpec.getBuilder(
KeyType.ECDSA(EllipticCurve._BRAINPOOLP384R1), KeyFlag.SIGN_DATA)
.build())
.withPrimaryKey(KeySpec.getBuilder(
KeyType.EDDSA(EdDSACurve._Ed25519), KeyFlag.CERTIFY_OTHER).build())
.withPrimaryUserId(UserId.newBuilder().withName("Alice").withEmail("alice@pgpainless.org").build()) .withPrimaryUserId(UserId.newBuilder().withName("Alice").withEmail("alice@pgpainless.org").build())
.withoutPassphrase() .withoutPassphrase()
.build(); .build();

View file

@ -51,12 +51,13 @@ public class UserIdRevocationTest {
@Test @Test
public void testRevocationWithoutRevocationAttributes() throws PGPException, InvalidAlgorithmParameterException, NoSuchAlgorithmException { public void testRevocationWithoutRevocationAttributes() throws PGPException, InvalidAlgorithmParameterException, NoSuchAlgorithmException {
PGPSecretKeyRing secretKeys = PGPainless.generateKeyRing() PGPSecretKeyRing secretKeys = PGPainless.generateKeyRing()
.withSubKey(KeySpec.getBuilder(KeyType.XDH(XDHSpec._X25519)) .withSubKey(KeySpec.getBuilder(
.withKeyFlags(KeyFlag.ENCRYPT_COMMS) KeyType.XDH(XDHSpec._X25519), KeyFlag.ENCRYPT_COMMS)
.withDefaultAlgorithms()) .build())
.withPrimaryKey(KeySpec.getBuilder(KeyType.EDDSA(EdDSACurve._Ed25519)) .withPrimaryKey(KeySpec.getBuilder(
.withKeyFlags(KeyFlag.SIGN_DATA, KeyFlag.CERTIFY_OTHER) KeyType.EDDSA(EdDSACurve._Ed25519),
.withDefaultAlgorithms()) KeyFlag.SIGN_DATA, KeyFlag.CERTIFY_OTHER)
.build())
.withPrimaryUserId("primary@key.id") .withPrimaryUserId("primary@key.id")
.withAdditionalUserId("secondary@key.id") .withAdditionalUserId("secondary@key.id")
.withoutPassphrase() .withoutPassphrase()
@ -91,12 +92,12 @@ public class UserIdRevocationTest {
@Test @Test
public void testRevocationWithRevocationReason() throws InvalidAlgorithmParameterException, NoSuchAlgorithmException, PGPException { public void testRevocationWithRevocationReason() throws InvalidAlgorithmParameterException, NoSuchAlgorithmException, PGPException {
PGPSecretKeyRing secretKeys = PGPainless.generateKeyRing() PGPSecretKeyRing secretKeys = PGPainless.generateKeyRing()
.withSubKey(KeySpec.getBuilder(KeyType.XDH(XDHSpec._X25519)) .withSubKey(KeySpec.getBuilder(KeyType.XDH(XDHSpec._X25519), KeyFlag.ENCRYPT_COMMS)
.withKeyFlags(KeyFlag.ENCRYPT_COMMS) .build())
.withDefaultAlgorithms()) .withPrimaryKey(KeySpec.getBuilder(
.withPrimaryKey(KeySpec.getBuilder(KeyType.EDDSA(EdDSACurve._Ed25519)) KeyType.EDDSA(EdDSACurve._Ed25519),
.withKeyFlags(KeyFlag.SIGN_DATA, KeyFlag.CERTIFY_OTHER) KeyFlag.SIGN_DATA, KeyFlag.CERTIFY_OTHER)
.withDefaultAlgorithms()) .build())
.withPrimaryUserId("primary@key.id") .withPrimaryUserId("primary@key.id")
.withAdditionalUserId("secondary@key.id") .withAdditionalUserId("secondary@key.id")
.withoutPassphrase() .withoutPassphrase()

View file

@ -61,9 +61,7 @@ public class AddSubKeyTest {
secretKeys = PGPainless.modifyKeyRing(secretKeys) secretKeys = PGPainless.modifyKeyRing(secretKeys)
.addSubKey( .addSubKey(
KeySpec.getBuilder(ECDSA.fromCurve(EllipticCurve._P256)) KeySpec.getBuilder(ECDSA.fromCurve(EllipticCurve._P256), KeyFlag.SIGN_DATA).build(),
.withKeyFlags(KeyFlag.SIGN_DATA)
.withDefaultAlgorithms(),
Passphrase.fromPassword("subKeyPassphrase"), Passphrase.fromPassword("subKeyPassphrase"),
PasswordBasedSecretKeyRingProtector.forKey(secretKeys, Passphrase.fromPassword("password123"))) PasswordBasedSecretKeyRingProtector.forKey(secretKeys, Passphrase.fromPassword("password123")))
.done(); .done();

View file

@ -89,14 +89,14 @@ public class PolicyTest {
@Test @Test
public void testAcceptableSymmetricKeyDecryptionAlgorithm() { public void testAcceptableSymmetricKeyDecryptionAlgorithm() {
assertTrue(policy.getSymmetricKeyDecryptionAlgoritmPolicy().isAcceptable(SymmetricKeyAlgorithm.BLOWFISH)); assertTrue(policy.getSymmetricKeyDecryptionAlgorithmPolicy().isAcceptable(SymmetricKeyAlgorithm.BLOWFISH));
assertTrue(policy.getSymmetricKeyDecryptionAlgoritmPolicy().isAcceptable(SymmetricKeyAlgorithm.BLOWFISH.getAlgorithmId())); assertTrue(policy.getSymmetricKeyDecryptionAlgorithmPolicy().isAcceptable(SymmetricKeyAlgorithm.BLOWFISH.getAlgorithmId()));
} }
@Test @Test
public void testUnAcceptableSymmetricKeyDecryptionAlgorithm() { public void testUnAcceptableSymmetricKeyDecryptionAlgorithm() {
assertFalse(policy.getSymmetricKeyDecryptionAlgoritmPolicy().isAcceptable(SymmetricKeyAlgorithm.CAMELLIA_128)); assertFalse(policy.getSymmetricKeyDecryptionAlgorithmPolicy().isAcceptable(SymmetricKeyAlgorithm.CAMELLIA_128));
assertFalse(policy.getSymmetricKeyDecryptionAlgoritmPolicy().isAcceptable(SymmetricKeyAlgorithm.CAMELLIA_128.getAlgorithmId())); assertFalse(policy.getSymmetricKeyDecryptionAlgorithmPolicy().isAcceptable(SymmetricKeyAlgorithm.CAMELLIA_128.getAlgorithmId()));
} }
@Test @Test

View file

@ -47,12 +47,11 @@ public class BCUtilTest {
throws PGPException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, throws PGPException, NoSuchAlgorithmException, InvalidAlgorithmParameterException,
IOException { IOException {
PGPSecretKeyRing sec = PGPainless.generateKeyRing() PGPSecretKeyRing sec = PGPainless.generateKeyRing()
.withSubKey(KeySpec.getBuilder(KeyType.RSA(RsaLength._3072)) .withSubKey(KeySpec.getBuilder(KeyType.RSA(RsaLength._3072), KeyFlag.ENCRYPT_COMMS).build())
.withKeyFlags(KeyFlag.ENCRYPT_COMMS) .withPrimaryKey(KeySpec.getBuilder(
.withDefaultAlgorithms()) KeyType.RSA(RsaLength._3072),
.withPrimaryKey(KeySpec.getBuilder(KeyType.RSA(RsaLength._3072)) KeyFlag.CERTIFY_OTHER, KeyFlag.SIGN_DATA)
.withKeyFlags(KeyFlag.CERTIFY_OTHER, KeyFlag.SIGN_DATA) .build())
.withDefaultAlgorithms())
.withPrimaryUserId("donald@duck.tails").withoutPassphrase().build(); .withPrimaryUserId("donald@duck.tails").withoutPassphrase().build();
PGPPublicKeyRing pub = KeyRingUtils.publicKeyRingFrom(sec); PGPPublicKeyRing pub = KeyRingUtils.publicKeyRingFrom(sec);

View file

@ -41,15 +41,12 @@ public class GuessPreferredHashAlgorithmTest {
@Test @Test
public void guessPreferredHashAlgorithmsAssumesHashAlgoUsedBySelfSig() throws InvalidAlgorithmParameterException, NoSuchAlgorithmException, PGPException, IOException { public void guessPreferredHashAlgorithmsAssumesHashAlgoUsedBySelfSig() throws InvalidAlgorithmParameterException, NoSuchAlgorithmException, PGPException, IOException {
PGPSecretKeyRing secretKeys = PGPainless.generateKeyRing() PGPSecretKeyRing secretKeys = PGPainless.generateKeyRing()
.withPrimaryKey(KeySpec.getBuilder(KeyType.EDDSA(EdDSACurve._Ed25519)) .withPrimaryKey(KeySpec.getBuilder(KeyType.EDDSA(EdDSACurve._Ed25519),
.withKeyFlags(KeyFlag.CERTIFY_OTHER, KeyFlag.SIGN_DATA) KeyFlag.CERTIFY_OTHER, KeyFlag.SIGN_DATA)
.withDetailedConfiguration() .overridePreferredHashAlgorithms(new HashAlgorithm[] {})
// Do not specify preferred algorithms .overridePreferredSymmetricKeyAlgorithms(new SymmetricKeyAlgorithm[] {})
.withPreferredSymmetricAlgorithms(new SymmetricKeyAlgorithm[] {}) .overridePreferredCompressionAlgorithms(new CompressionAlgorithm[] {})
.withPreferredHashAlgorithms(new HashAlgorithm[] {}) .build())
.withPreferredCompressionAlgorithms(new CompressionAlgorithm[] {})
.done())
.withPrimaryUserId("test@test.test") .withPrimaryUserId("test@test.test")
.withoutPassphrase() .withoutPassphrase()
.build(); .build();

View file

@ -38,12 +38,12 @@ public class TestEncryptCommsStorageFlagsDifferentiated {
@Test @Test
public void testThatEncryptionDifferentiatesBetweenPurposeKeyFlags() throws InvalidAlgorithmParameterException, NoSuchAlgorithmException, PGPException, IOException { public void testThatEncryptionDifferentiatesBetweenPurposeKeyFlags() throws InvalidAlgorithmParameterException, NoSuchAlgorithmException, PGPException, IOException {
PGPSecretKeyRing secretKeys = PGPainless.generateKeyRing() PGPSecretKeyRing secretKeys = PGPainless.generateKeyRing()
.withPrimaryKey(KeySpec.getBuilder(KeyType.RSA(RsaLength._3072)) .withPrimaryKey(KeySpec.getBuilder(
.withKeyFlags(KeyFlag.CERTIFY_OTHER, KeyType.RSA(RsaLength._3072),
KeyFlag.CERTIFY_OTHER,
KeyFlag.SIGN_DATA, KeyFlag.SIGN_DATA,
KeyFlag.ENCRYPT_STORAGE // no ENCRYPT_COMMS KeyFlag.ENCRYPT_STORAGE // no ENCRYPT_COMMS
) ).build())
.withDefaultAlgorithms())
.withPrimaryUserId("cannot@encrypt.comms") .withPrimaryUserId("cannot@encrypt.comms")
.withoutPassphrase() .withoutPassphrase()
.build(); .build();