Simplify Key Generator API and allow EC keys to be generated

This commit is contained in:
Paul Schaub 2018-06-04 14:50:09 +02:00
parent 22eb8f487c
commit ebb06494dd
Signed by: vanitasvitae
GPG Key ID: 62BEE9264BF17311
33 changed files with 443 additions and 301 deletions

View File

@ -1,5 +1,15 @@
plugins {
id 'java'
id 'ru.vyarus.animalsniffer' version '1.4.3'
}
apply plugin: 'ru.vyarus.animalsniffer'
dependencies {
signature "net.sf.androidscents.signature:android-api-level-9:2.3.1_r2@signature"
}
animalsniffer {
sourceSets = [sourceSets.main]
}
group 'de.vanitasvitae.crypto'

View File

@ -1,5 +1,6 @@
#Sat Jun 02 23:06:04 CEST 2018
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip

View File

@ -1,5 +0,0 @@
package de.vanitasvitae.crypto.pgpainless;
public class EncryptionBuilder {
}

View File

@ -1,15 +1,11 @@
package de.vanitasvitae.crypto.pgpainless;
import java.io.IOException;
import java.security.InvalidAlgorithmParameterException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.Security;
import java.util.Base64;
import de.vanitasvitae.crypto.pgpainless.key.algorithm.KeyFlag;
import de.vanitasvitae.crypto.pgpainless.key.generation.KeySpec;
import de.vanitasvitae.crypto.pgpainless.key.generation.type.DSA;
import de.vanitasvitae.crypto.pgpainless.key.generation.type.RSA_GENERAL;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.openpgp.PGPException;
import org.bouncycastle.openpgp.PGPSecretKeyRing;
@ -17,28 +13,13 @@ import org.bouncycastle.openpgp.PGPSecretKeyRing;
public class Main {
public static void main(String[] args)
throws NoSuchAlgorithmException, PGPException, NoSuchProviderException, IOException {
throws NoSuchAlgorithmException, PGPException, NoSuchProviderException, IOException,
InvalidAlgorithmParameterException {
Security.addProvider(new BouncyCastleProvider());
PGPSecretKeyRing secretKeys = PGPainless.generateKeyRing()
.generateCompositeKeyRing()
.withSubKey(
KeySpec.getBuilder()
.ofType(RSA_GENERAL._4096)
.withKeyFlags(KeyFlag.ENCRYPT_COMMS, KeyFlag.ENCRYPT_STORAGE)
.withStandardConfiguration())
.done()
.withCertificationKeyType(
KeySpec.getBuilder()
.ofType(DSA._3072)
.withKeyFlags(KeyFlag.SIGN_DATA)
.withStandardConfiguration())
.withPrimaryUserId("Test123")
.done()
.withoutPassphrase()
.build();
.simpleEcKeyRing("elliptic@cur.ve");
byte[] base64 = Base64.getEncoder().encode(secretKeys.getEncoded());
System.out.println(new String(base64));
//System.out.println(Base64.getEncoder().encodeToString(secretKeys.getEncoded()));
}
}

View File

@ -1,5 +1,7 @@
package de.vanitasvitae.crypto.pgpainless;
import de.vanitasvitae.crypto.pgpainless.decryption_verification.DecryptionBuilder;
import de.vanitasvitae.crypto.pgpainless.encryption_signing.EncryptionBuilder;
import de.vanitasvitae.crypto.pgpainless.key.generation.KeyRingBuilder;
public class PGPainless {
@ -7,4 +9,13 @@ public class PGPainless {
public static KeyRingBuilder generateKeyRing() {
return new KeyRingBuilder();
}
public static EncryptionBuilder createEncryptor() {
return new EncryptionBuilder();
}
public static DecryptionBuilder createDecryptor() {
return new DecryptionBuilder();
}
}

View File

@ -1,12 +1,10 @@
package de.vanitasvitae.crypto.pgpainless.key.algorithm;
package de.vanitasvitae.crypto.pgpainless.algorithm;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import com.sun.istack.internal.NotNull;
public class AlgorithmSuite {
private static AlgorithmSuite defaultAlgorithmSuite = new AlgorithmSuite(
@ -18,8 +16,7 @@ public class AlgorithmSuite {
HashAlgorithm.SHA512,
HashAlgorithm.SHA384,
HashAlgorithm.SHA256,
HashAlgorithm.SHA224,
HashAlgorithm.SHA1),
HashAlgorithm.SHA224),
Arrays.asList(
CompressionAlgorithm.ZLIB,
CompressionAlgorithm.BZIP2,
@ -31,15 +28,15 @@ public class AlgorithmSuite {
private List<HashAlgorithm> hashAlgorithms;
private List<CompressionAlgorithm> compressionAlgorithms;
public AlgorithmSuite(@NotNull List<SymmetricKeyAlgorithm> symmetricKeyAlgorithms,
@NotNull List<HashAlgorithm> hashAlgorithms,
@NotNull List<CompressionAlgorithm> compressionAlgorithms) {
public AlgorithmSuite(List<SymmetricKeyAlgorithm> symmetricKeyAlgorithms,
List<HashAlgorithm> hashAlgorithms,
List<CompressionAlgorithm> compressionAlgorithms) {
this.symmetricKeyAlgorithms = Collections.unmodifiableList(symmetricKeyAlgorithms);
this.hashAlgorithms = Collections.unmodifiableList(hashAlgorithms);
this.compressionAlgorithms = Collections.unmodifiableList(compressionAlgorithms);
}
public void setSymmetricKeyAlgorithms(@NotNull List<SymmetricKeyAlgorithm> symmetricKeyAlgorithms) {
public void setSymmetricKeyAlgorithms(List<SymmetricKeyAlgorithm> symmetricKeyAlgorithms) {
this.symmetricKeyAlgorithms = symmetricKeyAlgorithms;
}
@ -55,7 +52,7 @@ public class AlgorithmSuite {
return array;
}
public void setHashAlgorithms(@NotNull List<HashAlgorithm> hashAlgorithms) {
public void setHashAlgorithms(List<HashAlgorithm> hashAlgorithms) {
this.hashAlgorithms = hashAlgorithms;
}
@ -71,7 +68,7 @@ public class AlgorithmSuite {
return array;
}
public void setCompressionAlgorithms(@NotNull List<CompressionAlgorithm> compressionAlgorithms) {
public void setCompressionAlgorithms(List<CompressionAlgorithm> compressionAlgorithms) {
this.compressionAlgorithms = compressionAlgorithms;
}

View File

@ -1,4 +1,4 @@
package de.vanitasvitae.crypto.pgpainless.key.algorithm;
package de.vanitasvitae.crypto.pgpainless.algorithm;
import java.util.HashMap;
import java.util.Map;

View File

@ -1,4 +1,4 @@
package de.vanitasvitae.crypto.pgpainless.key.algorithm;
package de.vanitasvitae.crypto.pgpainless.algorithm;
import java.util.HashMap;
import java.util.Map;

View File

@ -1,4 +1,4 @@
package de.vanitasvitae.crypto.pgpainless.key.algorithm;
package de.vanitasvitae.crypto.pgpainless.algorithm;
import java.util.HashMap;
import java.util.Map;

View File

@ -1,4 +1,4 @@
package de.vanitasvitae.crypto.pgpainless.key.algorithm;
package de.vanitasvitae.crypto.pgpainless.algorithm;
import org.bouncycastle.bcpg.sig.KeyFlags;

View File

@ -1,4 +1,4 @@
package de.vanitasvitae.crypto.pgpainless.key.algorithm;
package de.vanitasvitae.crypto.pgpainless.algorithm;
import java.util.HashMap;
import java.util.Map;

View File

@ -1,4 +1,4 @@
package de.vanitasvitae.crypto.pgpainless.key.algorithm;
package de.vanitasvitae.crypto.pgpainless.algorithm;
import java.util.HashMap;
import java.util.Map;

View File

@ -0,0 +1,5 @@
package de.vanitasvitae.crypto.pgpainless.decryption_verification;
public class DecryptionBuilder {
}

View File

@ -0,0 +1,5 @@
package de.vanitasvitae.crypto.pgpainless.encryption_signing;
public class EncryptionBuilder {
}

View File

@ -2,6 +2,7 @@ package de.vanitasvitae.crypto.pgpainless.key.generation;
import java.nio.charset.Charset;
import java.security.InvalidAlgorithmParameterException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
@ -10,9 +11,15 @@ import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import de.vanitasvitae.crypto.pgpainless.key.algorithm.KeyFlag;
import de.vanitasvitae.crypto.pgpainless.algorithm.KeyFlag;
import de.vanitasvitae.crypto.pgpainless.key.generation.type.ECDH;
import de.vanitasvitae.crypto.pgpainless.key.generation.type.ECDSA;
import de.vanitasvitae.crypto.pgpainless.key.generation.type.KeyType;
import de.vanitasvitae.crypto.pgpainless.key.generation.type.RSA_GENERAL;
import de.vanitasvitae.crypto.pgpainless.key.generation.type.curve.EllipticCurve;
import de.vanitasvitae.crypto.pgpainless.key.generation.type.length.RsaLength;
import org.bouncycastle.bcpg.HashAlgorithmTags;
import org.bouncycastle.bcpg.sig.KeyFlags;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.openpgp.PGPEncryptedData;
import org.bouncycastle.openpgp.PGPException;
@ -20,7 +27,7 @@ import org.bouncycastle.openpgp.PGPKeyPair;
import org.bouncycastle.openpgp.PGPKeyRingGenerator;
import org.bouncycastle.openpgp.PGPSecretKeyRing;
import org.bouncycastle.openpgp.PGPSignature;
import org.bouncycastle.openpgp.PGPSignatureSubpacketGenerator;
import org.bouncycastle.openpgp.PGPSignatureSubpacketVector;
import org.bouncycastle.openpgp.operator.PBESecretKeyEncryptor;
import org.bouncycastle.openpgp.operator.PGPContentSignerBuilder;
import org.bouncycastle.openpgp.operator.PGPDigestCalculator;
@ -34,78 +41,65 @@ public class KeyRingBuilder implements KeyRingBuilderInterface {
private final Charset UTF8 = Charset.forName("UTF-8");
private List<KeySpec> keySpecs = new ArrayList<>();
private List<String> userIds = new ArrayList<>();
private String userId;
private char[] passphrase;
@Override
public WithSubKeyType generateCompositeKeyRing() {
return new WithSubKeyTypeImpl();
public PGPSecretKeyRing simpleRsaKeyRing(String userId, RsaLength length)
throws PGPException, NoSuchAlgorithmException, NoSuchProviderException, InvalidAlgorithmParameterException {
return withMasterKey(
KeySpec.getBuilder()
.ofType(RSA_GENERAL.withLength(length))
.withDefaultKeyFlags()
.withDefaultAlgorithms())
.withPrimaryUserId(userId)
.withoutPassphrase()
.build();
}
public PGPSecretKeyRing simpleEcKeyRing(String userId)
throws PGPException, NoSuchAlgorithmException, NoSuchProviderException, InvalidAlgorithmParameterException {
return withSubKey(
KeySpec.getBuilder()
.ofType(ECDH.fromCurve(EllipticCurve._P256))
.withKeyFlags(KeyFlag.ENCRYPT_STORAGE, KeyFlag.ENCRYPT_COMMS)
.withDefaultAlgorithms())
.withMasterKey(
KeySpec.getBuilder()
.ofType(ECDSA.fromCurve(EllipticCurve._P256))
.withKeyFlags(KeyFlag.AUTHENTICATION, KeyFlag.CERTIFY_OTHER, KeyFlag.SIGN_DATA)
.withDefaultAlgorithms())
.withPrimaryUserId(userId)
.withoutPassphrase()
.build();
}
@Override
public WithCertificationKeyType generateSingleKeyKeyRing() {
return new WithCertificationKeyTypeImpl();
public KeyRingBuilderInterface withSubKey(KeySpec type) {
KeyRingBuilder.this.keySpecs.add(type);
return this;
}
class WithSubKeyTypeImpl implements WithSubKeyType {
@Override
public WithSubKeyType withSubKey(KeySpec type) {
KeyRingBuilder.this.keySpecs.add(type);
return this;
}
@Override
public WithCertificationKeyType done() {
return new WithCertificationKeyTypeImpl();
}
}
class WithCertificationKeyTypeImpl implements WithCertificationKeyType {
@Override
public WithPrimaryUserId withCertificationKeyType(KeySpec spec) {
if ((spec.getKeyFlags() & KeyFlag.CERTIFY_OTHER.getFlag()) == 0) {
throw new IllegalArgumentException("Certification Key MUST have KeyFlag CERTIFY_OTHER");
}
KeyRingBuilder.this.keySpecs.add(spec);
return new WithPrimaryUserIdImpl();
@Override
public WithPrimaryUserId withMasterKey(KeySpec spec) {
if ((spec.getSubpackets().getKeyFlags() & KeyFlags.CERTIFY_OTHER) == 0) {
throw new IllegalArgumentException("Certification Key MUST have KeyFlag CERTIFY_OTHER");
}
KeyRingBuilder.this.keySpecs.add(0, spec);
return new WithPrimaryUserIdImpl();
}
class WithPrimaryUserIdImpl implements WithPrimaryUserId {
@Override
public WithAdditionalUserIds withPrimaryUserId(String userId) {
KeyRingBuilder.this.userIds.add(userId);
return new WithAdditionalUserIdsImpl();
}
@Override
public WithAdditionalUserIds withPrimaryUserId(byte[] userId) {
return withPrimaryUserId(new String(userId, UTF8));
}
}
class WithAdditionalUserIdsImpl implements WithAdditionalUserIds {
@Deprecated
@Override
public WithAdditionalUserIds withAdditionalUserId(String userId) {
KeyRingBuilder.this.userIds.add(userId);
return this;
}
@Deprecated
@Override
public WithAdditionalUserIds withAdditionalUserId(byte[] userId) {
return withAdditionalUserId(new String(userId, UTF8));
}
@Override
public WithPassphrase done() {
public WithPassphrase withPrimaryUserId(String userId) {
KeyRingBuilder.this.userId = userId;
return new WithPassphraseImpl();
}
@Override
public WithPassphrase withPrimaryUserId(byte[] userId) {
return withPrimaryUserId(new String(userId, UTF8));
}
}
class WithPassphraseImpl implements WithPassphrase {
@ -130,7 +124,8 @@ public class KeyRingBuilder implements KeyRingBuilderInterface {
class BuildImpl implements Build {
@Override
public PGPSecretKeyRing build() throws NoSuchAlgorithmException, PGPException, NoSuchProviderException {
public PGPSecretKeyRing build() throws NoSuchAlgorithmException, PGPException, NoSuchProviderException,
InvalidAlgorithmParameterException {
// Hash Calculator
PGPDigestCalculator calculator = new JcaPGPDigestCalculatorProviderBuilder()
@ -147,64 +142,51 @@ public class KeyRingBuilder implements KeyRingBuilderInterface {
// First key is the Master Key
KeySpec certKeySpec = keySpecs.get(0);
KeyType certKeyType = certKeySpec.getKeyType();
keySpecs.remove(0); // Remove master key, so that we later only add sub keys.
// Remove master key, so that we later only add sub keys.
keySpecs.remove(0);
// Generate Master Key
PGPKeyPair certKey = generateKeyPair(certKeySpec);
// Signer for creating self-signature
PGPContentSignerBuilder signer = new JcaPGPContentSignerBuilder(
certKey.getPublicKey().getAlgorithm(), HashAlgorithmTags.SHA256);
certKey.getPublicKey().getAlgorithm(), HashAlgorithmTags.SHA512)
.setProvider(BouncyCastleProvider.PROVIDER_NAME);
// Mimic GnuPGs signature sub packets
PGPSignatureSubpacketGenerator hashedSubPackets = new PGPSignatureSubpacketGenerator();
// Key flags
hashedSubPackets.setKeyFlags(true, certKeySpec.getKeyFlags());
// Encryption Algorithms
hashedSubPackets.setPreferredSymmetricAlgorithms(true,
certKeySpec.getPreferredAlgorithms().getSymmetricKeyAlgorithmIds());
// Hash Algorithms
hashedSubPackets.setPreferredHashAlgorithms(true,
certKeySpec.getPreferredAlgorithms().getHashAlgorithmIds());
// Compression Algorithms
hashedSubPackets.setPreferredCompressionAlgorithms(true,
certKeySpec.getPreferredAlgorithms().getCompressionAlgorithmIds());
// Modification Detection
hashedSubPackets.setFeature(true, certKeySpec.getFeatures());
PGPSignatureSubpacketVector hashedSubPackets = certKeySpec.getSubpackets();
// Generator which the user can get the key pair from
PGPKeyRingGenerator ringGenerator = new PGPKeyRingGenerator(
PGPSignature.POSITIVE_CERTIFICATION, certKey,
userIds.get(0), calculator,
hashedSubPackets.generate(), null, signer, encryptor);
userId, calculator,
hashedSubPackets, null, signer, encryptor);
for (KeySpec subKeySpec : keySpecs) {
PGPKeyPair subKey = generateKeyPair(subKeySpec);
ringGenerator.addSubKey(subKey);
if (subKeySpec.isInheritedSubPackets()) {
ringGenerator.addSubKey(subKey);
} else {
ringGenerator.addSubKey(subKey, subKeySpec.getSubpackets(), null);
}
}
return ringGenerator.generateSecretKeyRing();
}
private PGPKeyPair generateKeyPair(KeySpec spec)
throws NoSuchProviderException, NoSuchAlgorithmException, PGPException {
throws NoSuchProviderException, NoSuchAlgorithmException, PGPException,
InvalidAlgorithmParameterException {
KeyType type = spec.getKeyType();
KeyPairGenerator certKeyGenerator = KeyPairGenerator.getInstance(
type.getName(), BouncyCastleProvider.PROVIDER_NAME);
certKeyGenerator.initialize(type.getLength());
certKeyGenerator.initialize(type.getAlgorithmSpec());
// Create raw Key Pair
KeyPair rawKeyPair = certKeyGenerator.generateKeyPair();
KeyPair keyPair = certKeyGenerator.generateKeyPair();
// Form PGP key pair
PGPKeyPair pgpKeyPair = new JcaPGPKeyPair(type.getAlgorithm().getAlgorithmId(),
rawKeyPair, new Date());
keyPair, new Date());
return pgpKeyPair;
}

View File

@ -1,5 +1,6 @@
package de.vanitasvitae.crypto.pgpainless.key.generation;
import java.security.InvalidAlgorithmParameterException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
@ -8,36 +9,15 @@ import org.bouncycastle.openpgp.PGPSecretKeyRing;
public interface KeyRingBuilderInterface {
WithSubKeyType generateCompositeKeyRing();
KeyRingBuilderInterface withSubKey(KeySpec keySpec);
WithCertificationKeyType generateSingleKeyKeyRing();
interface WithSubKeyType {
WithSubKeyType withSubKey(KeySpec keySpec);
WithCertificationKeyType done();
}
interface WithCertificationKeyType {
WithPrimaryUserId withCertificationKeyType(KeySpec keySpec);
}
WithPrimaryUserId withMasterKey(KeySpec keySpec);
interface WithPrimaryUserId {
WithAdditionalUserIds withPrimaryUserId(String userId);
WithPassphrase withPrimaryUserId(String userId);
WithAdditionalUserIds withPrimaryUserId(byte[] userId);
}
interface WithAdditionalUserIds {
WithAdditionalUserIds withAdditionalUserId(String userId);
WithAdditionalUserIds withAdditionalUserId(byte[] userId);
WithPassphrase done();
WithPassphrase withPrimaryUserId(byte[] userId);
}
@ -52,7 +32,8 @@ public interface KeyRingBuilderInterface {
interface Build {
PGPSecretKeyRing build() throws NoSuchAlgorithmException, PGPException, NoSuchProviderException;
PGPSecretKeyRing build() throws NoSuchAlgorithmException, PGPException, NoSuchProviderException,
InvalidAlgorithmParameterException;
}
}

View File

@ -1,46 +1,33 @@
package de.vanitasvitae.crypto.pgpainless.key.generation;
import java.util.Set;
import de.vanitasvitae.crypto.pgpainless.key.algorithm.AlgorithmSuite;
import de.vanitasvitae.crypto.pgpainless.key.algorithm.Feature;
import de.vanitasvitae.crypto.pgpainless.key.generation.type.KeyType;
import org.bouncycastle.openpgp.PGPSignatureSubpacketGenerator;
import org.bouncycastle.openpgp.PGPSignatureSubpacketVector;
public class KeySpec {
private final KeyType keyType;
private final int keyFlags;
private final AlgorithmSuite algorithmSuite;
private final Set<Feature> features;
private final PGPSignatureSubpacketGenerator subpacketGenerator;
private final boolean inheritedSubPackets;
KeySpec(KeyType type,
int keyFlags,
AlgorithmSuite preferredAlgorithms,
Set<Feature> features) {
PGPSignatureSubpacketGenerator subpacketGenerator,
boolean inheritedSubPackets) {
this.keyType = type;
this.keyFlags = keyFlags;
this.algorithmSuite = preferredAlgorithms;
this.features = features;
this.subpacketGenerator = subpacketGenerator;
this.inheritedSubPackets = inheritedSubPackets;
}
KeyType getKeyType() {
return keyType;
}
int getKeyFlags() {
return keyFlags;
PGPSignatureSubpacketVector getSubpackets() {
return subpacketGenerator.generate();
}
AlgorithmSuite getPreferredAlgorithms() {
return algorithmSuite;
}
byte getFeatures() {
byte val = 0;
for (Feature f : features) {
val |= f.getFeatureId();
}
return val;
boolean isInheritedSubPackets() {
return inheritedSubPackets;
}
public static KeySpecBuilder getBuilder() {

View File

@ -1,23 +1,21 @@
package de.vanitasvitae.crypto.pgpainless.key.generation;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import de.vanitasvitae.crypto.pgpainless.key.algorithm.AlgorithmSuite;
import de.vanitasvitae.crypto.pgpainless.key.algorithm.CompressionAlgorithm;
import de.vanitasvitae.crypto.pgpainless.key.algorithm.Feature;
import de.vanitasvitae.crypto.pgpainless.key.algorithm.HashAlgorithm;
import de.vanitasvitae.crypto.pgpainless.key.algorithm.KeyFlag;
import de.vanitasvitae.crypto.pgpainless.key.algorithm.SymmetricKeyAlgorithm;
import de.vanitasvitae.crypto.pgpainless.algorithm.AlgorithmSuite;
import de.vanitasvitae.crypto.pgpainless.algorithm.CompressionAlgorithm;
import de.vanitasvitae.crypto.pgpainless.algorithm.Feature;
import de.vanitasvitae.crypto.pgpainless.algorithm.HashAlgorithm;
import de.vanitasvitae.crypto.pgpainless.algorithm.KeyFlag;
import de.vanitasvitae.crypto.pgpainless.algorithm.SymmetricKeyAlgorithm;
import de.vanitasvitae.crypto.pgpainless.key.generation.type.KeyType;
import org.bouncycastle.bcpg.sig.Features;
import org.bouncycastle.openpgp.PGPSignatureSubpacketGenerator;
public class KeySpecBuilder implements KeySpecBuilderInterface {
private KeyType type;
private int keyFlags;
private AlgorithmSuite algorithmSuite = AlgorithmSuite.getDefaultAlgorithmSuite();
private Set<Feature> features = new HashSet<>();
private PGPSignatureSubpacketGenerator hashedSubPackets = new PGPSignatureSubpacketGenerator();
@Override
public WithKeyFlags ofType(KeyType type) {
@ -33,7 +31,7 @@ public class KeySpecBuilder implements KeySpecBuilderInterface {
for (KeyFlag f : flags) {
val |= f.getFlag();
}
KeySpecBuilder.this.keyFlags = val;
KeySpecBuilder.this.hashedSubPackets.setKeyFlags(false, val);
return new WithDetailedConfigurationImpl();
}
@ -46,6 +44,11 @@ public class KeySpecBuilder implements KeySpecBuilderInterface {
KeyFlag.ENCRYPT_STORAGE,
KeyFlag.AUTHENTICATION);
}
@Override
public KeySpec withInheritedSubPackets() {
return new KeySpec(type, null, true);
}
}
class WithDetailedConfigurationImpl implements WithDetailedConfiguration {
@ -57,12 +60,16 @@ public class KeySpecBuilder implements KeySpecBuilderInterface {
}
@Override
public KeySpec withStandardConfiguration() {
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.keyFlags,
KeySpecBuilder.this.algorithmSuite,
KeySpecBuilder.this.features);
KeySpecBuilder.this.hashedSubPackets,
false);
}
}
@ -70,20 +77,29 @@ public class KeySpecBuilder implements KeySpecBuilderInterface {
@Override
public WithPreferredHashAlgorithms withPreferredSymmetricAlgorithms(SymmetricKeyAlgorithm... algorithms) {
KeySpecBuilder.this.algorithmSuite.setSymmetricKeyAlgorithms(Arrays.asList(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.algorithmSuite.setSymmetricKeyAlgorithms(
AlgorithmSuite.getDefaultAlgorithmSuite().getSymmetricKeyAlgorithms());
KeySpecBuilder.this.hashedSubPackets.setPreferredSymmetricAlgorithms(false,
AlgorithmSuite.getDefaultAlgorithmSuite().getSymmetricKeyAlgorithmIds());
return new WithPreferredHashAlgorithmsImpl();
}
@Override
public WithFeatures withDefaultAlgorithms() {
KeySpecBuilder.this.algorithmSuite = AlgorithmSuite.getDefaultAlgorithmSuite();
hashedSubPackets.setPreferredSymmetricAlgorithms(false,
AlgorithmSuite.getDefaultAlgorithmSuite().getSymmetricKeyAlgorithmIds());
hashedSubPackets.setPreferredCompressionAlgorithms(false,
AlgorithmSuite.getDefaultAlgorithmSuite().getCompressionAlgorithmIds());
hashedSubPackets.setPreferredHashAlgorithms(false,
AlgorithmSuite.getDefaultAlgorithmSuite().getHashAlgorithmIds());
return new WithFeaturesImpl();
}
}
@ -92,14 +108,18 @@ public class KeySpecBuilder implements KeySpecBuilderInterface {
@Override
public WithPreferredCompressionAlgorithms withPreferredHashAlgorithms(HashAlgorithm... algorithms) {
KeySpecBuilder.this.algorithmSuite.setHashAlgorithms(Arrays.asList(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.algorithmSuite.setHashAlgorithms(
AlgorithmSuite.getDefaultAlgorithmSuite().getHashAlgorithms());
KeySpecBuilder.this.hashedSubPackets.setPreferredHashAlgorithms(false,
AlgorithmSuite.getDefaultAlgorithmSuite().getHashAlgorithmIds());
return new WithPreferredCompressionAlgorithmsImpl();
}
}
@ -108,14 +128,18 @@ public class KeySpecBuilder implements KeySpecBuilderInterface {
@Override
public WithFeatures withPreferredCompressionAlgorithms(CompressionAlgorithm... algorithms) {
KeySpecBuilder.this.algorithmSuite.setCompressionAlgorithms(Arrays.asList(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.algorithmSuite.setCompressionAlgorithms(
AlgorithmSuite.getDefaultAlgorithmSuite().getCompressionAlgorithms());
KeySpecBuilder.this.hashedSubPackets.setPreferredCompressionAlgorithms(false,
AlgorithmSuite.getDefaultAlgorithmSuite().getCompressionAlgorithmIds());
return new WithFeaturesImpl();
}
}
@ -124,7 +148,7 @@ public class KeySpecBuilder implements KeySpecBuilderInterface {
@Override
public WithFeatures withFeature(Feature feature) {
KeySpecBuilder.this.features.add(feature);
KeySpecBuilder.this.hashedSubPackets.setFeature(false, feature.getFeatureId());
return this;
}
@ -132,9 +156,8 @@ public class KeySpecBuilder implements KeySpecBuilderInterface {
public KeySpec done() {
return new KeySpec(
KeySpecBuilder.this.type,
KeySpecBuilder.this.keyFlags,
KeySpecBuilder.this.algorithmSuite,
KeySpecBuilder.this.features);
hashedSubPackets,
false);
}
}
}

View File

@ -1,11 +1,10 @@
package de.vanitasvitae.crypto.pgpainless.key.generation;
import de.vanitasvitae.crypto.pgpainless.key.algorithm.AlgorithmSuite;
import de.vanitasvitae.crypto.pgpainless.key.algorithm.CompressionAlgorithm;
import de.vanitasvitae.crypto.pgpainless.key.algorithm.Feature;
import de.vanitasvitae.crypto.pgpainless.key.algorithm.HashAlgorithm;
import de.vanitasvitae.crypto.pgpainless.key.algorithm.KeyFlag;
import de.vanitasvitae.crypto.pgpainless.key.algorithm.SymmetricKeyAlgorithm;
import de.vanitasvitae.crypto.pgpainless.algorithm.CompressionAlgorithm;
import de.vanitasvitae.crypto.pgpainless.algorithm.Feature;
import de.vanitasvitae.crypto.pgpainless.algorithm.HashAlgorithm;
import de.vanitasvitae.crypto.pgpainless.algorithm.KeyFlag;
import de.vanitasvitae.crypto.pgpainless.algorithm.SymmetricKeyAlgorithm;
import de.vanitasvitae.crypto.pgpainless.key.generation.type.KeyType;
public interface KeySpecBuilderInterface {
@ -17,13 +16,15 @@ public interface KeySpecBuilderInterface {
WithDetailedConfiguration withKeyFlags(KeyFlag... flags);
WithDetailedConfiguration withDefaultKeyFlags();
KeySpec withInheritedSubPackets();
}
interface WithDetailedConfiguration {
WithPreferredSymmetricAlgorithms withDetailedConfiguration();
KeySpec withStandardConfiguration();
KeySpec withDefaultAlgorithms();
}
interface WithPreferredSymmetricAlgorithms {

View File

@ -1,36 +0,0 @@
package de.vanitasvitae.crypto.pgpainless.key.generation.type;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import de.vanitasvitae.crypto.pgpainless.key.algorithm.PublicKeyAlgorithm;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
public enum DSA implements KeyType {
_1024(1024),
_2048(2048),
_3072(3072),
;
private final int length;
DSA(int length) {
this.length = length;
}
@Override
public int getLength() {
return length;
}
@Override
public String getName() {
return "DSA";
}
@Override
public PublicKeyAlgorithm getAlgorithm() {
return PublicKeyAlgorithm.DSA;
}
}

View File

@ -0,0 +1,35 @@
package de.vanitasvitae.crypto.pgpainless.key.generation.type;
import java.security.spec.AlgorithmParameterSpec;
import de.vanitasvitae.crypto.pgpainless.algorithm.PublicKeyAlgorithm;
import de.vanitasvitae.crypto.pgpainless.key.generation.type.curve.EllipticCurve;
import org.bouncycastle.jce.spec.ECNamedCurveGenParameterSpec;
public class ECDH implements KeyType {
private final EllipticCurve curve;
ECDH(EllipticCurve curve) {
this.curve = curve;
}
public static ECDH fromCurve(EllipticCurve curve) {
return new ECDH(curve);
}
@Override
public String getName() {
return "ECDH";
}
@Override
public PublicKeyAlgorithm getAlgorithm() {
return PublicKeyAlgorithm.ECDH;
}
@Override
public AlgorithmParameterSpec getAlgorithmSpec() {
return new ECNamedCurveGenParameterSpec(curve.getName());
}
}

View File

@ -0,0 +1,25 @@
package de.vanitasvitae.crypto.pgpainless.key.generation.type;
import de.vanitasvitae.crypto.pgpainless.algorithm.PublicKeyAlgorithm;
import de.vanitasvitae.crypto.pgpainless.key.generation.type.curve.EllipticCurve;
public class ECDSA extends ECDH {
ECDSA(EllipticCurve curve) {
super(curve);
}
public static ECDSA fromCurve(EllipticCurve curve) {
return new ECDSA(curve);
}
@Override
public String getName() {
return "ECDSA";
}
@Override
public PublicKeyAlgorithm getAlgorithm() {
return PublicKeyAlgorithm.ECDSA;
}
}

View File

@ -1,28 +1,12 @@
package de.vanitasvitae.crypto.pgpainless.key.generation.type;
import de.vanitasvitae.crypto.pgpainless.key.algorithm.PublicKeyAlgorithm;
import de.vanitasvitae.crypto.pgpainless.algorithm.PublicKeyAlgorithm;
import de.vanitasvitae.crypto.pgpainless.key.generation.type.length.ElGamalLength;
public enum ElGamal_ENCRYPT implements KeyType {
public class ElGamal_ENCRYPT extends ElGamal_GENERAL {
_1024(1024),
_2048(2048),
_3072(3072),
;
private final int length;
ElGamal_ENCRYPT(int length) {
this.length = length;
}
@Override
public int getLength() {
return length;
}
@Override
public String getName() {
return "ElGamal";
ElGamal_ENCRYPT(ElGamalLength length) {
super(length);
}
@Override

View File

@ -0,0 +1,35 @@
package de.vanitasvitae.crypto.pgpainless.key.generation.type;
import java.security.spec.AlgorithmParameterSpec;
import de.vanitasvitae.crypto.pgpainless.algorithm.PublicKeyAlgorithm;
import de.vanitasvitae.crypto.pgpainless.key.generation.type.length.ElGamalLength;
import org.bouncycastle.jce.spec.ElGamalGenParameterSpec;
public class ElGamal_GENERAL implements KeyType {
private final ElGamalLength length;
ElGamal_GENERAL(ElGamalLength length) {
this.length = length;
}
public static ElGamal_GENERAL withLength(ElGamalLength length) {
return new ElGamal_GENERAL(length);
}
@Override
public String getName() {
return "ElGamal";
}
@Override
public PublicKeyAlgorithm getAlgorithm() {
return PublicKeyAlgorithm.ELGAMAL_GENERAL;
}
@Override
public AlgorithmParameterSpec getAlgorithmSpec() {
return new ElGamalGenParameterSpec(length.getLength());
}
}

View File

@ -1,12 +1,14 @@
package de.vanitasvitae.crypto.pgpainless.key.generation.type;
import de.vanitasvitae.crypto.pgpainless.key.algorithm.PublicKeyAlgorithm;
import java.security.spec.AlgorithmParameterSpec;
import de.vanitasvitae.crypto.pgpainless.algorithm.PublicKeyAlgorithm;
public interface KeyType {
int getLength();
String getName();
PublicKeyAlgorithm getAlgorithm();
AlgorithmParameterSpec getAlgorithmSpec();
}

View File

@ -0,0 +1,16 @@
package de.vanitasvitae.crypto.pgpainless.key.generation.type;
import de.vanitasvitae.crypto.pgpainless.algorithm.PublicKeyAlgorithm;
import de.vanitasvitae.crypto.pgpainless.key.generation.type.length.RsaLength;
public class RSA_ENCRYPT extends RSA_GENERAL {
RSA_ENCRYPT(RsaLength length) {
super(length);
}
@Override
public PublicKeyAlgorithm getAlgorithm() {
return PublicKeyAlgorithm.RSA_ENCRYPT;
}
}

View File

@ -1,27 +1,21 @@
package de.vanitasvitae.crypto.pgpainless.key.generation.type;
import de.vanitasvitae.crypto.pgpainless.key.algorithm.PublicKeyAlgorithm;
import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.RSAKeyGenParameterSpec;
public enum RSA_GENERAL implements KeyType {
import de.vanitasvitae.crypto.pgpainless.algorithm.PublicKeyAlgorithm;
import de.vanitasvitae.crypto.pgpainless.key.generation.type.length.RsaLength;
@Deprecated
_1024(1024),
@Deprecated
_2048(2048),
_3072(3072),
_4096(4096),
_8192(8192),
;
public class RSA_GENERAL implements KeyType {
private final int length;
private final RsaLength length;
RSA_GENERAL(int length) {
RSA_GENERAL(RsaLength length) {
this.length = length;
}
@Override
public int getLength() {
return length;
public static RSA_GENERAL withLength(RsaLength length) {
return new RSA_GENERAL(length);
}
@Override
@ -33,4 +27,9 @@ public enum RSA_GENERAL implements KeyType {
public PublicKeyAlgorithm getAlgorithm() {
return PublicKeyAlgorithm.RSA_GENERAL;
}
@Override
public AlgorithmParameterSpec getAlgorithmSpec() {
return new RSAKeyGenParameterSpec(length.getLength(), RSAKeyGenParameterSpec.F4);
}
}

View File

@ -0,0 +1,16 @@
package de.vanitasvitae.crypto.pgpainless.key.generation.type;
import de.vanitasvitae.crypto.pgpainless.algorithm.PublicKeyAlgorithm;
import de.vanitasvitae.crypto.pgpainless.key.generation.type.length.RsaLength;
public class RSA_SIGN extends RSA_GENERAL {
RSA_SIGN(RsaLength length) {
super(length);
}
@Override
public PublicKeyAlgorithm getAlgorithm() {
return PublicKeyAlgorithm.RSA_SIGN;
}
}

View File

@ -0,0 +1,16 @@
package de.vanitasvitae.crypto.pgpainless.key.generation.type.curve;
public enum EllipticCurve {
_P256("P-256"),
;
private final String name;
EllipticCurve(String name) {
this.name = name;
}
public String getName() {
return name;
}
}

View File

@ -0,0 +1,21 @@
package de.vanitasvitae.crypto.pgpainless.key.generation.type.length;
public enum DiffieHellmanLength implements KeyLength {
_1024(1024),
_2048(2048),
_3072(3072),
;
private final int length;
DiffieHellmanLength(int length) {
this.length = length;
}
@Override
public int getLength() {
return length;
}
}

View File

@ -0,0 +1,21 @@
package de.vanitasvitae.crypto.pgpainless.key.generation.type.length;
public enum ElGamalLength implements KeyLength {
_1024(1024),
_2048(2048),
_3072(3072),
;
private final int length;
ElGamalLength(int length) {
this.length = length;
}
@Override
public int getLength() {
return length;
}
}

View File

@ -0,0 +1,6 @@
package de.vanitasvitae.crypto.pgpainless.key.generation.type.length;
public interface KeyLength {
int getLength();
}

View File

@ -0,0 +1,23 @@
package de.vanitasvitae.crypto.pgpainless.key.generation.type.length;
public enum RsaLength implements KeyLength {
@Deprecated
_1024(1024),
@Deprecated
_2048(2048),
_3072(3072),
_4096(4096),
_8192(8192),
;
private final int length;
RsaLength(int length) {
this.length = length;
}
@Override
public int getLength() {
return length;
}
}