mirror of
https://github.com/pgpainless/pgpainless.git
synced 2025-12-10 14:21:09 +01:00
Simplify KeySpecBuilder
This commit is contained in:
parent
5683ee205e
commit
21f424551b
23 changed files with 240 additions and 336 deletions
|
|
@ -384,7 +384,7 @@ public final class DecryptionStreamFactory {
|
|||
}
|
||||
|
||||
private void throwIfAlgorithmIsRejected(SymmetricKeyAlgorithm algorithm) throws UnacceptableAlgorithmException {
|
||||
if (!PGPainless.getPolicy().getSymmetricKeyDecryptionAlgoritmPolicy().isAcceptable(algorithm)) {
|
||||
if (!PGPainless.getPolicy().getSymmetricKeyDecryptionAlgorithmPolicy().isAcceptable(algorithm)) {
|
||||
throw new UnacceptableAlgorithmException("Data is "
|
||||
+ (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().");
|
||||
|
|
|
|||
|
|
@ -127,10 +127,9 @@ public class KeyRingBuilder implements KeyRingBuilderInterface {
|
|||
public PGPSecretKeyRing simpleRsaKeyRing(@Nonnull String userId, @Nonnull RsaLength length, String password)
|
||||
throws PGPException, NoSuchAlgorithmException, InvalidAlgorithmParameterException {
|
||||
WithAdditionalUserIdOrPassphrase builder = this
|
||||
.withPrimaryKey(
|
||||
KeySpec.getBuilder(KeyType.RSA(length))
|
||||
.withKeyFlags(KeyFlag.CERTIFY_OTHER, KeyFlag.SIGN_DATA, KeyFlag.ENCRYPT_COMMS)
|
||||
.withDefaultAlgorithms())
|
||||
.withPrimaryKey(KeySpec
|
||||
.getBuilder(KeyType.RSA(length), KeyFlag.CERTIFY_OTHER, KeyFlag.SIGN_DATA, KeyFlag.ENCRYPT_COMMS)
|
||||
.build())
|
||||
.withPrimaryUserId(userId);
|
||||
|
||||
if (password == null) {
|
||||
|
|
@ -197,13 +196,11 @@ public class KeyRingBuilder implements KeyRingBuilderInterface {
|
|||
throws PGPException, NoSuchAlgorithmException, InvalidAlgorithmParameterException {
|
||||
WithAdditionalUserIdOrPassphrase builder = this
|
||||
.withSubKey(
|
||||
KeySpec.getBuilder(KeyType.XDH(XDHSpec._X25519))
|
||||
.withKeyFlags(KeyFlag.ENCRYPT_STORAGE, KeyFlag.ENCRYPT_COMMS)
|
||||
.withDefaultAlgorithms())
|
||||
KeySpec.getBuilder(KeyType.XDH(XDHSpec._X25519), KeyFlag.ENCRYPT_STORAGE, KeyFlag.ENCRYPT_COMMS)
|
||||
.build())
|
||||
.withPrimaryKey(
|
||||
KeySpec.getBuilder(KeyType.EDDSA(EdDSACurve._Ed25519))
|
||||
.withKeyFlags(KeyFlag.CERTIFY_OTHER, KeyFlag.SIGN_DATA)
|
||||
.withDefaultAlgorithms())
|
||||
KeySpec.getBuilder(KeyType.EDDSA(EdDSACurve._Ed25519), KeyFlag.CERTIFY_OTHER, KeyFlag.SIGN_DATA)
|
||||
.build())
|
||||
.withPrimaryUserId(userId);
|
||||
|
||||
if (password == null) {
|
||||
|
|
@ -225,17 +222,14 @@ public class KeyRingBuilder implements KeyRingBuilderInterface {
|
|||
throws InvalidAlgorithmParameterException, NoSuchAlgorithmException, PGPException {
|
||||
WithAdditionalUserIdOrPassphrase builder = this
|
||||
.withSubKey(
|
||||
KeySpec.getBuilder(KeyType.XDH(XDHSpec._X25519))
|
||||
.withKeyFlags(KeyFlag.ENCRYPT_STORAGE, KeyFlag.ENCRYPT_COMMS)
|
||||
.withDefaultAlgorithms())
|
||||
KeySpec.getBuilder(KeyType.XDH(XDHSpec._X25519), KeyFlag.ENCRYPT_STORAGE, KeyFlag.ENCRYPT_COMMS)
|
||||
.build())
|
||||
.withSubKey(
|
||||
KeySpec.getBuilder(KeyType.EDDSA(EdDSACurve._Ed25519))
|
||||
.withKeyFlags(KeyFlag.SIGN_DATA)
|
||||
.withDefaultAlgorithms())
|
||||
KeySpec.getBuilder(KeyType.EDDSA(EdDSACurve._Ed25519), KeyFlag.SIGN_DATA)
|
||||
.build())
|
||||
.withPrimaryKey(
|
||||
KeySpec.getBuilder(KeyType.EDDSA(EdDSACurve._Ed25519))
|
||||
.withKeyFlags(KeyFlag.CERTIFY_OTHER)
|
||||
.withDefaultAlgorithms())
|
||||
KeySpec.getBuilder(KeyType.EDDSA(EdDSACurve._Ed25519), KeyFlag.CERTIFY_OTHER)
|
||||
.build())
|
||||
.withPrimaryUserId(userId);
|
||||
|
||||
if (password == null) {
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import javax.annotation.Nullable;
|
|||
|
||||
import org.bouncycastle.openpgp.PGPSignatureSubpacketGenerator;
|
||||
import org.bouncycastle.openpgp.PGPSignatureSubpacketVector;
|
||||
import org.pgpainless.algorithm.KeyFlag;
|
||||
import org.pgpainless.key.generation.type.KeyType;
|
||||
|
||||
public class KeySpec {
|
||||
|
|
@ -54,7 +55,7 @@ public class KeySpec {
|
|||
return inheritedSubPackets;
|
||||
}
|
||||
|
||||
public static KeySpecBuilder getBuilder(KeyType type) {
|
||||
return new KeySpecBuilder(type);
|
||||
public static KeySpecBuilder getBuilder(KeyType type, KeyFlag... flags) {
|
||||
return new KeySpecBuilder(type, flags);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,10 +15,14 @@
|
|||
*/
|
||||
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 org.bouncycastle.bcpg.sig.Features;
|
||||
import org.bouncycastle.openpgp.PGPSignatureSubpacketGenerator;
|
||||
import org.pgpainless.PGPainless;
|
||||
import org.pgpainless.algorithm.AlgorithmSuite;
|
||||
import org.pgpainless.algorithm.CompressionAlgorithm;
|
||||
import org.pgpainless.algorithm.Feature;
|
||||
|
|
@ -30,20 +34,83 @@ import org.pgpainless.key.generation.type.KeyType;
|
|||
public class KeySpecBuilder implements KeySpecBuilderInterface {
|
||||
|
||||
private final KeyType type;
|
||||
private final KeyFlag[] keyFlags;
|
||||
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.keyFlags = flags;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WithDetailedConfiguration withKeyFlags(@Nonnull KeyFlag... flags) {
|
||||
assureKeyCanCarryFlags(flags);
|
||||
this.hashedSubPackets.setKeyFlags(false, KeyFlag.toBitmask(flags));
|
||||
return new WithDetailedConfigurationImpl();
|
||||
public KeySpecBuilder overridePreferredCompressionAlgorithms(@Nonnull CompressionAlgorithm... compressionAlgorithms) {
|
||||
this.preferredCompressionAlgorithms = new LinkedHashSet<>(Arrays.asList(compressionAlgorithms));
|
||||
return this;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
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.");
|
||||
}
|
||||
}
|
||||
|
||||
@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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,55 +18,16 @@ package org.pgpainless.key.generation;
|
|||
import javax.annotation.Nonnull;
|
||||
|
||||
import org.pgpainless.algorithm.CompressionAlgorithm;
|
||||
import org.pgpainless.algorithm.Feature;
|
||||
import org.pgpainless.algorithm.HashAlgorithm;
|
||||
import org.pgpainless.algorithm.KeyFlag;
|
||||
import org.pgpainless.algorithm.SymmetricKeyAlgorithm;
|
||||
|
||||
public interface KeySpecBuilderInterface {
|
||||
|
||||
WithDetailedConfiguration withKeyFlags(@Nonnull KeyFlag... flags);
|
||||
KeySpecBuilder overridePreferredCompressionAlgorithms(@Nonnull CompressionAlgorithm... compressionAlgorithms);
|
||||
|
||||
KeySpec withInheritedSubPackets();
|
||||
KeySpecBuilder overridePreferredHashAlgorithms(@Nonnull HashAlgorithm... preferredHashAlgorithms);
|
||||
|
||||
interface WithDetailedConfiguration {
|
||||
|
||||
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();
|
||||
}
|
||||
KeySpecBuilder overridePreferredSymmetricKeyAlgorithms(@Nonnull SymmetricKeyAlgorithm... preferredSymmetricKeyAlgorithms);
|
||||
|
||||
KeySpec build();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,6 +21,9 @@ import java.util.EnumMap;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
import org.pgpainless.algorithm.AlgorithmSuite;
|
||||
import org.pgpainless.algorithm.CompressionAlgorithm;
|
||||
import org.pgpainless.algorithm.HashAlgorithm;
|
||||
import org.pgpainless.algorithm.PublicKeyAlgorithm;
|
||||
|
|
@ -48,6 +51,8 @@ public final class Policy {
|
|||
PublicKeyAlgorithmPolicy.defaultPublicKeyAlgorithmPolicy();
|
||||
private final NotationRegistry notationRegistry = new NotationRegistry();
|
||||
|
||||
private AlgorithmSuite keyGenerationAlgorithmSuite = AlgorithmSuite.getDefaultAlgorithmSuite();
|
||||
|
||||
Policy() {
|
||||
}
|
||||
|
||||
|
|
@ -122,7 +127,7 @@ public final class Policy {
|
|||
*
|
||||
* @return symmetric algorithm policy for decryption
|
||||
*/
|
||||
public SymmetricKeyAlgorithmPolicy getSymmetricKeyDecryptionAlgoritmPolicy() {
|
||||
public SymmetricKeyAlgorithmPolicy getSymmetricKeyDecryptionAlgorithmPolicy() {
|
||||
return symmetricKeyDecryptionAlgorithmPolicy;
|
||||
}
|
||||
|
||||
|
|
@ -459,4 +464,21 @@ public final class Policy {
|
|||
public NotationRegistry getNotationRegistry() {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue