Free as in Freedom: Codeberg.org. Create your repos!
Browse Source

Initial commit

tags/0.0.1-alpha1
Paul Schaub 10 months ago
commit
6dd2e83acf
Signed by: Paul Schaub <vanitasvitae@fsfe.org> GPG Key ID: 62BEE9264BF17311
27 changed files with 1325 additions and 0 deletions
  1. 14
    0
      .gitignore
  2. 18
    0
      build.gradle
  3. BIN
      gradle/wrapper/gradle-wrapper.jar
  4. 5
    0
      gradle/wrapper/gradle-wrapper.properties
  5. 172
    0
      gradlew
  6. 84
    0
      gradlew.bat
  7. 2
    0
      settings.gradle
  8. 5
    0
      src/main/java/de/vanitasvitae/crypto/pgpainless/EncryptionBuilder.java
  9. 44
    0
      src/main/java/de/vanitasvitae/crypto/pgpainless/Main.java
  10. 10
    0
      src/main/java/de/vanitasvitae/crypto/pgpainless/PGPainless.java
  11. 8
    0
      src/main/java/de/vanitasvitae/crypto/pgpainless/PainlessResult.java
  12. 93
    0
      src/main/java/de/vanitasvitae/crypto/pgpainless/key/algorithm/AlgorithmSuite.java
  13. 37
    0
      src/main/java/de/vanitasvitae/crypto/pgpainless/key/algorithm/CompressionAlgorithm.java
  14. 33
    0
      src/main/java/de/vanitasvitae/crypto/pgpainless/key/algorithm/Feature.java
  15. 44
    0
      src/main/java/de/vanitasvitae/crypto/pgpainless/key/algorithm/HashAlgorithm.java
  16. 25
    0
      src/main/java/de/vanitasvitae/crypto/pgpainless/key/algorithm/KeyFlag.java
  17. 46
    0
      src/main/java/de/vanitasvitae/crypto/pgpainless/key/algorithm/PublicKeyAlgorithm.java
  18. 47
    0
      src/main/java/de/vanitasvitae/crypto/pgpainless/key/algorithm/SymmetricKeyAlgorithm.java
  19. 213
    0
      src/main/java/de/vanitasvitae/crypto/pgpainless/key/generation/KeyRingBuilder.java
  20. 58
    0
      src/main/java/de/vanitasvitae/crypto/pgpainless/key/generation/KeyRingBuilderInterface.java
  21. 49
    0
      src/main/java/de/vanitasvitae/crypto/pgpainless/key/generation/KeySpec.java
  22. 140
    0
      src/main/java/de/vanitasvitae/crypto/pgpainless/key/generation/KeySpecBuilder.java
  23. 62
    0
      src/main/java/de/vanitasvitae/crypto/pgpainless/key/generation/KeySpecBuilderInterface.java
  24. 36
    0
      src/main/java/de/vanitasvitae/crypto/pgpainless/key/generation/type/DSA.java
  25. 32
    0
      src/main/java/de/vanitasvitae/crypto/pgpainless/key/generation/type/ElGamal_ENCRYPT.java
  26. 12
    0
      src/main/java/de/vanitasvitae/crypto/pgpainless/key/generation/type/KeyType.java
  27. 36
    0
      src/main/java/de/vanitasvitae/crypto/pgpainless/key/generation/type/RSA_GENERAL.java

+ 14
- 0
.gitignore View File

@@ -0,0 +1,14 @@
1
+.idea
2
+.gradle
3
+
4
+out/
5
+
6
+*.iws
7
+*.iml
8
+*.ipr
9
+*.class
10
+*.log
11
+*.jar
12
+
13
+
14
+!gradle-wrapper.jar

+ 18
- 0
build.gradle View File

@@ -0,0 +1,18 @@
1
+plugins {
2
+    id 'java'
3
+}
4
+
5
+group 'de.vanitasvitae.crypto'
6
+version '0.1-SNAPSHOT'
7
+
8
+sourceCompatibility = 1.8
9
+
10
+repositories {
11
+    mavenCentral()
12
+}
13
+
14
+dependencies {
15
+    testCompile group: 'junit', name: 'junit', version: '4.12'
16
+    compile 'org.bouncycastle:bcprov-jdk15on:1.59'
17
+    compile 'org.bouncycastle:bcpg-jdk15on:1.59'
18
+}

BIN
gradle/wrapper/gradle-wrapper.jar View File


+ 5
- 0
gradle/wrapper/gradle-wrapper.properties View File

@@ -0,0 +1,5 @@
1
+distributionBase=GRADLE_USER_HOME
2
+distributionPath=wrapper/dists
3
+zipStoreBase=GRADLE_USER_HOME
4
+zipStorePath=wrapper/dists
5
+distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-bin.zip

+ 172
- 0
gradlew View File

@@ -0,0 +1,172 @@
1
+#!/usr/bin/env sh
2
+
3
+##############################################################################
4
+##
5
+##  Gradle start up script for UN*X
6
+##
7
+##############################################################################
8
+
9
+# Attempt to set APP_HOME
10
+# Resolve links: $0 may be a link
11
+PRG="$0"
12
+# Need this for relative symlinks.
13
+while [ -h "$PRG" ] ; do
14
+    ls=`ls -ld "$PRG"`
15
+    link=`expr "$ls" : '.*-> \(.*\)$'`
16
+    if expr "$link" : '/.*' > /dev/null; then
17
+        PRG="$link"
18
+    else
19
+        PRG=`dirname "$PRG"`"/$link"
20
+    fi
21
+done
22
+SAVED="`pwd`"
23
+cd "`dirname \"$PRG\"`/" >/dev/null
24
+APP_HOME="`pwd -P`"
25
+cd "$SAVED" >/dev/null
26
+
27
+APP_NAME="Gradle"
28
+APP_BASE_NAME=`basename "$0"`
29
+
30
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
31
+DEFAULT_JVM_OPTS=""
32
+
33
+# Use the maximum available, or set MAX_FD != -1 to use that value.
34
+MAX_FD="maximum"
35
+
36
+warn () {
37
+    echo "$*"
38
+}
39
+
40
+die () {
41
+    echo
42
+    echo "$*"
43
+    echo
44
+    exit 1
45
+}
46
+
47
+# OS specific support (must be 'true' or 'false').
48
+cygwin=false
49
+msys=false
50
+darwin=false
51
+nonstop=false
52
+case "`uname`" in
53
+  CYGWIN* )
54
+    cygwin=true
55
+    ;;
56
+  Darwin* )
57
+    darwin=true
58
+    ;;
59
+  MINGW* )
60
+    msys=true
61
+    ;;
62
+  NONSTOP* )
63
+    nonstop=true
64
+    ;;
65
+esac
66
+
67
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
68
+
69
+# Determine the Java command to use to start the JVM.
70
+if [ -n "$JAVA_HOME" ] ; then
71
+    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
72
+        # IBM's JDK on AIX uses strange locations for the executables
73
+        JAVACMD="$JAVA_HOME/jre/sh/java"
74
+    else
75
+        JAVACMD="$JAVA_HOME/bin/java"
76
+    fi
77
+    if [ ! -x "$JAVACMD" ] ; then
78
+        die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
79
+
80
+Please set the JAVA_HOME variable in your environment to match the
81
+location of your Java installation."
82
+    fi
83
+else
84
+    JAVACMD="java"
85
+    which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
86
+
87
+Please set the JAVA_HOME variable in your environment to match the
88
+location of your Java installation."
89
+fi
90
+
91
+# Increase the maximum file descriptors if we can.
92
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
93
+    MAX_FD_LIMIT=`ulimit -H -n`
94
+    if [ $? -eq 0 ] ; then
95
+        if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
96
+            MAX_FD="$MAX_FD_LIMIT"
97
+        fi
98
+        ulimit -n $MAX_FD
99
+        if [ $? -ne 0 ] ; then
100
+            warn "Could not set maximum file descriptor limit: $MAX_FD"
101
+        fi
102
+    else
103
+        warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
104
+    fi
105
+fi
106
+
107
+# For Darwin, add options to specify how the application appears in the dock
108
+if $darwin; then
109
+    GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
110
+fi
111
+
112
+# For Cygwin, switch paths to Windows format before running java
113
+if $cygwin ; then
114
+    APP_HOME=`cygpath --path --mixed "$APP_HOME"`
115
+    CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
116
+    JAVACMD=`cygpath --unix "$JAVACMD"`
117
+
118
+    # We build the pattern for arguments to be converted via cygpath
119
+    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120
+    SEP=""
121
+    for dir in $ROOTDIRSRAW ; do
122
+        ROOTDIRS="$ROOTDIRS$SEP$dir"
123
+        SEP="|"
124
+    done
125
+    OURCYGPATTERN="(^($ROOTDIRS))"
126
+    # Add a user-defined pattern to the cygpath arguments
127
+    if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128
+        OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129
+    fi
130
+    # Now convert the arguments - kludge to limit ourselves to /bin/sh
131
+    i=0
132
+    for arg in "$@" ; do
133
+        CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134
+        CHECK2=`echo "$arg"|egrep -c "^-"`                                 ### Determine if an option
135
+
136
+        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition
137
+            eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138
+        else
139
+            eval `echo args$i`="\"$arg\""
140
+        fi
141
+        i=$((i+1))
142
+    done
143
+    case $i in
144
+        (0) set -- ;;
145
+        (1) set -- "$args0" ;;
146
+        (2) set -- "$args0" "$args1" ;;
147
+        (3) set -- "$args0" "$args1" "$args2" ;;
148
+        (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149
+        (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150
+        (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151
+        (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152
+        (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153
+        (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154
+    esac
155
+fi
156
+
157
+# Escape application args
158
+save () {
159
+    for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
160
+    echo " "
161
+}
162
+APP_ARGS=$(save "$@")
163
+
164
+# Collect all arguments for the java command, following the shell quoting and substitution rules
165
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
166
+
167
+# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
168
+if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
169
+  cd "$(dirname "$0")"
170
+fi
171
+
172
+exec "$JAVACMD" "$@"

+ 84
- 0
gradlew.bat View File

@@ -0,0 +1,84 @@
1
+@if "%DEBUG%" == "" @echo off
2
+@rem ##########################################################################
3
+@rem
4
+@rem  Gradle startup script for Windows
5
+@rem
6
+@rem ##########################################################################
7
+
8
+@rem Set local scope for the variables with windows NT shell
9
+if "%OS%"=="Windows_NT" setlocal
10
+
11
+set DIRNAME=%~dp0
12
+if "%DIRNAME%" == "" set DIRNAME=.
13
+set APP_BASE_NAME=%~n0
14
+set APP_HOME=%DIRNAME%
15
+
16
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
17
+set DEFAULT_JVM_OPTS=
18
+
19
+@rem Find java.exe
20
+if defined JAVA_HOME goto findJavaFromJavaHome
21
+
22
+set JAVA_EXE=java.exe
23
+%JAVA_EXE% -version >NUL 2>&1
24
+if "%ERRORLEVEL%" == "0" goto init
25
+
26
+echo.
27
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28
+echo.
29
+echo Please set the JAVA_HOME variable in your environment to match the
30
+echo location of your Java installation.
31
+
32
+goto fail
33
+
34
+:findJavaFromJavaHome
35
+set JAVA_HOME=%JAVA_HOME:"=%
36
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37
+
38
+if exist "%JAVA_EXE%" goto init
39
+
40
+echo.
41
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42
+echo.
43
+echo Please set the JAVA_HOME variable in your environment to match the
44
+echo location of your Java installation.
45
+
46
+goto fail
47
+
48
+:init
49
+@rem Get command-line arguments, handling Windows variants
50
+
51
+if not "%OS%" == "Windows_NT" goto win9xME_args
52
+
53
+:win9xME_args
54
+@rem Slurp the command line arguments.
55
+set CMD_LINE_ARGS=
56
+set _SKIP=2
57
+
58
+:win9xME_args_slurp
59
+if "x%~1" == "x" goto execute
60
+
61
+set CMD_LINE_ARGS=%*
62
+
63
+:execute
64
+@rem Setup the command line
65
+
66
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
67
+
68
+@rem Execute Gradle
69
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
70
+
71
+:end
72
+@rem End local scope for the variables with windows NT shell
73
+if "%ERRORLEVEL%"=="0" goto mainEnd
74
+
75
+:fail
76
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
77
+rem the _cmd.exe /c_ return code!
78
+if  not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
79
+exit /b 1
80
+
81
+:mainEnd
82
+if "%OS%"=="Windows_NT" endlocal
83
+
84
+:omega

+ 2
- 0
settings.gradle View File

@@ -0,0 +1,2 @@
1
+rootProject.name = 'pgpainless'
2
+

+ 5
- 0
src/main/java/de/vanitasvitae/crypto/pgpainless/EncryptionBuilder.java View File

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

+ 44
- 0
src/main/java/de/vanitasvitae/crypto/pgpainless/Main.java View File

@@ -0,0 +1,44 @@
1
+package de.vanitasvitae.crypto.pgpainless;
2
+
3
+import java.io.IOException;
4
+import java.security.NoSuchAlgorithmException;
5
+import java.security.NoSuchProviderException;
6
+import java.security.Security;
7
+import java.util.Base64;
8
+
9
+import de.vanitasvitae.crypto.pgpainless.key.algorithm.KeyFlag;
10
+import de.vanitasvitae.crypto.pgpainless.key.generation.KeySpec;
11
+import de.vanitasvitae.crypto.pgpainless.key.generation.type.DSA;
12
+import de.vanitasvitae.crypto.pgpainless.key.generation.type.RSA_GENERAL;
13
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
14
+import org.bouncycastle.openpgp.PGPException;
15
+import org.bouncycastle.openpgp.PGPSecretKeyRing;
16
+
17
+public class Main {
18
+
19
+    public static void main(String[] args)
20
+            throws NoSuchAlgorithmException, PGPException, NoSuchProviderException, IOException {
21
+        Security.addProvider(new BouncyCastleProvider());
22
+        PGPSecretKeyRing secretKeys = PGPainless.generateKeyRing()
23
+                .generateCompositeKeyRing()
24
+                .withSubKey(
25
+                        KeySpec.getBuilder()
26
+                                .ofType(RSA_GENERAL._4096)
27
+                                .withKeyFlags(KeyFlag.ENCRYPT_COMMS, KeyFlag.ENCRYPT_STORAGE)
28
+                                .withStandardConfiguration())
29
+                .done()
30
+                .withCertificationKeyType(
31
+                        KeySpec.getBuilder()
32
+                                .ofType(DSA._3072)
33
+                                .withKeyFlags(KeyFlag.SIGN_DATA)
34
+                                .withStandardConfiguration())
35
+                .withPrimaryUserId("Test123")
36
+                .done()
37
+                .withoutPassphrase()
38
+                .build();
39
+
40
+        byte[] base64 = Base64.getEncoder().encode(secretKeys.getEncoded());
41
+
42
+        System.out.println(new String(base64));
43
+    }
44
+}

+ 10
- 0
src/main/java/de/vanitasvitae/crypto/pgpainless/PGPainless.java View File

@@ -0,0 +1,10 @@
1
+package de.vanitasvitae.crypto.pgpainless;
2
+
3
+import de.vanitasvitae.crypto.pgpainless.key.generation.KeyRingBuilder;
4
+
5
+public class PGPainless {
6
+
7
+    public static KeyRingBuilder generateKeyRing() {
8
+        return new KeyRingBuilder();
9
+    }
10
+}

+ 8
- 0
src/main/java/de/vanitasvitae/crypto/pgpainless/PainlessResult.java View File

@@ -0,0 +1,8 @@
1
+package de.vanitasvitae.crypto.pgpainless;
2
+
3
+import java.util.Set;
4
+
5
+public class PainlessResult {
6
+    Set<Long> signingKeys;
7
+    Long decryptingKey;
8
+}

+ 93
- 0
src/main/java/de/vanitasvitae/crypto/pgpainless/key/algorithm/AlgorithmSuite.java View File

@@ -0,0 +1,93 @@
1
+package de.vanitasvitae.crypto.pgpainless.key.algorithm;
2
+
3
+import java.util.ArrayList;
4
+import java.util.Arrays;
5
+import java.util.Collections;
6
+import java.util.List;
7
+
8
+import com.sun.istack.internal.NotNull;
9
+
10
+public class AlgorithmSuite {
11
+
12
+    private static AlgorithmSuite defaultAlgorithmSuite = new AlgorithmSuite(
13
+            Arrays.asList(
14
+                    SymmetricKeyAlgorithm.AES_256,
15
+                    SymmetricKeyAlgorithm.AES_192,
16
+                    SymmetricKeyAlgorithm.AES_128),
17
+            Arrays.asList(
18
+                    HashAlgorithm.SHA512,
19
+                    HashAlgorithm.SHA384,
20
+                    HashAlgorithm.SHA256,
21
+                    HashAlgorithm.SHA224,
22
+                    HashAlgorithm.SHA1),
23
+            Arrays.asList(
24
+                    CompressionAlgorithm.ZLIB,
25
+                    CompressionAlgorithm.BZIP2,
26
+                    CompressionAlgorithm.ZIP,
27
+                    CompressionAlgorithm.UNCOMPRESSED)
28
+    );
29
+
30
+    private List<SymmetricKeyAlgorithm> symmetricKeyAlgorithms;
31
+    private List<HashAlgorithm> hashAlgorithms;
32
+    private List<CompressionAlgorithm> compressionAlgorithms;
33
+
34
+    public AlgorithmSuite(@NotNull List<SymmetricKeyAlgorithm> symmetricKeyAlgorithms,
35
+                          @NotNull List<HashAlgorithm> hashAlgorithms,
36
+                          @NotNull List<CompressionAlgorithm> compressionAlgorithms) {
37
+        this.symmetricKeyAlgorithms = Collections.unmodifiableList(symmetricKeyAlgorithms);
38
+        this.hashAlgorithms = Collections.unmodifiableList(hashAlgorithms);
39
+        this.compressionAlgorithms = Collections.unmodifiableList(compressionAlgorithms);
40
+    }
41
+
42
+    public void setSymmetricKeyAlgorithms(@NotNull List<SymmetricKeyAlgorithm> symmetricKeyAlgorithms) {
43
+        this.symmetricKeyAlgorithms = symmetricKeyAlgorithms;
44
+    }
45
+
46
+    public List<SymmetricKeyAlgorithm> getSymmetricKeyAlgorithms() {
47
+        return new ArrayList<>(symmetricKeyAlgorithms);
48
+    }
49
+
50
+    public int[] getSymmetricKeyAlgorithmIds() {
51
+        int[] array = new int[symmetricKeyAlgorithms.size()];
52
+        for (int i = 0; i < array.length; i++) {
53
+            array[i] = symmetricKeyAlgorithms.get(i).getAlgorithmId();
54
+        }
55
+        return array;
56
+    }
57
+
58
+    public void setHashAlgorithms(@NotNull List<HashAlgorithm> hashAlgorithms) {
59
+        this.hashAlgorithms = hashAlgorithms;
60
+    }
61
+
62
+    public List<HashAlgorithm> getHashAlgorithms() {
63
+        return hashAlgorithms;
64
+    }
65
+
66
+    public int[] getHashAlgorithmIds() {
67
+        int[] array = new int[hashAlgorithms.size()];
68
+        for (int i = 0; i < array.length; i++) {
69
+            array[i] = hashAlgorithms.get(i).getAlgorithmId();
70
+        }
71
+        return array;
72
+    }
73
+
74
+    public void setCompressionAlgorithms(@NotNull List<CompressionAlgorithm> compressionAlgorithms) {
75
+        this.compressionAlgorithms = compressionAlgorithms;
76
+    }
77
+
78
+    public List<CompressionAlgorithm> getCompressionAlgorithms() {
79
+        return compressionAlgorithms;
80
+    }
81
+
82
+    public int[] getCompressionAlgorithmIds() {
83
+        int[] array = new int[compressionAlgorithms.size()];
84
+        for (int i = 0; i < array.length; i++) {
85
+            array[i] = compressionAlgorithms.get(i).getAlgorithmId();
86
+        }
87
+        return array;
88
+    }
89
+
90
+    public static AlgorithmSuite getDefaultAlgorithmSuite() {
91
+        return defaultAlgorithmSuite;
92
+    }
93
+}

+ 37
- 0
src/main/java/de/vanitasvitae/crypto/pgpainless/key/algorithm/CompressionAlgorithm.java View File

@@ -0,0 +1,37 @@
1
+package de.vanitasvitae.crypto.pgpainless.key.algorithm;
2
+
3
+import java.util.HashMap;
4
+import java.util.Map;
5
+
6
+import org.bouncycastle.bcpg.CompressionAlgorithmTags;
7
+
8
+public enum CompressionAlgorithm {
9
+
10
+    UNCOMPRESSED(   CompressionAlgorithmTags.UNCOMPRESSED),
11
+    ZIP(            CompressionAlgorithmTags.ZIP),
12
+    ZLIB(           CompressionAlgorithmTags.ZLIB),
13
+    BZIP2(          CompressionAlgorithmTags.BZIP2),
14
+    ;
15
+
16
+    private static final Map<Integer, CompressionAlgorithm> MAP = new HashMap<>();
17
+
18
+    static {
19
+        for (CompressionAlgorithm c : CompressionAlgorithm.values()) {
20
+            MAP.put(c.algorithmId, c);
21
+        }
22
+    }
23
+
24
+    public static CompressionAlgorithm fromId(int id) {
25
+        return MAP.get(id);
26
+    }
27
+
28
+    private final int algorithmId;
29
+
30
+    CompressionAlgorithm(int id) {
31
+        this.algorithmId = id;
32
+    }
33
+
34
+    public int getAlgorithmId() {
35
+        return algorithmId;
36
+    }
37
+}

+ 33
- 0
src/main/java/de/vanitasvitae/crypto/pgpainless/key/algorithm/Feature.java View File

@@ -0,0 +1,33 @@
1
+package de.vanitasvitae.crypto.pgpainless.key.algorithm;
2
+
3
+import java.util.HashMap;
4
+import java.util.Map;
5
+
6
+import org.bouncycastle.bcpg.sig.Features;
7
+
8
+public enum Feature {
9
+    MODIFICATION_DETECTION(Features.FEATURE_MODIFICATION_DETECTION),
10
+    ;
11
+
12
+    private static final Map<Byte, Feature> MAP = new HashMap<>();
13
+
14
+    static {
15
+        for (Feature f : Feature.values()) {
16
+            MAP.put(f.featureId, f);
17
+        }
18
+    }
19
+
20
+    public static Feature fromId(byte id) {
21
+        return MAP.get(id);
22
+    }
23
+
24
+    private final byte featureId;
25
+
26
+    Feature(byte featureId) {
27
+        this.featureId = featureId;
28
+    }
29
+
30
+    public byte getFeatureId() {
31
+        return featureId;
32
+    }
33
+}

+ 44
- 0
src/main/java/de/vanitasvitae/crypto/pgpainless/key/algorithm/HashAlgorithm.java View File

@@ -0,0 +1,44 @@
1
+package de.vanitasvitae.crypto.pgpainless.key.algorithm;
2
+
3
+import java.util.HashMap;
4
+import java.util.Map;
5
+
6
+import org.bouncycastle.bcpg.HashAlgorithmTags;
7
+
8
+public enum HashAlgorithm {
9
+
10
+    MD5(        HashAlgorithmTags.MD5),
11
+    SHA1(       HashAlgorithmTags.SHA1),
12
+    RIPEMD160(  HashAlgorithmTags.RIPEMD160),
13
+    DOUBLE_SHA( HashAlgorithmTags.DOUBLE_SHA),
14
+    MD2(        HashAlgorithmTags.MD2),
15
+    TIGER_192(  HashAlgorithmTags.TIGER_192),
16
+    HAVAL_5_160(HashAlgorithmTags.HAVAL_5_160),
17
+    SHA256(     HashAlgorithmTags.SHA256),
18
+    SHA384(     HashAlgorithmTags.SHA384),
19
+    SHA512(     HashAlgorithmTags.SHA512),
20
+    SHA224(     HashAlgorithmTags.SHA224),
21
+    ;
22
+    //                                                         Coincidence? I don't this so...
23
+    private static final Map<Integer, HashAlgorithm> MAP = new HashMap<>();
24
+
25
+    static {
26
+        for (HashAlgorithm h : HashAlgorithm.values()) {
27
+            MAP.put(h.algorithmId, h);
28
+        }
29
+    }
30
+
31
+    public static HashAlgorithm fromId(int id) {
32
+        return MAP.get(id);
33
+    }
34
+
35
+    private final int algorithmId;
36
+
37
+    HashAlgorithm(int id) {
38
+        this.algorithmId = id;
39
+    }
40
+
41
+    public int getAlgorithmId() {
42
+        return algorithmId;
43
+    }
44
+}

+ 25
- 0
src/main/java/de/vanitasvitae/crypto/pgpainless/key/algorithm/KeyFlag.java View File

@@ -0,0 +1,25 @@
1
+package de.vanitasvitae.crypto.pgpainless.key.algorithm;
2
+
3
+import org.bouncycastle.bcpg.sig.KeyFlags;
4
+
5
+public enum KeyFlag {
6
+
7
+    CERTIFY_OTHER(  KeyFlags.CERTIFY_OTHER),
8
+    SIGN_DATA(      KeyFlags.SIGN_DATA),
9
+    ENCRYPT_COMMS(  KeyFlags.ENCRYPT_COMMS),
10
+    ENCRYPT_STORAGE(KeyFlags.ENCRYPT_STORAGE),
11
+    SPLIT(          KeyFlags.SPLIT),
12
+    AUTHENTICATION( KeyFlags.AUTHENTICATION),
13
+    SHARED(         KeyFlags.SHARED),
14
+    ;
15
+
16
+    private final int flag;
17
+
18
+    KeyFlag(int flag) {
19
+        this.flag = flag;
20
+    }
21
+
22
+    public int getFlag() {
23
+        return flag;
24
+    }
25
+}

+ 46
- 0
src/main/java/de/vanitasvitae/crypto/pgpainless/key/algorithm/PublicKeyAlgorithm.java View File

@@ -0,0 +1,46 @@
1
+package de.vanitasvitae.crypto.pgpainless.key.algorithm;
2
+
3
+import java.util.HashMap;
4
+import java.util.Map;
5
+
6
+import org.bouncycastle.bcpg.PublicKeyAlgorithmTags;
7
+
8
+public enum PublicKeyAlgorithm {
9
+
10
+    RSA_GENERAL(    PublicKeyAlgorithmTags.RSA_GENERAL),
11
+    RSA_ENCRYPT(    PublicKeyAlgorithmTags.RSA_ENCRYPT),
12
+    RSA_SIGN(       PublicKeyAlgorithmTags.RSA_SIGN),
13
+    ELGAMAL_ENCRYPT(PublicKeyAlgorithmTags.ELGAMAL_ENCRYPT),
14
+    DSA(PublicKeyAlgorithmTags.DSA),
15
+    /**
16
+     * @deprecated use {@link #ECDH} instead.
17
+     */
18
+    EC(             PublicKeyAlgorithmTags.EC),
19
+    ECDH(           PublicKeyAlgorithmTags.ECDH),
20
+    ECDSA(          PublicKeyAlgorithmTags.ECDSA),
21
+    ELGAMAL_GENERAL(PublicKeyAlgorithmTags.ELGAMAL_GENERAL),
22
+    DIFFIE_HELLMAN( PublicKeyAlgorithmTags.DIFFIE_HELLMAN),
23
+    ;
24
+
25
+    private static final Map<Integer, PublicKeyAlgorithm> MAP = new HashMap<>();
26
+
27
+    static {
28
+        for (PublicKeyAlgorithm p : PublicKeyAlgorithm.values()) {
29
+            MAP.put(p.algorithmId, p);
30
+        }
31
+    }
32
+
33
+    public static PublicKeyAlgorithm fromId(int id) {
34
+        return MAP.get(id);
35
+    }
36
+
37
+    private final int algorithmId;
38
+
39
+    PublicKeyAlgorithm(int algorithmId) {
40
+        this.algorithmId = algorithmId;
41
+    }
42
+
43
+    public int getAlgorithmId() {
44
+        return algorithmId;
45
+    }
46
+}

+ 47
- 0
src/main/java/de/vanitasvitae/crypto/pgpainless/key/algorithm/SymmetricKeyAlgorithm.java View File

@@ -0,0 +1,47 @@
1
+package de.vanitasvitae.crypto.pgpainless.key.algorithm;
2
+
3
+import java.util.HashMap;
4
+import java.util.Map;
5
+
6
+import org.bouncycastle.bcpg.SymmetricKeyAlgorithmTags;
7
+
8
+public enum SymmetricKeyAlgorithm {
9
+
10
+    NULL(           SymmetricKeyAlgorithmTags.NULL),
11
+    IDEA(           SymmetricKeyAlgorithmTags.IDEA),
12
+    TRIPLE_DES(     SymmetricKeyAlgorithmTags.TRIPLE_DES),
13
+    CAST5(          SymmetricKeyAlgorithmTags.CAST5),
14
+    BLOWFISH(       SymmetricKeyAlgorithmTags.BLOWFISH),
15
+    SAFER(          SymmetricKeyAlgorithmTags.SAFER),
16
+    DES(            SymmetricKeyAlgorithmTags.DES),
17
+    AES_128(        SymmetricKeyAlgorithmTags.AES_128),
18
+    AES_192(        SymmetricKeyAlgorithmTags.AES_192),
19
+    AES_256(        SymmetricKeyAlgorithmTags.AES_256),
20
+    TWOFISH(        SymmetricKeyAlgorithmTags.TWOFISH),
21
+    CAMELLIA_128(   SymmetricKeyAlgorithmTags.CAMELLIA_128),
22
+    CAMELLIA_192(   SymmetricKeyAlgorithmTags.CAMELLIA_192),
23
+    CAMELLIA_256(   SymmetricKeyAlgorithmTags.CAMELLIA_256),
24
+    ;
25
+
26
+    private static final Map<Integer, SymmetricKeyAlgorithm> MAP = new HashMap<>();
27
+
28
+    static {
29
+        for (SymmetricKeyAlgorithm s : SymmetricKeyAlgorithm.values()) {
30
+            MAP.put(s.algorithmId, s);
31
+        }
32
+    }
33
+
34
+    public static SymmetricKeyAlgorithm forId(int id) {
35
+        return MAP.get(id);
36
+    }
37
+
38
+    private final int algorithmId;
39
+
40
+    SymmetricKeyAlgorithm(int algorithmId) {
41
+        this.algorithmId = algorithmId;
42
+    }
43
+
44
+    public int getAlgorithmId() {
45
+        return algorithmId;
46
+    }
47
+}

+ 213
- 0
src/main/java/de/vanitasvitae/crypto/pgpainless/key/generation/KeyRingBuilder.java View File

@@ -0,0 +1,213 @@
1
+package de.vanitasvitae.crypto.pgpainless.key.generation;
2
+
3
+
4
+import java.nio.charset.Charset;
5
+import java.security.KeyPair;
6
+import java.security.KeyPairGenerator;
7
+import java.security.NoSuchAlgorithmException;
8
+import java.security.NoSuchProviderException;
9
+import java.util.ArrayList;
10
+import java.util.Date;
11
+import java.util.List;
12
+
13
+import de.vanitasvitae.crypto.pgpainless.key.algorithm.KeyFlag;
14
+import de.vanitasvitae.crypto.pgpainless.key.generation.type.KeyType;
15
+import org.bouncycastle.bcpg.HashAlgorithmTags;
16
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
17
+import org.bouncycastle.openpgp.PGPEncryptedData;
18
+import org.bouncycastle.openpgp.PGPException;
19
+import org.bouncycastle.openpgp.PGPKeyPair;
20
+import org.bouncycastle.openpgp.PGPKeyRingGenerator;
21
+import org.bouncycastle.openpgp.PGPSecretKeyRing;
22
+import org.bouncycastle.openpgp.PGPSignature;
23
+import org.bouncycastle.openpgp.PGPSignatureSubpacketGenerator;
24
+import org.bouncycastle.openpgp.operator.PBESecretKeyEncryptor;
25
+import org.bouncycastle.openpgp.operator.PGPContentSignerBuilder;
26
+import org.bouncycastle.openpgp.operator.PGPDigestCalculator;
27
+import org.bouncycastle.openpgp.operator.jcajce.JcaPGPContentSignerBuilder;
28
+import org.bouncycastle.openpgp.operator.jcajce.JcaPGPDigestCalculatorProviderBuilder;
29
+import org.bouncycastle.openpgp.operator.jcajce.JcaPGPKeyPair;
30
+import org.bouncycastle.openpgp.operator.jcajce.JcePBESecretKeyEncryptorBuilder;
31
+
32
+public class KeyRingBuilder implements KeyRingBuilderInterface {
33
+
34
+    private final Charset UTF8 = Charset.forName("UTF-8");
35
+
36
+    private List<KeySpec> keySpecs = new ArrayList<>();
37
+    private List<String> userIds = new ArrayList<>();
38
+    private char[] passphrase;
39
+
40
+    @Override
41
+    public WithSubKeyType generateCompositeKeyRing() {
42
+        return new WithSubKeyTypeImpl();
43
+    }
44
+
45
+    @Override
46
+    public WithCertificationKeyType generateSingleKeyKeyRing() {
47
+        return new WithCertificationKeyTypeImpl();
48
+    }
49
+
50
+    class WithSubKeyTypeImpl implements WithSubKeyType {
51
+
52
+        @Override
53
+        public WithSubKeyType withSubKey(KeySpec type) {
54
+            KeyRingBuilder.this.keySpecs.add(type);
55
+            return this;
56
+        }
57
+
58
+        @Override
59
+        public WithCertificationKeyType done() {
60
+            return new WithCertificationKeyTypeImpl();
61
+        }
62
+    }
63
+
64
+    class WithCertificationKeyTypeImpl implements WithCertificationKeyType {
65
+
66
+        @Override
67
+        public WithPrimaryUserId withCertificationKeyType(KeySpec spec) {
68
+            if ((spec.getKeyFlags() & KeyFlag.CERTIFY_OTHER.getFlag()) == 0) {
69
+                throw new IllegalArgumentException("Certification Key MUST have KeyFlag CERTIFY_OTHER");
70
+            }
71
+            KeyRingBuilder.this.keySpecs.add(spec);
72
+            return new WithPrimaryUserIdImpl();
73
+        }
74
+    }
75
+
76
+    class WithPrimaryUserIdImpl implements WithPrimaryUserId {
77
+
78
+        @Override
79
+        public WithAdditionalUserIds withPrimaryUserId(String userId) {
80
+            KeyRingBuilder.this.userIds.add(userId);
81
+            return new WithAdditionalUserIdsImpl();
82
+        }
83
+
84
+        @Override
85
+        public WithAdditionalUserIds withPrimaryUserId(byte[] userId) {
86
+            return withPrimaryUserId(new String(userId, UTF8));
87
+        }
88
+    }
89
+
90
+    class WithAdditionalUserIdsImpl implements WithAdditionalUserIds {
91
+
92
+        @Deprecated
93
+        @Override
94
+        public WithAdditionalUserIds withAdditionalUserId(String userId) {
95
+            KeyRingBuilder.this.userIds.add(userId);
96
+            return this;
97
+        }
98
+
99
+        @Deprecated
100
+        @Override
101
+        public WithAdditionalUserIds withAdditionalUserId(byte[] userId) {
102
+            return withAdditionalUserId(new String(userId, UTF8));
103
+        }
104
+
105
+        @Override
106
+        public WithPassphrase done() {
107
+            return new WithPassphraseImpl();
108
+        }
109
+    }
110
+
111
+    class WithPassphraseImpl implements WithPassphrase {
112
+
113
+        @Override
114
+        public Build withPassphrase(String passphrase) {
115
+            return withPassphrase(passphrase.toCharArray());
116
+        }
117
+
118
+        @Override
119
+        public Build withPassphrase(char[] passphrase) {
120
+            KeyRingBuilder.this.passphrase = passphrase;
121
+            return new BuildImpl();
122
+        }
123
+
124
+        @Override
125
+        public Build withoutPassphrase() {
126
+            KeyRingBuilder.this.passphrase = null;
127
+            return new BuildImpl();
128
+        }
129
+
130
+        class BuildImpl implements Build {
131
+
132
+            @Override
133
+            public PGPSecretKeyRing build() throws NoSuchAlgorithmException, PGPException, NoSuchProviderException {
134
+
135
+                // Hash Calculator
136
+                PGPDigestCalculator calculator = new JcaPGPDigestCalculatorProviderBuilder()
137
+                        .setProvider(BouncyCastleProvider.PROVIDER_NAME)
138
+                        .build()
139
+                        .get(HashAlgorithmTags.SHA1);
140
+
141
+                // Encryptor for encrypting secret keys
142
+                PBESecretKeyEncryptor encryptor = passphrase == null ?
143
+                        null : // unencrypted key pair, otherwise AES-256 encrypted
144
+                        new JcePBESecretKeyEncryptorBuilder(PGPEncryptedData.AES_256, calculator)
145
+                                .setProvider(BouncyCastleProvider.PROVIDER_NAME)
146
+                                .build(passphrase);
147
+
148
+                // First key is the Master Key
149
+                KeySpec certKeySpec = keySpecs.get(0);
150
+                KeyType certKeyType = certKeySpec.getKeyType();
151
+                keySpecs.remove(0); // Remove master key, so that we later only add sub keys.
152
+
153
+                // Generate Master Key
154
+                PGPKeyPair certKey = generateKeyPair(certKeySpec);
155
+
156
+                // Signer for creating self-signature
157
+                PGPContentSignerBuilder signer = new JcaPGPContentSignerBuilder(
158
+                        certKey.getPublicKey().getAlgorithm(), HashAlgorithmTags.SHA256);
159
+
160
+                // Mimic GnuPGs signature sub packets
161
+                PGPSignatureSubpacketGenerator hashedSubPackets = new PGPSignatureSubpacketGenerator();
162
+
163
+                // Key flags
164
+                hashedSubPackets.setKeyFlags(true, certKeySpec.getKeyFlags());
165
+
166
+                // Encryption Algorithms
167
+                hashedSubPackets.setPreferredSymmetricAlgorithms(true,
168
+                        certKeySpec.getPreferredAlgorithms().getSymmetricKeyAlgorithmIds());
169
+
170
+                // Hash Algorithms
171
+                hashedSubPackets.setPreferredHashAlgorithms(true,
172
+                        certKeySpec.getPreferredAlgorithms().getHashAlgorithmIds());
173
+
174
+                // Compression Algorithms
175
+                hashedSubPackets.setPreferredCompressionAlgorithms(true,
176
+                        certKeySpec.getPreferredAlgorithms().getCompressionAlgorithmIds());
177
+
178
+                // Modification Detection
179
+                hashedSubPackets.setFeature(true, certKeySpec.getFeatures());
180
+
181
+                // Generator which the user can get the key pair from
182
+                PGPKeyRingGenerator ringGenerator = new PGPKeyRingGenerator(
183
+                        PGPSignature.POSITIVE_CERTIFICATION, certKey,
184
+                        userIds.get(0), calculator,
185
+                        hashedSubPackets.generate(), null, signer, encryptor);
186
+
187
+                for (KeySpec subKeySpec : keySpecs) {
188
+                    PGPKeyPair subKey = generateKeyPair(subKeySpec);
189
+                    ringGenerator.addSubKey(subKey);
190
+                }
191
+
192
+                return ringGenerator.generateSecretKeyRing();
193
+            }
194
+
195
+            private PGPKeyPair generateKeyPair(KeySpec spec)
196
+                    throws NoSuchProviderException, NoSuchAlgorithmException, PGPException {
197
+                KeyType type = spec.getKeyType();
198
+                KeyPairGenerator certKeyGenerator = KeyPairGenerator.getInstance(
199
+                        type.getName(), BouncyCastleProvider.PROVIDER_NAME);
200
+                certKeyGenerator.initialize(type.getLength());
201
+
202
+                // Create raw Key Pair
203
+                KeyPair rawKeyPair = certKeyGenerator.generateKeyPair();
204
+
205
+                // Form PGP key pair
206
+                PGPKeyPair pgpKeyPair = new JcaPGPKeyPair(type.getAlgorithm().getAlgorithmId(),
207
+                        rawKeyPair, new Date());
208
+
209
+                return pgpKeyPair;
210
+            }
211
+        }
212
+    }
213
+}

+ 58
- 0
src/main/java/de/vanitasvitae/crypto/pgpainless/key/generation/KeyRingBuilderInterface.java View File

@@ -0,0 +1,58 @@
1
+package de.vanitasvitae.crypto.pgpainless.key.generation;
2
+
3
+import java.security.NoSuchAlgorithmException;
4
+import java.security.NoSuchProviderException;
5
+
6
+import org.bouncycastle.openpgp.PGPException;
7
+import org.bouncycastle.openpgp.PGPSecretKeyRing;
8
+
9
+public interface KeyRingBuilderInterface {
10
+
11
+    WithSubKeyType generateCompositeKeyRing();
12
+
13
+    WithCertificationKeyType generateSingleKeyKeyRing();
14
+
15
+    interface WithSubKeyType {
16
+
17
+        WithSubKeyType withSubKey(KeySpec keySpec);
18
+
19
+        WithCertificationKeyType done();
20
+    }
21
+
22
+    interface WithCertificationKeyType {
23
+        WithPrimaryUserId withCertificationKeyType(KeySpec keySpec);
24
+    }
25
+
26
+    interface WithPrimaryUserId {
27
+
28
+        WithAdditionalUserIds withPrimaryUserId(String userId);
29
+
30
+        WithAdditionalUserIds withPrimaryUserId(byte[] userId);
31
+
32
+    }
33
+
34
+    interface WithAdditionalUserIds {
35
+
36
+        WithAdditionalUserIds withAdditionalUserId(String userId);
37
+
38
+        WithAdditionalUserIds withAdditionalUserId(byte[] userId);
39
+
40
+        WithPassphrase done();
41
+
42
+    }
43
+
44
+    interface WithPassphrase {
45
+
46
+        Build withPassphrase(String passphrase);
47
+
48
+        Build withPassphrase(char[] passphrase);
49
+
50
+        Build withoutPassphrase();
51
+    }
52
+
53
+    interface Build {
54
+
55
+        PGPSecretKeyRing build() throws NoSuchAlgorithmException, PGPException, NoSuchProviderException;
56
+
57
+    }
58
+}

+ 49
- 0
src/main/java/de/vanitasvitae/crypto/pgpainless/key/generation/KeySpec.java View File

@@ -0,0 +1,49 @@
1
+package de.vanitasvitae.crypto.pgpainless.key.generation;
2
+
3
+import java.util.Set;
4
+
5
+import de.vanitasvitae.crypto.pgpainless.key.algorithm.AlgorithmSuite;
6
+import de.vanitasvitae.crypto.pgpainless.key.algorithm.Feature;
7
+import de.vanitasvitae.crypto.pgpainless.key.generation.type.KeyType;
8
+
9
+public class KeySpec {
10
+
11
+    private final KeyType keyType;
12
+    private final int keyFlags;
13
+    private final AlgorithmSuite algorithmSuite;
14
+    private final Set<Feature> features;
15
+
16
+    KeySpec(KeyType type,
17
+                   int keyFlags,
18
+                   AlgorithmSuite preferredAlgorithms,
19
+                   Set<Feature> features) {
20
+        this.keyType = type;
21
+        this.keyFlags = keyFlags;
22
+        this.algorithmSuite = preferredAlgorithms;
23
+        this.features = features;
24
+    }
25
+
26
+    KeyType getKeyType() {
27
+        return keyType;
28
+    }
29
+
30
+    int getKeyFlags() {
31
+        return keyFlags;
32
+    }
33
+
34
+    AlgorithmSuite getPreferredAlgorithms() {
35
+        return algorithmSuite;
36
+    }
37
+
38
+    byte getFeatures() {
39
+        byte val = 0;
40
+        for (Feature f : features) {
41
+            val |= f.getFeatureId();
42
+        }
43
+        return val;
44
+    }
45
+
46
+    public static KeySpecBuilder getBuilder() {
47
+        return new KeySpecBuilder();
48
+    }
49
+}

+ 140
- 0
src/main/java/de/vanitasvitae/crypto/pgpainless/key/generation/KeySpecBuilder.java View File

@@ -0,0 +1,140 @@
1
+package de.vanitasvitae.crypto.pgpainless.key.generation;
2
+
3
+import java.util.Arrays;
4
+import java.util.HashSet;
5
+import java.util.Set;
6
+
7
+import de.vanitasvitae.crypto.pgpainless.key.algorithm.AlgorithmSuite;
8
+import de.vanitasvitae.crypto.pgpainless.key.algorithm.CompressionAlgorithm;
9
+import de.vanitasvitae.crypto.pgpainless.key.algorithm.Feature;
10
+import de.vanitasvitae.crypto.pgpainless.key.algorithm.HashAlgorithm;
11
+import de.vanitasvitae.crypto.pgpainless.key.algorithm.KeyFlag;
12
+import de.vanitasvitae.crypto.pgpainless.key.algorithm.SymmetricKeyAlgorithm;
13
+import de.vanitasvitae.crypto.pgpainless.key.generation.type.KeyType;
14
+
15
+public class KeySpecBuilder implements KeySpecBuilderInterface {
16
+
17
+    private KeyType type;
18
+    private int keyFlags;
19
+    private AlgorithmSuite algorithmSuite = AlgorithmSuite.getDefaultAlgorithmSuite();
20
+    private Set<Feature> features = new HashSet<>();
21
+
22
+    @Override
23
+    public WithKeyFlags ofType(KeyType type) {
24
+        KeySpecBuilder.this.type = type;
25
+        return new WithKeyFlagsImpl();
26
+    }
27
+
28
+    class WithKeyFlagsImpl implements WithKeyFlags {
29
+
30
+        @Override
31
+        public WithDetailedConfiguration withKeyFlags(KeyFlag... flags) {
32
+            int val = 0;
33
+            for (KeyFlag f : flags) {
34
+                val |= f.getFlag();
35
+            }
36
+            KeySpecBuilder.this.keyFlags = val;
37
+            return new WithDetailedConfigurationImpl();
38
+        }
39
+
40
+        @Override
41
+        public WithDetailedConfiguration withDefaultKeyFlags() {
42
+            return withKeyFlags(
43
+                    KeyFlag.CERTIFY_OTHER,
44
+                    KeyFlag.SIGN_DATA,
45
+                    KeyFlag.ENCRYPT_COMMS,
46
+                    KeyFlag.ENCRYPT_STORAGE,
47
+                    KeyFlag.AUTHENTICATION);
48
+        }
49
+    }
50
+
51
+    class WithDetailedConfigurationImpl implements WithDetailedConfiguration {
52
+
53
+        @Deprecated
54
+        @Override
55
+        public WithPreferredSymmetricAlgorithms withDetailedConfiguration() {
56
+            return new WithPreferredSymmetricAlgorithmsImpl();
57
+        }
58
+
59
+        @Override
60
+        public KeySpec withStandardConfiguration() {
61
+            return new KeySpec(
62
+                    KeySpecBuilder.this.type,
63
+                    KeySpecBuilder.this.keyFlags,
64
+                    KeySpecBuilder.this.algorithmSuite,
65
+                    KeySpecBuilder.this.features);
66
+        }
67
+    }
68
+
69
+    class WithPreferredSymmetricAlgorithmsImpl implements WithPreferredSymmetricAlgorithms {
70
+
71
+        @Override
72
+        public WithPreferredHashAlgorithms withPreferredSymmetricAlgorithms(SymmetricKeyAlgorithm... algorithms) {
73
+            KeySpecBuilder.this.algorithmSuite.setSymmetricKeyAlgorithms(Arrays.asList(algorithms));
74
+            return new WithPreferredHashAlgorithmsImpl();
75
+        }
76
+
77
+        @Override
78
+        public WithPreferredHashAlgorithms withDefaultSymmetricAlgorithms() {
79
+            KeySpecBuilder.this.algorithmSuite.setSymmetricKeyAlgorithms(
80
+                    AlgorithmSuite.getDefaultAlgorithmSuite().getSymmetricKeyAlgorithms());
81
+            return new WithPreferredHashAlgorithmsImpl();
82
+        }
83
+
84
+        @Override
85
+        public WithFeatures withDefaultAlgorithms() {
86
+            KeySpecBuilder.this.algorithmSuite = AlgorithmSuite.getDefaultAlgorithmSuite();
87
+            return new WithFeaturesImpl();
88
+        }
89
+    }
90
+
91
+    class WithPreferredHashAlgorithmsImpl implements WithPreferredHashAlgorithms {
92
+
93
+        @Override
94
+        public WithPreferredCompressionAlgorithms withPreferredHashAlgorithms(HashAlgorithm... algorithms) {
95
+            KeySpecBuilder.this.algorithmSuite.setHashAlgorithms(Arrays.asList(algorithms));
96
+            return new WithPreferredCompressionAlgorithmsImpl();
97
+        }
98
+
99
+        @Override
100
+        public WithPreferredCompressionAlgorithms withDefaultHashAlgorithms() {
101
+            KeySpecBuilder.this.algorithmSuite.setHashAlgorithms(
102
+                    AlgorithmSuite.getDefaultAlgorithmSuite().getHashAlgorithms());
103
+            return new WithPreferredCompressionAlgorithmsImpl();
104
+        }
105
+    }
106
+
107
+    class WithPreferredCompressionAlgorithmsImpl implements WithPreferredCompressionAlgorithms {
108
+
109
+        @Override
110
+        public WithFeatures withPreferredCompressionAlgorithms(CompressionAlgorithm... algorithms) {
111
+            KeySpecBuilder.this.algorithmSuite.setCompressionAlgorithms(Arrays.asList(algorithms));
112
+            return new WithFeaturesImpl();
113
+        }
114
+
115
+        @Override
116
+        public WithFeatures withDefaultCompressionAlgorithms() {
117
+            KeySpecBuilder.this.algorithmSuite.setCompressionAlgorithms(
118
+                    AlgorithmSuite.getDefaultAlgorithmSuite().getCompressionAlgorithms());
119
+            return new WithFeaturesImpl();
120
+        }
121
+    }
122
+
123
+    class WithFeaturesImpl implements WithFeatures {
124
+
125
+        @Override
126
+        public WithFeatures withFeature(Feature feature) {
127
+            KeySpecBuilder.this.features.add(feature);
128
+            return this;
129
+        }
130
+
131
+        @Override
132
+        public KeySpec done() {
133
+            return new KeySpec(
134
+                    KeySpecBuilder.this.type,
135
+                    KeySpecBuilder.this.keyFlags,
136
+                    KeySpecBuilder.this.algorithmSuite,
137
+                    KeySpecBuilder.this.features);
138
+        }
139
+    }
140
+}

+ 62
- 0
src/main/java/de/vanitasvitae/crypto/pgpainless/key/generation/KeySpecBuilderInterface.java View File

@@ -0,0 +1,62 @@
1
+package de.vanitasvitae.crypto.pgpainless.key.generation;
2
+
3
+import de.vanitasvitae.crypto.pgpainless.key.algorithm.AlgorithmSuite;
4
+import de.vanitasvitae.crypto.pgpainless.key.algorithm.CompressionAlgorithm;
5
+import de.vanitasvitae.crypto.pgpainless.key.algorithm.Feature;
6
+import de.vanitasvitae.crypto.pgpainless.key.algorithm.HashAlgorithm;
7
+import de.vanitasvitae.crypto.pgpainless.key.algorithm.KeyFlag;
8
+import de.vanitasvitae.crypto.pgpainless.key.algorithm.SymmetricKeyAlgorithm;
9
+import de.vanitasvitae.crypto.pgpainless.key.generation.type.KeyType;
10
+
11
+public interface KeySpecBuilderInterface {
12
+
13
+    WithKeyFlags ofType(KeyType type);
14
+
15
+    interface WithKeyFlags {
16
+
17
+        WithDetailedConfiguration withKeyFlags(KeyFlag... flags);
18
+
19
+        WithDetailedConfiguration withDefaultKeyFlags();
20
+    }
21
+
22
+    interface WithDetailedConfiguration {
23
+
24
+        WithPreferredSymmetricAlgorithms withDetailedConfiguration();
25
+
26
+        KeySpec withStandardConfiguration();
27
+    }
28
+
29
+    interface WithPreferredSymmetricAlgorithms {
30
+
31
+        WithPreferredHashAlgorithms withPreferredSymmetricAlgorithms(SymmetricKeyAlgorithm... algorithms);
32
+
33
+        WithPreferredHashAlgorithms withDefaultSymmetricAlgorithms();
34
+
35
+        WithFeatures withDefaultAlgorithms();
36
+
37
+    }
38
+
39
+    interface WithPreferredHashAlgorithms {
40
+
41
+        WithPreferredCompressionAlgorithms withPreferredHashAlgorithms(HashAlgorithm... algorithms);
42
+
43
+        WithPreferredCompressionAlgorithms withDefaultHashAlgorithms();
44
+
45
+    }
46
+
47
+    interface WithPreferredCompressionAlgorithms {
48
+
49
+        WithFeatures withPreferredCompressionAlgorithms(CompressionAlgorithm... algorithms);
50
+
51
+        WithFeatures withDefaultCompressionAlgorithms();
52
+
53
+    }
54
+
55
+    interface WithFeatures {
56
+
57
+        WithFeatures withFeature(Feature feature);
58
+
59
+        KeySpec done();
60
+    }
61
+
62
+}

+ 36
- 0
src/main/java/de/vanitasvitae/crypto/pgpainless/key/generation/type/DSA.java View File

@@ -0,0 +1,36 @@
1
+package de.vanitasvitae.crypto.pgpainless.key.generation.type;
2
+
3
+import java.security.KeyPairGenerator;
4
+import java.security.NoSuchAlgorithmException;
5
+
6
+import de.vanitasvitae.crypto.pgpainless.key.algorithm.PublicKeyAlgorithm;
7
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
8
+
9
+public enum DSA implements KeyType {
10
+
11
+    _1024(1024),
12
+    _2048(2048),
13
+    _3072(3072),
14
+    ;
15
+
16
+    private final int length;
17
+
18
+    DSA(int length) {
19
+        this.length = length;
20
+    }
21
+
22
+    @Override
23
+    public int getLength() {
24
+        return length;
25
+    }
26
+
27
+    @Override
28
+    public String getName() {
29
+        return "DSA";
30
+    }
31
+
32
+    @Override
33
+    public PublicKeyAlgorithm getAlgorithm() {
34
+        return PublicKeyAlgorithm.DSA;
35
+    }
36
+}

+ 32
- 0
src/main/java/de/vanitasvitae/crypto/pgpainless/key/generation/type/ElGamal_ENCRYPT.java View File

@@ -0,0 +1,32 @@
1
+package de.vanitasvitae.crypto.pgpainless.key.generation.type;
2
+
3
+import de.vanitasvitae.crypto.pgpainless.key.algorithm.PublicKeyAlgorithm;
4
+
5
+public enum ElGamal_ENCRYPT implements KeyType {
6
+
7
+    _1024(1024),
8
+    _2048(2048),
9
+    _3072(3072),
10
+    ;
11
+
12
+    private final int length;
13
+
14
+    ElGamal_ENCRYPT(int length) {
15
+        this.length = length;
16
+    }
17
+
18
+    @Override
19
+    public int getLength() {
20
+        return length;
21
+    }
22
+
23
+    @Override
24
+    public String getName() {
25
+        return "ElGamal";
26
+    }
27
+
28
+    @Override
29
+    public PublicKeyAlgorithm getAlgorithm() {
30
+        return PublicKeyAlgorithm.ELGAMAL_ENCRYPT;
31
+    }
32
+}

+ 12
- 0
src/main/java/de/vanitasvitae/crypto/pgpainless/key/generation/type/KeyType.java View File

@@ -0,0 +1,12 @@
1
+package de.vanitasvitae.crypto.pgpainless.key.generation.type;
2
+
3
+import de.vanitasvitae.crypto.pgpainless.key.algorithm.PublicKeyAlgorithm;
4
+
5
+public interface KeyType {
6
+
7
+    int getLength();
8
+
9
+    String getName();
10
+
11
+    PublicKeyAlgorithm getAlgorithm();
12
+}

+ 36
- 0
src/main/java/de/vanitasvitae/crypto/pgpainless/key/generation/type/RSA_GENERAL.java View File

@@ -0,0 +1,36 @@
1
+package de.vanitasvitae.crypto.pgpainless.key.generation.type;
2
+
3
+import de.vanitasvitae.crypto.pgpainless.key.algorithm.PublicKeyAlgorithm;
4
+
5
+public enum RSA_GENERAL implements KeyType {
6
+
7
+    @Deprecated
8
+    _1024(1024),
9
+    @Deprecated
10
+    _2048(2048),
11
+    _3072(3072),
12
+    _4096(4096),
13
+    _8192(8192),
14
+    ;
15
+
16
+    private final int length;
17
+
18
+    RSA_GENERAL(int length) {
19
+        this.length = length;
20
+    }
21
+
22
+    @Override
23
+    public int getLength() {
24
+        return length;
25
+    }
26
+
27
+    @Override
28
+    public String getName() {
29
+        return "RSA";
30
+    }
31
+
32
+    @Override
33
+    public PublicKeyAlgorithm getAlgorithm() {
34
+        return PublicKeyAlgorithm.RSA_GENERAL;
35
+    }
36
+}

Loading…
Cancel
Save