mirror of
https://github.com/pgpainless/pgpainless.git
synced 2024-12-22 19:08:00 +01:00
Simplify Key Generator API and allow EC keys to be generated
This commit is contained in:
parent
22eb8f487c
commit
ebb06494dd
33 changed files with 443 additions and 301 deletions
10
build.gradle
10
build.gradle
|
@ -1,5 +1,15 @@
|
||||||
plugins {
|
plugins {
|
||||||
id 'java'
|
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'
|
group 'de.vanitasvitae.crypto'
|
||||||
|
|
3
gradle/wrapper/gradle-wrapper.properties
vendored
3
gradle/wrapper/gradle-wrapper.properties
vendored
|
@ -1,5 +1,6 @@
|
||||||
|
#Sat Jun 02 23:06:04 CEST 2018
|
||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
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
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
package de.vanitasvitae.crypto.pgpainless;
|
|
||||||
|
|
||||||
public class EncryptionBuilder {
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,15 +1,11 @@
|
||||||
package de.vanitasvitae.crypto.pgpainless;
|
package de.vanitasvitae.crypto.pgpainless;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.security.InvalidAlgorithmParameterException;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.security.NoSuchProviderException;
|
import java.security.NoSuchProviderException;
|
||||||
import java.security.Security;
|
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.jce.provider.BouncyCastleProvider;
|
||||||
import org.bouncycastle.openpgp.PGPException;
|
import org.bouncycastle.openpgp.PGPException;
|
||||||
import org.bouncycastle.openpgp.PGPSecretKeyRing;
|
import org.bouncycastle.openpgp.PGPSecretKeyRing;
|
||||||
|
@ -17,28 +13,13 @@ import org.bouncycastle.openpgp.PGPSecretKeyRing;
|
||||||
public class Main {
|
public class Main {
|
||||||
|
|
||||||
public static void main(String[] args)
|
public static void main(String[] args)
|
||||||
throws NoSuchAlgorithmException, PGPException, NoSuchProviderException, IOException {
|
throws NoSuchAlgorithmException, PGPException, NoSuchProviderException, IOException,
|
||||||
|
InvalidAlgorithmParameterException {
|
||||||
Security.addProvider(new BouncyCastleProvider());
|
Security.addProvider(new BouncyCastleProvider());
|
||||||
|
|
||||||
PGPSecretKeyRing secretKeys = PGPainless.generateKeyRing()
|
PGPSecretKeyRing secretKeys = PGPainless.generateKeyRing()
|
||||||
.generateCompositeKeyRing()
|
.simpleEcKeyRing("elliptic@cur.ve");
|
||||||
.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();
|
|
||||||
|
|
||||||
byte[] base64 = Base64.getEncoder().encode(secretKeys.getEncoded());
|
//System.out.println(Base64.getEncoder().encodeToString(secretKeys.getEncoded()));
|
||||||
|
|
||||||
System.out.println(new String(base64));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package de.vanitasvitae.crypto.pgpainless;
|
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;
|
import de.vanitasvitae.crypto.pgpainless.key.generation.KeyRingBuilder;
|
||||||
|
|
||||||
public class PGPainless {
|
public class PGPainless {
|
||||||
|
@ -7,4 +9,13 @@ public class PGPainless {
|
||||||
public static KeyRingBuilder generateKeyRing() {
|
public static KeyRingBuilder generateKeyRing() {
|
||||||
return new KeyRingBuilder();
|
return new KeyRingBuilder();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static EncryptionBuilder createEncryptor() {
|
||||||
|
return new EncryptionBuilder();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static DecryptionBuilder createDecryptor() {
|
||||||
|
return new DecryptionBuilder();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,10 @@
|
||||||
package de.vanitasvitae.crypto.pgpainless.key.algorithm;
|
package de.vanitasvitae.crypto.pgpainless.algorithm;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import com.sun.istack.internal.NotNull;
|
|
||||||
|
|
||||||
public class AlgorithmSuite {
|
public class AlgorithmSuite {
|
||||||
|
|
||||||
private static AlgorithmSuite defaultAlgorithmSuite = new AlgorithmSuite(
|
private static AlgorithmSuite defaultAlgorithmSuite = new AlgorithmSuite(
|
||||||
|
@ -18,8 +16,7 @@ public class AlgorithmSuite {
|
||||||
HashAlgorithm.SHA512,
|
HashAlgorithm.SHA512,
|
||||||
HashAlgorithm.SHA384,
|
HashAlgorithm.SHA384,
|
||||||
HashAlgorithm.SHA256,
|
HashAlgorithm.SHA256,
|
||||||
HashAlgorithm.SHA224,
|
HashAlgorithm.SHA224),
|
||||||
HashAlgorithm.SHA1),
|
|
||||||
Arrays.asList(
|
Arrays.asList(
|
||||||
CompressionAlgorithm.ZLIB,
|
CompressionAlgorithm.ZLIB,
|
||||||
CompressionAlgorithm.BZIP2,
|
CompressionAlgorithm.BZIP2,
|
||||||
|
@ -31,15 +28,15 @@ public class AlgorithmSuite {
|
||||||
private List<HashAlgorithm> hashAlgorithms;
|
private List<HashAlgorithm> hashAlgorithms;
|
||||||
private List<CompressionAlgorithm> compressionAlgorithms;
|
private List<CompressionAlgorithm> compressionAlgorithms;
|
||||||
|
|
||||||
public AlgorithmSuite(@NotNull List<SymmetricKeyAlgorithm> symmetricKeyAlgorithms,
|
public AlgorithmSuite(List<SymmetricKeyAlgorithm> symmetricKeyAlgorithms,
|
||||||
@NotNull List<HashAlgorithm> hashAlgorithms,
|
List<HashAlgorithm> hashAlgorithms,
|
||||||
@NotNull List<CompressionAlgorithm> compressionAlgorithms) {
|
List<CompressionAlgorithm> compressionAlgorithms) {
|
||||||
this.symmetricKeyAlgorithms = Collections.unmodifiableList(symmetricKeyAlgorithms);
|
this.symmetricKeyAlgorithms = Collections.unmodifiableList(symmetricKeyAlgorithms);
|
||||||
this.hashAlgorithms = Collections.unmodifiableList(hashAlgorithms);
|
this.hashAlgorithms = Collections.unmodifiableList(hashAlgorithms);
|
||||||
this.compressionAlgorithms = Collections.unmodifiableList(compressionAlgorithms);
|
this.compressionAlgorithms = Collections.unmodifiableList(compressionAlgorithms);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setSymmetricKeyAlgorithms(@NotNull List<SymmetricKeyAlgorithm> symmetricKeyAlgorithms) {
|
public void setSymmetricKeyAlgorithms(List<SymmetricKeyAlgorithm> symmetricKeyAlgorithms) {
|
||||||
this.symmetricKeyAlgorithms = symmetricKeyAlgorithms;
|
this.symmetricKeyAlgorithms = symmetricKeyAlgorithms;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,7 +52,7 @@ public class AlgorithmSuite {
|
||||||
return array;
|
return array;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setHashAlgorithms(@NotNull List<HashAlgorithm> hashAlgorithms) {
|
public void setHashAlgorithms(List<HashAlgorithm> hashAlgorithms) {
|
||||||
this.hashAlgorithms = hashAlgorithms;
|
this.hashAlgorithms = hashAlgorithms;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,7 +68,7 @@ public class AlgorithmSuite {
|
||||||
return array;
|
return array;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCompressionAlgorithms(@NotNull List<CompressionAlgorithm> compressionAlgorithms) {
|
public void setCompressionAlgorithms(List<CompressionAlgorithm> compressionAlgorithms) {
|
||||||
this.compressionAlgorithms = compressionAlgorithms;
|
this.compressionAlgorithms = compressionAlgorithms;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package de.vanitasvitae.crypto.pgpainless.key.algorithm;
|
package de.vanitasvitae.crypto.pgpainless.algorithm;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
|
@ -1,4 +1,4 @@
|
||||||
package de.vanitasvitae.crypto.pgpainless.key.algorithm;
|
package de.vanitasvitae.crypto.pgpainless.algorithm;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
|
@ -1,4 +1,4 @@
|
||||||
package de.vanitasvitae.crypto.pgpainless.key.algorithm;
|
package de.vanitasvitae.crypto.pgpainless.algorithm;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
|
@ -1,4 +1,4 @@
|
||||||
package de.vanitasvitae.crypto.pgpainless.key.algorithm;
|
package de.vanitasvitae.crypto.pgpainless.algorithm;
|
||||||
|
|
||||||
import org.bouncycastle.bcpg.sig.KeyFlags;
|
import org.bouncycastle.bcpg.sig.KeyFlags;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package de.vanitasvitae.crypto.pgpainless.key.algorithm;
|
package de.vanitasvitae.crypto.pgpainless.algorithm;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
|
@ -1,4 +1,4 @@
|
||||||
package de.vanitasvitae.crypto.pgpainless.key.algorithm;
|
package de.vanitasvitae.crypto.pgpainless.algorithm;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
|
@ -0,0 +1,5 @@
|
||||||
|
package de.vanitasvitae.crypto.pgpainless.decryption_verification;
|
||||||
|
|
||||||
|
public class DecryptionBuilder {
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
package de.vanitasvitae.crypto.pgpainless.encryption_signing;
|
||||||
|
|
||||||
|
public class EncryptionBuilder {
|
||||||
|
|
||||||
|
}
|
|
@ -2,6 +2,7 @@ package de.vanitasvitae.crypto.pgpainless.key.generation;
|
||||||
|
|
||||||
|
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
|
import java.security.InvalidAlgorithmParameterException;
|
||||||
import java.security.KeyPair;
|
import java.security.KeyPair;
|
||||||
import java.security.KeyPairGenerator;
|
import java.security.KeyPairGenerator;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
@ -10,9 +11,15 @@ import java.util.ArrayList;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
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.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.HashAlgorithmTags;
|
||||||
|
import org.bouncycastle.bcpg.sig.KeyFlags;
|
||||||
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
||||||
import org.bouncycastle.openpgp.PGPEncryptedData;
|
import org.bouncycastle.openpgp.PGPEncryptedData;
|
||||||
import org.bouncycastle.openpgp.PGPException;
|
import org.bouncycastle.openpgp.PGPException;
|
||||||
|
@ -20,7 +27,7 @@ import org.bouncycastle.openpgp.PGPKeyPair;
|
||||||
import org.bouncycastle.openpgp.PGPKeyRingGenerator;
|
import org.bouncycastle.openpgp.PGPKeyRingGenerator;
|
||||||
import org.bouncycastle.openpgp.PGPSecretKeyRing;
|
import org.bouncycastle.openpgp.PGPSecretKeyRing;
|
||||||
import org.bouncycastle.openpgp.PGPSignature;
|
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.PBESecretKeyEncryptor;
|
||||||
import org.bouncycastle.openpgp.operator.PGPContentSignerBuilder;
|
import org.bouncycastle.openpgp.operator.PGPContentSignerBuilder;
|
||||||
import org.bouncycastle.openpgp.operator.PGPDigestCalculator;
|
import org.bouncycastle.openpgp.operator.PGPDigestCalculator;
|
||||||
|
@ -34,78 +41,65 @@ public class KeyRingBuilder implements KeyRingBuilderInterface {
|
||||||
private final Charset UTF8 = Charset.forName("UTF-8");
|
private final Charset UTF8 = Charset.forName("UTF-8");
|
||||||
|
|
||||||
private List<KeySpec> keySpecs = new ArrayList<>();
|
private List<KeySpec> keySpecs = new ArrayList<>();
|
||||||
private List<String> userIds = new ArrayList<>();
|
private String userId;
|
||||||
private char[] passphrase;
|
private char[] passphrase;
|
||||||
|
|
||||||
@Override
|
public PGPSecretKeyRing simpleRsaKeyRing(String userId, RsaLength length)
|
||||||
public WithSubKeyType generateCompositeKeyRing() {
|
throws PGPException, NoSuchAlgorithmException, NoSuchProviderException, InvalidAlgorithmParameterException {
|
||||||
return new WithSubKeyTypeImpl();
|
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
|
@Override
|
||||||
public WithCertificationKeyType generateSingleKeyKeyRing() {
|
public KeyRingBuilderInterface withSubKey(KeySpec type) {
|
||||||
return new WithCertificationKeyTypeImpl();
|
KeyRingBuilder.this.keySpecs.add(type);
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
class WithSubKeyTypeImpl implements WithSubKeyType {
|
@Override
|
||||||
|
public WithPrimaryUserId withMasterKey(KeySpec spec) {
|
||||||
@Override
|
if ((spec.getSubpackets().getKeyFlags() & KeyFlags.CERTIFY_OTHER) == 0) {
|
||||||
public WithSubKeyType withSubKey(KeySpec type) {
|
throw new IllegalArgumentException("Certification Key MUST have KeyFlag CERTIFY_OTHER");
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
|
KeyRingBuilder.this.keySpecs.add(0, spec);
|
||||||
|
return new WithPrimaryUserIdImpl();
|
||||||
}
|
}
|
||||||
|
|
||||||
class WithPrimaryUserIdImpl implements WithPrimaryUserId {
|
class WithPrimaryUserIdImpl implements WithPrimaryUserId {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WithAdditionalUserIds withPrimaryUserId(String userId) {
|
public WithPassphrase withPrimaryUserId(String userId) {
|
||||||
KeyRingBuilder.this.userIds.add(userId);
|
KeyRingBuilder.this.userId = 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() {
|
|
||||||
return new WithPassphraseImpl();
|
return new WithPassphraseImpl();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public WithPassphrase withPrimaryUserId(byte[] userId) {
|
||||||
|
return withPrimaryUserId(new String(userId, UTF8));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class WithPassphraseImpl implements WithPassphrase {
|
class WithPassphraseImpl implements WithPassphrase {
|
||||||
|
@ -130,7 +124,8 @@ public class KeyRingBuilder implements KeyRingBuilderInterface {
|
||||||
class BuildImpl implements Build {
|
class BuildImpl implements Build {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PGPSecretKeyRing build() throws NoSuchAlgorithmException, PGPException, NoSuchProviderException {
|
public PGPSecretKeyRing build() throws NoSuchAlgorithmException, PGPException, NoSuchProviderException,
|
||||||
|
InvalidAlgorithmParameterException {
|
||||||
|
|
||||||
// Hash Calculator
|
// Hash Calculator
|
||||||
PGPDigestCalculator calculator = new JcaPGPDigestCalculatorProviderBuilder()
|
PGPDigestCalculator calculator = new JcaPGPDigestCalculatorProviderBuilder()
|
||||||
|
@ -147,64 +142,51 @@ public class KeyRingBuilder implements KeyRingBuilderInterface {
|
||||||
|
|
||||||
// First key is the Master Key
|
// First key is the Master Key
|
||||||
KeySpec certKeySpec = keySpecs.get(0);
|
KeySpec certKeySpec = keySpecs.get(0);
|
||||||
KeyType certKeyType = certKeySpec.getKeyType();
|
// Remove master key, so that we later only add sub keys.
|
||||||
keySpecs.remove(0); // Remove master key, so that we later only add sub keys.
|
keySpecs.remove(0);
|
||||||
|
|
||||||
// Generate Master Key
|
// Generate Master Key
|
||||||
PGPKeyPair certKey = generateKeyPair(certKeySpec);
|
PGPKeyPair certKey = generateKeyPair(certKeySpec);
|
||||||
|
|
||||||
// Signer for creating self-signature
|
// Signer for creating self-signature
|
||||||
PGPContentSignerBuilder signer = new JcaPGPContentSignerBuilder(
|
PGPContentSignerBuilder signer = new JcaPGPContentSignerBuilder(
|
||||||
certKey.getPublicKey().getAlgorithm(), HashAlgorithmTags.SHA256);
|
certKey.getPublicKey().getAlgorithm(), HashAlgorithmTags.SHA512)
|
||||||
|
.setProvider(BouncyCastleProvider.PROVIDER_NAME);
|
||||||
|
|
||||||
// Mimic GnuPGs signature sub packets
|
PGPSignatureSubpacketVector hashedSubPackets = certKeySpec.getSubpackets();
|
||||||
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());
|
|
||||||
|
|
||||||
// Generator which the user can get the key pair from
|
// Generator which the user can get the key pair from
|
||||||
PGPKeyRingGenerator ringGenerator = new PGPKeyRingGenerator(
|
PGPKeyRingGenerator ringGenerator = new PGPKeyRingGenerator(
|
||||||
PGPSignature.POSITIVE_CERTIFICATION, certKey,
|
PGPSignature.POSITIVE_CERTIFICATION, certKey,
|
||||||
userIds.get(0), calculator,
|
userId, calculator,
|
||||||
hashedSubPackets.generate(), null, signer, encryptor);
|
hashedSubPackets, null, signer, encryptor);
|
||||||
|
|
||||||
for (KeySpec subKeySpec : keySpecs) {
|
for (KeySpec subKeySpec : keySpecs) {
|
||||||
PGPKeyPair subKey = generateKeyPair(subKeySpec);
|
PGPKeyPair subKey = generateKeyPair(subKeySpec);
|
||||||
ringGenerator.addSubKey(subKey);
|
if (subKeySpec.isInheritedSubPackets()) {
|
||||||
|
ringGenerator.addSubKey(subKey);
|
||||||
|
} else {
|
||||||
|
ringGenerator.addSubKey(subKey, subKeySpec.getSubpackets(), null);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ringGenerator.generateSecretKeyRing();
|
return ringGenerator.generateSecretKeyRing();
|
||||||
}
|
}
|
||||||
|
|
||||||
private PGPKeyPair generateKeyPair(KeySpec spec)
|
private PGPKeyPair generateKeyPair(KeySpec spec)
|
||||||
throws NoSuchProviderException, NoSuchAlgorithmException, PGPException {
|
throws NoSuchProviderException, NoSuchAlgorithmException, PGPException,
|
||||||
|
InvalidAlgorithmParameterException {
|
||||||
KeyType type = spec.getKeyType();
|
KeyType type = spec.getKeyType();
|
||||||
KeyPairGenerator certKeyGenerator = KeyPairGenerator.getInstance(
|
KeyPairGenerator certKeyGenerator = KeyPairGenerator.getInstance(
|
||||||
type.getName(), BouncyCastleProvider.PROVIDER_NAME);
|
type.getName(), BouncyCastleProvider.PROVIDER_NAME);
|
||||||
certKeyGenerator.initialize(type.getLength());
|
certKeyGenerator.initialize(type.getAlgorithmSpec());
|
||||||
|
|
||||||
// Create raw Key Pair
|
// Create raw Key Pair
|
||||||
KeyPair rawKeyPair = certKeyGenerator.generateKeyPair();
|
KeyPair keyPair = certKeyGenerator.generateKeyPair();
|
||||||
|
|
||||||
// Form PGP key pair
|
// Form PGP key pair
|
||||||
PGPKeyPair pgpKeyPair = new JcaPGPKeyPair(type.getAlgorithm().getAlgorithmId(),
|
PGPKeyPair pgpKeyPair = new JcaPGPKeyPair(type.getAlgorithm().getAlgorithmId(),
|
||||||
rawKeyPair, new Date());
|
keyPair, new Date());
|
||||||
|
|
||||||
return pgpKeyPair;
|
return pgpKeyPair;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package de.vanitasvitae.crypto.pgpainless.key.generation;
|
package de.vanitasvitae.crypto.pgpainless.key.generation;
|
||||||
|
|
||||||
|
import java.security.InvalidAlgorithmParameterException;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.security.NoSuchProviderException;
|
import java.security.NoSuchProviderException;
|
||||||
|
|
||||||
|
@ -8,36 +9,15 @@ import org.bouncycastle.openpgp.PGPSecretKeyRing;
|
||||||
|
|
||||||
public interface KeyRingBuilderInterface {
|
public interface KeyRingBuilderInterface {
|
||||||
|
|
||||||
WithSubKeyType generateCompositeKeyRing();
|
KeyRingBuilderInterface withSubKey(KeySpec keySpec);
|
||||||
|
|
||||||
WithCertificationKeyType generateSingleKeyKeyRing();
|
WithPrimaryUserId withMasterKey(KeySpec keySpec);
|
||||||
|
|
||||||
interface WithSubKeyType {
|
|
||||||
|
|
||||||
WithSubKeyType withSubKey(KeySpec keySpec);
|
|
||||||
|
|
||||||
WithCertificationKeyType done();
|
|
||||||
}
|
|
||||||
|
|
||||||
interface WithCertificationKeyType {
|
|
||||||
WithPrimaryUserId withCertificationKeyType(KeySpec keySpec);
|
|
||||||
}
|
|
||||||
|
|
||||||
interface WithPrimaryUserId {
|
interface WithPrimaryUserId {
|
||||||
|
|
||||||
WithAdditionalUserIds withPrimaryUserId(String userId);
|
WithPassphrase withPrimaryUserId(String userId);
|
||||||
|
|
||||||
WithAdditionalUserIds withPrimaryUserId(byte[] userId);
|
WithPassphrase withPrimaryUserId(byte[] userId);
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
interface WithAdditionalUserIds {
|
|
||||||
|
|
||||||
WithAdditionalUserIds withAdditionalUserId(String userId);
|
|
||||||
|
|
||||||
WithAdditionalUserIds withAdditionalUserId(byte[] userId);
|
|
||||||
|
|
||||||
WithPassphrase done();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,7 +32,8 @@ public interface KeyRingBuilderInterface {
|
||||||
|
|
||||||
interface Build {
|
interface Build {
|
||||||
|
|
||||||
PGPSecretKeyRing build() throws NoSuchAlgorithmException, PGPException, NoSuchProviderException;
|
PGPSecretKeyRing build() throws NoSuchAlgorithmException, PGPException, NoSuchProviderException,
|
||||||
|
InvalidAlgorithmParameterException;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,46 +1,33 @@
|
||||||
package de.vanitasvitae.crypto.pgpainless.key.generation;
|
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 de.vanitasvitae.crypto.pgpainless.key.generation.type.KeyType;
|
||||||
|
import org.bouncycastle.openpgp.PGPSignatureSubpacketGenerator;
|
||||||
|
import org.bouncycastle.openpgp.PGPSignatureSubpacketVector;
|
||||||
|
|
||||||
public class KeySpec {
|
public class KeySpec {
|
||||||
|
|
||||||
private final KeyType keyType;
|
private final KeyType keyType;
|
||||||
private final int keyFlags;
|
private final PGPSignatureSubpacketGenerator subpacketGenerator;
|
||||||
private final AlgorithmSuite algorithmSuite;
|
private final boolean inheritedSubPackets;
|
||||||
private final Set<Feature> features;
|
|
||||||
|
|
||||||
KeySpec(KeyType type,
|
KeySpec(KeyType type,
|
||||||
int keyFlags,
|
PGPSignatureSubpacketGenerator subpacketGenerator,
|
||||||
AlgorithmSuite preferredAlgorithms,
|
boolean inheritedSubPackets) {
|
||||||
Set<Feature> features) {
|
|
||||||
this.keyType = type;
|
this.keyType = type;
|
||||||
this.keyFlags = keyFlags;
|
this.subpacketGenerator = subpacketGenerator;
|
||||||
this.algorithmSuite = preferredAlgorithms;
|
this.inheritedSubPackets = inheritedSubPackets;
|
||||||
this.features = features;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
KeyType getKeyType() {
|
KeyType getKeyType() {
|
||||||
return keyType;
|
return keyType;
|
||||||
}
|
}
|
||||||
|
|
||||||
int getKeyFlags() {
|
PGPSignatureSubpacketVector getSubpackets() {
|
||||||
return keyFlags;
|
return subpacketGenerator.generate();
|
||||||
}
|
}
|
||||||
|
|
||||||
AlgorithmSuite getPreferredAlgorithms() {
|
boolean isInheritedSubPackets() {
|
||||||
return algorithmSuite;
|
return inheritedSubPackets;
|
||||||
}
|
|
||||||
|
|
||||||
byte getFeatures() {
|
|
||||||
byte val = 0;
|
|
||||||
for (Feature f : features) {
|
|
||||||
val |= f.getFeatureId();
|
|
||||||
}
|
|
||||||
return val;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static KeySpecBuilder getBuilder() {
|
public static KeySpecBuilder getBuilder() {
|
||||||
|
|
|
@ -1,23 +1,21 @@
|
||||||
package de.vanitasvitae.crypto.pgpainless.key.generation;
|
package de.vanitasvitae.crypto.pgpainless.key.generation;
|
||||||
|
|
||||||
import java.util.Arrays;
|
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.algorithm.AlgorithmSuite;
|
||||||
import de.vanitasvitae.crypto.pgpainless.key.algorithm.CompressionAlgorithm;
|
import de.vanitasvitae.crypto.pgpainless.algorithm.CompressionAlgorithm;
|
||||||
import de.vanitasvitae.crypto.pgpainless.key.algorithm.Feature;
|
import de.vanitasvitae.crypto.pgpainless.algorithm.Feature;
|
||||||
import de.vanitasvitae.crypto.pgpainless.key.algorithm.HashAlgorithm;
|
import de.vanitasvitae.crypto.pgpainless.algorithm.HashAlgorithm;
|
||||||
import de.vanitasvitae.crypto.pgpainless.key.algorithm.KeyFlag;
|
import de.vanitasvitae.crypto.pgpainless.algorithm.KeyFlag;
|
||||||
import de.vanitasvitae.crypto.pgpainless.key.algorithm.SymmetricKeyAlgorithm;
|
import de.vanitasvitae.crypto.pgpainless.algorithm.SymmetricKeyAlgorithm;
|
||||||
import de.vanitasvitae.crypto.pgpainless.key.generation.type.KeyType;
|
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 {
|
public class KeySpecBuilder implements KeySpecBuilderInterface {
|
||||||
|
|
||||||
private KeyType type;
|
private KeyType type;
|
||||||
private int keyFlags;
|
private PGPSignatureSubpacketGenerator hashedSubPackets = new PGPSignatureSubpacketGenerator();
|
||||||
private AlgorithmSuite algorithmSuite = AlgorithmSuite.getDefaultAlgorithmSuite();
|
|
||||||
private Set<Feature> features = new HashSet<>();
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WithKeyFlags ofType(KeyType type) {
|
public WithKeyFlags ofType(KeyType type) {
|
||||||
|
@ -33,7 +31,7 @@ public class KeySpecBuilder implements KeySpecBuilderInterface {
|
||||||
for (KeyFlag f : flags) {
|
for (KeyFlag f : flags) {
|
||||||
val |= f.getFlag();
|
val |= f.getFlag();
|
||||||
}
|
}
|
||||||
KeySpecBuilder.this.keyFlags = val;
|
KeySpecBuilder.this.hashedSubPackets.setKeyFlags(false, val);
|
||||||
return new WithDetailedConfigurationImpl();
|
return new WithDetailedConfigurationImpl();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,6 +44,11 @@ public class KeySpecBuilder implements KeySpecBuilderInterface {
|
||||||
KeyFlag.ENCRYPT_STORAGE,
|
KeyFlag.ENCRYPT_STORAGE,
|
||||||
KeyFlag.AUTHENTICATION);
|
KeyFlag.AUTHENTICATION);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public KeySpec withInheritedSubPackets() {
|
||||||
|
return new KeySpec(type, null, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class WithDetailedConfigurationImpl implements WithDetailedConfiguration {
|
class WithDetailedConfigurationImpl implements WithDetailedConfiguration {
|
||||||
|
@ -57,12 +60,16 @@ public class KeySpecBuilder implements KeySpecBuilderInterface {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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(
|
return new KeySpec(
|
||||||
KeySpecBuilder.this.type,
|
KeySpecBuilder.this.type,
|
||||||
KeySpecBuilder.this.keyFlags,
|
KeySpecBuilder.this.hashedSubPackets,
|
||||||
KeySpecBuilder.this.algorithmSuite,
|
false);
|
||||||
KeySpecBuilder.this.features);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,20 +77,29 @@ public class KeySpecBuilder implements KeySpecBuilderInterface {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WithPreferredHashAlgorithms withPreferredSymmetricAlgorithms(SymmetricKeyAlgorithm... algorithms) {
|
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();
|
return new WithPreferredHashAlgorithmsImpl();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WithPreferredHashAlgorithms withDefaultSymmetricAlgorithms() {
|
public WithPreferredHashAlgorithms withDefaultSymmetricAlgorithms() {
|
||||||
KeySpecBuilder.this.algorithmSuite.setSymmetricKeyAlgorithms(
|
KeySpecBuilder.this.hashedSubPackets.setPreferredSymmetricAlgorithms(false,
|
||||||
AlgorithmSuite.getDefaultAlgorithmSuite().getSymmetricKeyAlgorithms());
|
AlgorithmSuite.getDefaultAlgorithmSuite().getSymmetricKeyAlgorithmIds());
|
||||||
return new WithPreferredHashAlgorithmsImpl();
|
return new WithPreferredHashAlgorithmsImpl();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WithFeatures withDefaultAlgorithms() {
|
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();
|
return new WithFeaturesImpl();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -92,14 +108,18 @@ public class KeySpecBuilder implements KeySpecBuilderInterface {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WithPreferredCompressionAlgorithms withPreferredHashAlgorithms(HashAlgorithm... algorithms) {
|
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();
|
return new WithPreferredCompressionAlgorithmsImpl();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WithPreferredCompressionAlgorithms withDefaultHashAlgorithms() {
|
public WithPreferredCompressionAlgorithms withDefaultHashAlgorithms() {
|
||||||
KeySpecBuilder.this.algorithmSuite.setHashAlgorithms(
|
KeySpecBuilder.this.hashedSubPackets.setPreferredHashAlgorithms(false,
|
||||||
AlgorithmSuite.getDefaultAlgorithmSuite().getHashAlgorithms());
|
AlgorithmSuite.getDefaultAlgorithmSuite().getHashAlgorithmIds());
|
||||||
return new WithPreferredCompressionAlgorithmsImpl();
|
return new WithPreferredCompressionAlgorithmsImpl();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -108,14 +128,18 @@ public class KeySpecBuilder implements KeySpecBuilderInterface {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WithFeatures withPreferredCompressionAlgorithms(CompressionAlgorithm... algorithms) {
|
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();
|
return new WithFeaturesImpl();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WithFeatures withDefaultCompressionAlgorithms() {
|
public WithFeatures withDefaultCompressionAlgorithms() {
|
||||||
KeySpecBuilder.this.algorithmSuite.setCompressionAlgorithms(
|
KeySpecBuilder.this.hashedSubPackets.setPreferredCompressionAlgorithms(false,
|
||||||
AlgorithmSuite.getDefaultAlgorithmSuite().getCompressionAlgorithms());
|
AlgorithmSuite.getDefaultAlgorithmSuite().getCompressionAlgorithmIds());
|
||||||
return new WithFeaturesImpl();
|
return new WithFeaturesImpl();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -124,7 +148,7 @@ public class KeySpecBuilder implements KeySpecBuilderInterface {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WithFeatures withFeature(Feature feature) {
|
public WithFeatures withFeature(Feature feature) {
|
||||||
KeySpecBuilder.this.features.add(feature);
|
KeySpecBuilder.this.hashedSubPackets.setFeature(false, feature.getFeatureId());
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -132,9 +156,8 @@ public class KeySpecBuilder implements KeySpecBuilderInterface {
|
||||||
public KeySpec done() {
|
public KeySpec done() {
|
||||||
return new KeySpec(
|
return new KeySpec(
|
||||||
KeySpecBuilder.this.type,
|
KeySpecBuilder.this.type,
|
||||||
KeySpecBuilder.this.keyFlags,
|
hashedSubPackets,
|
||||||
KeySpecBuilder.this.algorithmSuite,
|
false);
|
||||||
KeySpecBuilder.this.features);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
package de.vanitasvitae.crypto.pgpainless.key.generation;
|
package de.vanitasvitae.crypto.pgpainless.key.generation;
|
||||||
|
|
||||||
import de.vanitasvitae.crypto.pgpainless.key.algorithm.AlgorithmSuite;
|
import de.vanitasvitae.crypto.pgpainless.algorithm.CompressionAlgorithm;
|
||||||
import de.vanitasvitae.crypto.pgpainless.key.algorithm.CompressionAlgorithm;
|
import de.vanitasvitae.crypto.pgpainless.algorithm.Feature;
|
||||||
import de.vanitasvitae.crypto.pgpainless.key.algorithm.Feature;
|
import de.vanitasvitae.crypto.pgpainless.algorithm.HashAlgorithm;
|
||||||
import de.vanitasvitae.crypto.pgpainless.key.algorithm.HashAlgorithm;
|
import de.vanitasvitae.crypto.pgpainless.algorithm.KeyFlag;
|
||||||
import de.vanitasvitae.crypto.pgpainless.key.algorithm.KeyFlag;
|
import de.vanitasvitae.crypto.pgpainless.algorithm.SymmetricKeyAlgorithm;
|
||||||
import de.vanitasvitae.crypto.pgpainless.key.algorithm.SymmetricKeyAlgorithm;
|
|
||||||
import de.vanitasvitae.crypto.pgpainless.key.generation.type.KeyType;
|
import de.vanitasvitae.crypto.pgpainless.key.generation.type.KeyType;
|
||||||
|
|
||||||
public interface KeySpecBuilderInterface {
|
public interface KeySpecBuilderInterface {
|
||||||
|
@ -17,13 +16,15 @@ public interface KeySpecBuilderInterface {
|
||||||
WithDetailedConfiguration withKeyFlags(KeyFlag... flags);
|
WithDetailedConfiguration withKeyFlags(KeyFlag... flags);
|
||||||
|
|
||||||
WithDetailedConfiguration withDefaultKeyFlags();
|
WithDetailedConfiguration withDefaultKeyFlags();
|
||||||
|
|
||||||
|
KeySpec withInheritedSubPackets();
|
||||||
}
|
}
|
||||||
|
|
||||||
interface WithDetailedConfiguration {
|
interface WithDetailedConfiguration {
|
||||||
|
|
||||||
WithPreferredSymmetricAlgorithms withDetailedConfiguration();
|
WithPreferredSymmetricAlgorithms withDetailedConfiguration();
|
||||||
|
|
||||||
KeySpec withStandardConfiguration();
|
KeySpec withDefaultAlgorithms();
|
||||||
}
|
}
|
||||||
|
|
||||||
interface WithPreferredSymmetricAlgorithms {
|
interface WithPreferredSymmetricAlgorithms {
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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());
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,28 +1,12 @@
|
||||||
package de.vanitasvitae.crypto.pgpainless.key.generation.type;
|
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),
|
ElGamal_ENCRYPT(ElGamalLength length) {
|
||||||
_2048(2048),
|
super(length);
|
||||||
_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";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -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());
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,12 +1,14 @@
|
||||||
package de.vanitasvitae.crypto.pgpainless.key.generation.type;
|
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 {
|
public interface KeyType {
|
||||||
|
|
||||||
int getLength();
|
|
||||||
|
|
||||||
String getName();
|
String getName();
|
||||||
|
|
||||||
PublicKeyAlgorithm getAlgorithm();
|
PublicKeyAlgorithm getAlgorithm();
|
||||||
|
|
||||||
|
AlgorithmParameterSpec getAlgorithmSpec();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,27 +1,21 @@
|
||||||
package de.vanitasvitae.crypto.pgpainless.key.generation.type;
|
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
|
public class RSA_GENERAL implements KeyType {
|
||||||
_1024(1024),
|
|
||||||
@Deprecated
|
|
||||||
_2048(2048),
|
|
||||||
_3072(3072),
|
|
||||||
_4096(4096),
|
|
||||||
_8192(8192),
|
|
||||||
;
|
|
||||||
|
|
||||||
private final int length;
|
private final RsaLength length;
|
||||||
|
|
||||||
RSA_GENERAL(int length) {
|
RSA_GENERAL(RsaLength length) {
|
||||||
this.length = length;
|
this.length = length;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public static RSA_GENERAL withLength(RsaLength length) {
|
||||||
public int getLength() {
|
return new RSA_GENERAL(length);
|
||||||
return length;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -33,4 +27,9 @@ public enum RSA_GENERAL implements KeyType {
|
||||||
public PublicKeyAlgorithm getAlgorithm() {
|
public PublicKeyAlgorithm getAlgorithm() {
|
||||||
return PublicKeyAlgorithm.RSA_GENERAL;
|
return PublicKeyAlgorithm.RSA_GENERAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AlgorithmParameterSpec getAlgorithmSpec() {
|
||||||
|
return new RSAKeyGenParameterSpec(length.getLength(), RSAKeyGenParameterSpec.F4);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
package de.vanitasvitae.crypto.pgpainless.key.generation.type.length;
|
||||||
|
|
||||||
|
public interface KeyLength {
|
||||||
|
|
||||||
|
int getLength();
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue