commit 6dd2e83acf4bf9665ba1e17f42740a9456cc49b7 Author: Paul Schaub Date: Sat Jun 2 21:21:35 2018 +0200 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..bb249db5 --- /dev/null +++ b/.gitignore @@ -0,0 +1,14 @@ +.idea +.gradle + +out/ + +*.iws +*.iml +*.ipr +*.class +*.log +*.jar + + +!gradle-wrapper.jar diff --git a/build.gradle b/build.gradle new file mode 100644 index 00000000..a270fed1 --- /dev/null +++ b/build.gradle @@ -0,0 +1,18 @@ +plugins { + id 'java' +} + +group 'de.vanitasvitae.crypto' +version '0.1-SNAPSHOT' + +sourceCompatibility = 1.8 + +repositories { + mavenCentral() +} + +dependencies { + testCompile group: 'junit', name: 'junit', version: '4.12' + compile 'org.bouncycastle:bcprov-jdk15on:1.59' + compile 'org.bouncycastle:bcpg-jdk15on:1.59' +} diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 00000000..01b8bf6b Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 00000000..933b6473 --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-bin.zip diff --git a/gradlew b/gradlew new file mode 100755 index 00000000..cccdd3d5 --- /dev/null +++ b/gradlew @@ -0,0 +1,172 @@ +#!/usr/bin/env sh + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=$(save "$@") + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong +if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then + cd "$(dirname "$0")" +fi + +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 00000000..e95643d6 --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,84 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windows variants + +if not "%OS%" == "Windows_NT" goto win9xME_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 00000000..eecf6f51 --- /dev/null +++ b/settings.gradle @@ -0,0 +1,2 @@ +rootProject.name = 'pgpainless' + diff --git a/src/main/java/de/vanitasvitae/crypto/pgpainless/EncryptionBuilder.java b/src/main/java/de/vanitasvitae/crypto/pgpainless/EncryptionBuilder.java new file mode 100644 index 00000000..a5b2a2a8 --- /dev/null +++ b/src/main/java/de/vanitasvitae/crypto/pgpainless/EncryptionBuilder.java @@ -0,0 +1,5 @@ +package de.vanitasvitae.crypto.pgpainless; + +public class EncryptionBuilder { + +} diff --git a/src/main/java/de/vanitasvitae/crypto/pgpainless/Main.java b/src/main/java/de/vanitasvitae/crypto/pgpainless/Main.java new file mode 100644 index 00000000..5618c144 --- /dev/null +++ b/src/main/java/de/vanitasvitae/crypto/pgpainless/Main.java @@ -0,0 +1,44 @@ +package de.vanitasvitae.crypto.pgpainless; + +import java.io.IOException; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.Security; +import java.util.Base64; + +import de.vanitasvitae.crypto.pgpainless.key.algorithm.KeyFlag; +import de.vanitasvitae.crypto.pgpainless.key.generation.KeySpec; +import de.vanitasvitae.crypto.pgpainless.key.generation.type.DSA; +import de.vanitasvitae.crypto.pgpainless.key.generation.type.RSA_GENERAL; +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.bouncycastle.openpgp.PGPException; +import org.bouncycastle.openpgp.PGPSecretKeyRing; + +public class Main { + + public static void main(String[] args) + throws NoSuchAlgorithmException, PGPException, NoSuchProviderException, IOException { + Security.addProvider(new BouncyCastleProvider()); + PGPSecretKeyRing secretKeys = PGPainless.generateKeyRing() + .generateCompositeKeyRing() + .withSubKey( + KeySpec.getBuilder() + .ofType(RSA_GENERAL._4096) + .withKeyFlags(KeyFlag.ENCRYPT_COMMS, KeyFlag.ENCRYPT_STORAGE) + .withStandardConfiguration()) + .done() + .withCertificationKeyType( + KeySpec.getBuilder() + .ofType(DSA._3072) + .withKeyFlags(KeyFlag.SIGN_DATA) + .withStandardConfiguration()) + .withPrimaryUserId("Test123") + .done() + .withoutPassphrase() + .build(); + + byte[] base64 = Base64.getEncoder().encode(secretKeys.getEncoded()); + + System.out.println(new String(base64)); + } +} diff --git a/src/main/java/de/vanitasvitae/crypto/pgpainless/PGPainless.java b/src/main/java/de/vanitasvitae/crypto/pgpainless/PGPainless.java new file mode 100644 index 00000000..90573165 --- /dev/null +++ b/src/main/java/de/vanitasvitae/crypto/pgpainless/PGPainless.java @@ -0,0 +1,10 @@ +package de.vanitasvitae.crypto.pgpainless; + +import de.vanitasvitae.crypto.pgpainless.key.generation.KeyRingBuilder; + +public class PGPainless { + + public static KeyRingBuilder generateKeyRing() { + return new KeyRingBuilder(); + } +} diff --git a/src/main/java/de/vanitasvitae/crypto/pgpainless/PainlessResult.java b/src/main/java/de/vanitasvitae/crypto/pgpainless/PainlessResult.java new file mode 100644 index 00000000..c5c9d87d --- /dev/null +++ b/src/main/java/de/vanitasvitae/crypto/pgpainless/PainlessResult.java @@ -0,0 +1,8 @@ +package de.vanitasvitae.crypto.pgpainless; + +import java.util.Set; + +public class PainlessResult { + Set signingKeys; + Long decryptingKey; +} diff --git a/src/main/java/de/vanitasvitae/crypto/pgpainless/key/algorithm/AlgorithmSuite.java b/src/main/java/de/vanitasvitae/crypto/pgpainless/key/algorithm/AlgorithmSuite.java new file mode 100644 index 00000000..8d1449e9 --- /dev/null +++ b/src/main/java/de/vanitasvitae/crypto/pgpainless/key/algorithm/AlgorithmSuite.java @@ -0,0 +1,93 @@ +package de.vanitasvitae.crypto.pgpainless.key.algorithm; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import com.sun.istack.internal.NotNull; + +public class AlgorithmSuite { + + private static AlgorithmSuite defaultAlgorithmSuite = new AlgorithmSuite( + Arrays.asList( + SymmetricKeyAlgorithm.AES_256, + SymmetricKeyAlgorithm.AES_192, + SymmetricKeyAlgorithm.AES_128), + Arrays.asList( + HashAlgorithm.SHA512, + HashAlgorithm.SHA384, + HashAlgorithm.SHA256, + HashAlgorithm.SHA224, + HashAlgorithm.SHA1), + Arrays.asList( + CompressionAlgorithm.ZLIB, + CompressionAlgorithm.BZIP2, + CompressionAlgorithm.ZIP, + CompressionAlgorithm.UNCOMPRESSED) + ); + + private List symmetricKeyAlgorithms; + private List hashAlgorithms; + private List compressionAlgorithms; + + public AlgorithmSuite(@NotNull List symmetricKeyAlgorithms, + @NotNull List hashAlgorithms, + @NotNull List compressionAlgorithms) { + this.symmetricKeyAlgorithms = Collections.unmodifiableList(symmetricKeyAlgorithms); + this.hashAlgorithms = Collections.unmodifiableList(hashAlgorithms); + this.compressionAlgorithms = Collections.unmodifiableList(compressionAlgorithms); + } + + public void setSymmetricKeyAlgorithms(@NotNull List symmetricKeyAlgorithms) { + this.symmetricKeyAlgorithms = symmetricKeyAlgorithms; + } + + public List getSymmetricKeyAlgorithms() { + return new ArrayList<>(symmetricKeyAlgorithms); + } + + public int[] getSymmetricKeyAlgorithmIds() { + int[] array = new int[symmetricKeyAlgorithms.size()]; + for (int i = 0; i < array.length; i++) { + array[i] = symmetricKeyAlgorithms.get(i).getAlgorithmId(); + } + return array; + } + + public void setHashAlgorithms(@NotNull List hashAlgorithms) { + this.hashAlgorithms = hashAlgorithms; + } + + public List getHashAlgorithms() { + return hashAlgorithms; + } + + public int[] getHashAlgorithmIds() { + int[] array = new int[hashAlgorithms.size()]; + for (int i = 0; i < array.length; i++) { + array[i] = hashAlgorithms.get(i).getAlgorithmId(); + } + return array; + } + + public void setCompressionAlgorithms(@NotNull List compressionAlgorithms) { + this.compressionAlgorithms = compressionAlgorithms; + } + + public List getCompressionAlgorithms() { + return compressionAlgorithms; + } + + public int[] getCompressionAlgorithmIds() { + int[] array = new int[compressionAlgorithms.size()]; + for (int i = 0; i < array.length; i++) { + array[i] = compressionAlgorithms.get(i).getAlgorithmId(); + } + return array; + } + + public static AlgorithmSuite getDefaultAlgorithmSuite() { + return defaultAlgorithmSuite; + } +} diff --git a/src/main/java/de/vanitasvitae/crypto/pgpainless/key/algorithm/CompressionAlgorithm.java b/src/main/java/de/vanitasvitae/crypto/pgpainless/key/algorithm/CompressionAlgorithm.java new file mode 100644 index 00000000..ceda111e --- /dev/null +++ b/src/main/java/de/vanitasvitae/crypto/pgpainless/key/algorithm/CompressionAlgorithm.java @@ -0,0 +1,37 @@ +package de.vanitasvitae.crypto.pgpainless.key.algorithm; + +import java.util.HashMap; +import java.util.Map; + +import org.bouncycastle.bcpg.CompressionAlgorithmTags; + +public enum CompressionAlgorithm { + + UNCOMPRESSED( CompressionAlgorithmTags.UNCOMPRESSED), + ZIP( CompressionAlgorithmTags.ZIP), + ZLIB( CompressionAlgorithmTags.ZLIB), + BZIP2( CompressionAlgorithmTags.BZIP2), + ; + + private static final Map MAP = new HashMap<>(); + + static { + for (CompressionAlgorithm c : CompressionAlgorithm.values()) { + MAP.put(c.algorithmId, c); + } + } + + public static CompressionAlgorithm fromId(int id) { + return MAP.get(id); + } + + private final int algorithmId; + + CompressionAlgorithm(int id) { + this.algorithmId = id; + } + + public int getAlgorithmId() { + return algorithmId; + } +} diff --git a/src/main/java/de/vanitasvitae/crypto/pgpainless/key/algorithm/Feature.java b/src/main/java/de/vanitasvitae/crypto/pgpainless/key/algorithm/Feature.java new file mode 100644 index 00000000..468f17cc --- /dev/null +++ b/src/main/java/de/vanitasvitae/crypto/pgpainless/key/algorithm/Feature.java @@ -0,0 +1,33 @@ +package de.vanitasvitae.crypto.pgpainless.key.algorithm; + +import java.util.HashMap; +import java.util.Map; + +import org.bouncycastle.bcpg.sig.Features; + +public enum Feature { + MODIFICATION_DETECTION(Features.FEATURE_MODIFICATION_DETECTION), + ; + + private static final Map MAP = new HashMap<>(); + + static { + for (Feature f : Feature.values()) { + MAP.put(f.featureId, f); + } + } + + public static Feature fromId(byte id) { + return MAP.get(id); + } + + private final byte featureId; + + Feature(byte featureId) { + this.featureId = featureId; + } + + public byte getFeatureId() { + return featureId; + } +} diff --git a/src/main/java/de/vanitasvitae/crypto/pgpainless/key/algorithm/HashAlgorithm.java b/src/main/java/de/vanitasvitae/crypto/pgpainless/key/algorithm/HashAlgorithm.java new file mode 100644 index 00000000..c447d782 --- /dev/null +++ b/src/main/java/de/vanitasvitae/crypto/pgpainless/key/algorithm/HashAlgorithm.java @@ -0,0 +1,44 @@ +package de.vanitasvitae.crypto.pgpainless.key.algorithm; + +import java.util.HashMap; +import java.util.Map; + +import org.bouncycastle.bcpg.HashAlgorithmTags; + +public enum HashAlgorithm { + + MD5( HashAlgorithmTags.MD5), + SHA1( HashAlgorithmTags.SHA1), + RIPEMD160( HashAlgorithmTags.RIPEMD160), + DOUBLE_SHA( HashAlgorithmTags.DOUBLE_SHA), + MD2( HashAlgorithmTags.MD2), + TIGER_192( HashAlgorithmTags.TIGER_192), + HAVAL_5_160(HashAlgorithmTags.HAVAL_5_160), + SHA256( HashAlgorithmTags.SHA256), + SHA384( HashAlgorithmTags.SHA384), + SHA512( HashAlgorithmTags.SHA512), + SHA224( HashAlgorithmTags.SHA224), + ; + // Coincidence? I don't this so... + private static final Map MAP = new HashMap<>(); + + static { + for (HashAlgorithm h : HashAlgorithm.values()) { + MAP.put(h.algorithmId, h); + } + } + + public static HashAlgorithm fromId(int id) { + return MAP.get(id); + } + + private final int algorithmId; + + HashAlgorithm(int id) { + this.algorithmId = id; + } + + public int getAlgorithmId() { + return algorithmId; + } +} diff --git a/src/main/java/de/vanitasvitae/crypto/pgpainless/key/algorithm/KeyFlag.java b/src/main/java/de/vanitasvitae/crypto/pgpainless/key/algorithm/KeyFlag.java new file mode 100644 index 00000000..924b68fa --- /dev/null +++ b/src/main/java/de/vanitasvitae/crypto/pgpainless/key/algorithm/KeyFlag.java @@ -0,0 +1,25 @@ +package de.vanitasvitae.crypto.pgpainless.key.algorithm; + +import org.bouncycastle.bcpg.sig.KeyFlags; + +public enum KeyFlag { + + CERTIFY_OTHER( KeyFlags.CERTIFY_OTHER), + SIGN_DATA( KeyFlags.SIGN_DATA), + ENCRYPT_COMMS( KeyFlags.ENCRYPT_COMMS), + ENCRYPT_STORAGE(KeyFlags.ENCRYPT_STORAGE), + SPLIT( KeyFlags.SPLIT), + AUTHENTICATION( KeyFlags.AUTHENTICATION), + SHARED( KeyFlags.SHARED), + ; + + private final int flag; + + KeyFlag(int flag) { + this.flag = flag; + } + + public int getFlag() { + return flag; + } +} diff --git a/src/main/java/de/vanitasvitae/crypto/pgpainless/key/algorithm/PublicKeyAlgorithm.java b/src/main/java/de/vanitasvitae/crypto/pgpainless/key/algorithm/PublicKeyAlgorithm.java new file mode 100644 index 00000000..fb734721 --- /dev/null +++ b/src/main/java/de/vanitasvitae/crypto/pgpainless/key/algorithm/PublicKeyAlgorithm.java @@ -0,0 +1,46 @@ +package de.vanitasvitae.crypto.pgpainless.key.algorithm; + +import java.util.HashMap; +import java.util.Map; + +import org.bouncycastle.bcpg.PublicKeyAlgorithmTags; + +public enum PublicKeyAlgorithm { + + RSA_GENERAL( PublicKeyAlgorithmTags.RSA_GENERAL), + RSA_ENCRYPT( PublicKeyAlgorithmTags.RSA_ENCRYPT), + RSA_SIGN( PublicKeyAlgorithmTags.RSA_SIGN), + ELGAMAL_ENCRYPT(PublicKeyAlgorithmTags.ELGAMAL_ENCRYPT), + DSA(PublicKeyAlgorithmTags.DSA), + /** + * @deprecated use {@link #ECDH} instead. + */ + EC( PublicKeyAlgorithmTags.EC), + ECDH( PublicKeyAlgorithmTags.ECDH), + ECDSA( PublicKeyAlgorithmTags.ECDSA), + ELGAMAL_GENERAL(PublicKeyAlgorithmTags.ELGAMAL_GENERAL), + DIFFIE_HELLMAN( PublicKeyAlgorithmTags.DIFFIE_HELLMAN), + ; + + private static final Map MAP = new HashMap<>(); + + static { + for (PublicKeyAlgorithm p : PublicKeyAlgorithm.values()) { + MAP.put(p.algorithmId, p); + } + } + + public static PublicKeyAlgorithm fromId(int id) { + return MAP.get(id); + } + + private final int algorithmId; + + PublicKeyAlgorithm(int algorithmId) { + this.algorithmId = algorithmId; + } + + public int getAlgorithmId() { + return algorithmId; + } +} diff --git a/src/main/java/de/vanitasvitae/crypto/pgpainless/key/algorithm/SymmetricKeyAlgorithm.java b/src/main/java/de/vanitasvitae/crypto/pgpainless/key/algorithm/SymmetricKeyAlgorithm.java new file mode 100644 index 00000000..1c813ec6 --- /dev/null +++ b/src/main/java/de/vanitasvitae/crypto/pgpainless/key/algorithm/SymmetricKeyAlgorithm.java @@ -0,0 +1,47 @@ +package de.vanitasvitae.crypto.pgpainless.key.algorithm; + +import java.util.HashMap; +import java.util.Map; + +import org.bouncycastle.bcpg.SymmetricKeyAlgorithmTags; + +public enum SymmetricKeyAlgorithm { + + NULL( SymmetricKeyAlgorithmTags.NULL), + IDEA( SymmetricKeyAlgorithmTags.IDEA), + TRIPLE_DES( SymmetricKeyAlgorithmTags.TRIPLE_DES), + CAST5( SymmetricKeyAlgorithmTags.CAST5), + BLOWFISH( SymmetricKeyAlgorithmTags.BLOWFISH), + SAFER( SymmetricKeyAlgorithmTags.SAFER), + DES( SymmetricKeyAlgorithmTags.DES), + AES_128( SymmetricKeyAlgorithmTags.AES_128), + AES_192( SymmetricKeyAlgorithmTags.AES_192), + AES_256( SymmetricKeyAlgorithmTags.AES_256), + TWOFISH( SymmetricKeyAlgorithmTags.TWOFISH), + CAMELLIA_128( SymmetricKeyAlgorithmTags.CAMELLIA_128), + CAMELLIA_192( SymmetricKeyAlgorithmTags.CAMELLIA_192), + CAMELLIA_256( SymmetricKeyAlgorithmTags.CAMELLIA_256), + ; + + private static final Map MAP = new HashMap<>(); + + static { + for (SymmetricKeyAlgorithm s : SymmetricKeyAlgorithm.values()) { + MAP.put(s.algorithmId, s); + } + } + + public static SymmetricKeyAlgorithm forId(int id) { + return MAP.get(id); + } + + private final int algorithmId; + + SymmetricKeyAlgorithm(int algorithmId) { + this.algorithmId = algorithmId; + } + + public int getAlgorithmId() { + return algorithmId; + } +} diff --git a/src/main/java/de/vanitasvitae/crypto/pgpainless/key/generation/KeyRingBuilder.java b/src/main/java/de/vanitasvitae/crypto/pgpainless/key/generation/KeyRingBuilder.java new file mode 100644 index 00000000..aec69d29 --- /dev/null +++ b/src/main/java/de/vanitasvitae/crypto/pgpainless/key/generation/KeyRingBuilder.java @@ -0,0 +1,213 @@ +package de.vanitasvitae.crypto.pgpainless.key.generation; + + +import java.nio.charset.Charset; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +import de.vanitasvitae.crypto.pgpainless.key.algorithm.KeyFlag; +import de.vanitasvitae.crypto.pgpainless.key.generation.type.KeyType; +import org.bouncycastle.bcpg.HashAlgorithmTags; +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.bouncycastle.openpgp.PGPEncryptedData; +import org.bouncycastle.openpgp.PGPException; +import org.bouncycastle.openpgp.PGPKeyPair; +import org.bouncycastle.openpgp.PGPKeyRingGenerator; +import org.bouncycastle.openpgp.PGPSecretKeyRing; +import org.bouncycastle.openpgp.PGPSignature; +import org.bouncycastle.openpgp.PGPSignatureSubpacketGenerator; +import org.bouncycastle.openpgp.operator.PBESecretKeyEncryptor; +import org.bouncycastle.openpgp.operator.PGPContentSignerBuilder; +import org.bouncycastle.openpgp.operator.PGPDigestCalculator; +import org.bouncycastle.openpgp.operator.jcajce.JcaPGPContentSignerBuilder; +import org.bouncycastle.openpgp.operator.jcajce.JcaPGPDigestCalculatorProviderBuilder; +import org.bouncycastle.openpgp.operator.jcajce.JcaPGPKeyPair; +import org.bouncycastle.openpgp.operator.jcajce.JcePBESecretKeyEncryptorBuilder; + +public class KeyRingBuilder implements KeyRingBuilderInterface { + + private final Charset UTF8 = Charset.forName("UTF-8"); + + private List keySpecs = new ArrayList<>(); + private List userIds = new ArrayList<>(); + private char[] passphrase; + + @Override + public WithSubKeyType generateCompositeKeyRing() { + return new WithSubKeyTypeImpl(); + } + + @Override + public WithCertificationKeyType generateSingleKeyKeyRing() { + return new WithCertificationKeyTypeImpl(); + } + + class WithSubKeyTypeImpl implements WithSubKeyType { + + @Override + public WithSubKeyType withSubKey(KeySpec type) { + KeyRingBuilder.this.keySpecs.add(type); + return this; + } + + @Override + public WithCertificationKeyType done() { + return new WithCertificationKeyTypeImpl(); + } + } + + class WithCertificationKeyTypeImpl implements WithCertificationKeyType { + + @Override + public WithPrimaryUserId withCertificationKeyType(KeySpec spec) { + if ((spec.getKeyFlags() & KeyFlag.CERTIFY_OTHER.getFlag()) == 0) { + throw new IllegalArgumentException("Certification Key MUST have KeyFlag CERTIFY_OTHER"); + } + KeyRingBuilder.this.keySpecs.add(spec); + return new WithPrimaryUserIdImpl(); + } + } + + class WithPrimaryUserIdImpl implements WithPrimaryUserId { + + @Override + public WithAdditionalUserIds withPrimaryUserId(String userId) { + KeyRingBuilder.this.userIds.add(userId); + return new WithAdditionalUserIdsImpl(); + } + + @Override + public WithAdditionalUserIds withPrimaryUserId(byte[] userId) { + return withPrimaryUserId(new String(userId, UTF8)); + } + } + + class WithAdditionalUserIdsImpl implements WithAdditionalUserIds { + + @Deprecated + @Override + public WithAdditionalUserIds withAdditionalUserId(String userId) { + KeyRingBuilder.this.userIds.add(userId); + return this; + } + + @Deprecated + @Override + public WithAdditionalUserIds withAdditionalUserId(byte[] userId) { + return withAdditionalUserId(new String(userId, UTF8)); + } + + @Override + public WithPassphrase done() { + return new WithPassphraseImpl(); + } + } + + class WithPassphraseImpl implements WithPassphrase { + + @Override + public Build withPassphrase(String passphrase) { + return withPassphrase(passphrase.toCharArray()); + } + + @Override + public Build withPassphrase(char[] passphrase) { + KeyRingBuilder.this.passphrase = passphrase; + return new BuildImpl(); + } + + @Override + public Build withoutPassphrase() { + KeyRingBuilder.this.passphrase = null; + return new BuildImpl(); + } + + class BuildImpl implements Build { + + @Override + public PGPSecretKeyRing build() throws NoSuchAlgorithmException, PGPException, NoSuchProviderException { + + // Hash Calculator + PGPDigestCalculator calculator = new JcaPGPDigestCalculatorProviderBuilder() + .setProvider(BouncyCastleProvider.PROVIDER_NAME) + .build() + .get(HashAlgorithmTags.SHA1); + + // Encryptor for encrypting secret keys + PBESecretKeyEncryptor encryptor = passphrase == null ? + null : // unencrypted key pair, otherwise AES-256 encrypted + new JcePBESecretKeyEncryptorBuilder(PGPEncryptedData.AES_256, calculator) + .setProvider(BouncyCastleProvider.PROVIDER_NAME) + .build(passphrase); + + // First key is the Master Key + KeySpec certKeySpec = keySpecs.get(0); + KeyType certKeyType = certKeySpec.getKeyType(); + keySpecs.remove(0); // Remove master key, so that we later only add sub keys. + + // Generate Master Key + PGPKeyPair certKey = generateKeyPair(certKeySpec); + + // Signer for creating self-signature + PGPContentSignerBuilder signer = new JcaPGPContentSignerBuilder( + certKey.getPublicKey().getAlgorithm(), HashAlgorithmTags.SHA256); + + // Mimic GnuPGs signature sub packets + PGPSignatureSubpacketGenerator hashedSubPackets = new PGPSignatureSubpacketGenerator(); + + // Key flags + hashedSubPackets.setKeyFlags(true, certKeySpec.getKeyFlags()); + + // Encryption Algorithms + hashedSubPackets.setPreferredSymmetricAlgorithms(true, + certKeySpec.getPreferredAlgorithms().getSymmetricKeyAlgorithmIds()); + + // Hash Algorithms + hashedSubPackets.setPreferredHashAlgorithms(true, + certKeySpec.getPreferredAlgorithms().getHashAlgorithmIds()); + + // Compression Algorithms + hashedSubPackets.setPreferredCompressionAlgorithms(true, + certKeySpec.getPreferredAlgorithms().getCompressionAlgorithmIds()); + + // Modification Detection + hashedSubPackets.setFeature(true, certKeySpec.getFeatures()); + + // Generator which the user can get the key pair from + PGPKeyRingGenerator ringGenerator = new PGPKeyRingGenerator( + PGPSignature.POSITIVE_CERTIFICATION, certKey, + userIds.get(0), calculator, + hashedSubPackets.generate(), null, signer, encryptor); + + for (KeySpec subKeySpec : keySpecs) { + PGPKeyPair subKey = generateKeyPair(subKeySpec); + ringGenerator.addSubKey(subKey); + } + + return ringGenerator.generateSecretKeyRing(); + } + + private PGPKeyPair generateKeyPair(KeySpec spec) + throws NoSuchProviderException, NoSuchAlgorithmException, PGPException { + KeyType type = spec.getKeyType(); + KeyPairGenerator certKeyGenerator = KeyPairGenerator.getInstance( + type.getName(), BouncyCastleProvider.PROVIDER_NAME); + certKeyGenerator.initialize(type.getLength()); + + // Create raw Key Pair + KeyPair rawKeyPair = certKeyGenerator.generateKeyPair(); + + // Form PGP key pair + PGPKeyPair pgpKeyPair = new JcaPGPKeyPair(type.getAlgorithm().getAlgorithmId(), + rawKeyPair, new Date()); + + return pgpKeyPair; + } + } + } +} \ No newline at end of file diff --git a/src/main/java/de/vanitasvitae/crypto/pgpainless/key/generation/KeyRingBuilderInterface.java b/src/main/java/de/vanitasvitae/crypto/pgpainless/key/generation/KeyRingBuilderInterface.java new file mode 100644 index 00000000..b9cf7cde --- /dev/null +++ b/src/main/java/de/vanitasvitae/crypto/pgpainless/key/generation/KeyRingBuilderInterface.java @@ -0,0 +1,58 @@ +package de.vanitasvitae.crypto.pgpainless.key.generation; + +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; + +import org.bouncycastle.openpgp.PGPException; +import org.bouncycastle.openpgp.PGPSecretKeyRing; + +public interface KeyRingBuilderInterface { + + WithSubKeyType generateCompositeKeyRing(); + + WithCertificationKeyType generateSingleKeyKeyRing(); + + interface WithSubKeyType { + + WithSubKeyType withSubKey(KeySpec keySpec); + + WithCertificationKeyType done(); + } + + interface WithCertificationKeyType { + WithPrimaryUserId withCertificationKeyType(KeySpec keySpec); + } + + interface WithPrimaryUserId { + + WithAdditionalUserIds withPrimaryUserId(String userId); + + WithAdditionalUserIds withPrimaryUserId(byte[] userId); + + } + + interface WithAdditionalUserIds { + + WithAdditionalUserIds withAdditionalUserId(String userId); + + WithAdditionalUserIds withAdditionalUserId(byte[] userId); + + WithPassphrase done(); + + } + + interface WithPassphrase { + + Build withPassphrase(String passphrase); + + Build withPassphrase(char[] passphrase); + + Build withoutPassphrase(); + } + + interface Build { + + PGPSecretKeyRing build() throws NoSuchAlgorithmException, PGPException, NoSuchProviderException; + + } +} diff --git a/src/main/java/de/vanitasvitae/crypto/pgpainless/key/generation/KeySpec.java b/src/main/java/de/vanitasvitae/crypto/pgpainless/key/generation/KeySpec.java new file mode 100644 index 00000000..1d03eefd --- /dev/null +++ b/src/main/java/de/vanitasvitae/crypto/pgpainless/key/generation/KeySpec.java @@ -0,0 +1,49 @@ +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; + +public class KeySpec { + + private final KeyType keyType; + private final int keyFlags; + private final AlgorithmSuite algorithmSuite; + private final Set features; + + KeySpec(KeyType type, + int keyFlags, + AlgorithmSuite preferredAlgorithms, + Set features) { + this.keyType = type; + this.keyFlags = keyFlags; + this.algorithmSuite = preferredAlgorithms; + this.features = features; + } + + KeyType getKeyType() { + return keyType; + } + + int getKeyFlags() { + return keyFlags; + } + + AlgorithmSuite getPreferredAlgorithms() { + return algorithmSuite; + } + + byte getFeatures() { + byte val = 0; + for (Feature f : features) { + val |= f.getFeatureId(); + } + return val; + } + + public static KeySpecBuilder getBuilder() { + return new KeySpecBuilder(); + } +} diff --git a/src/main/java/de/vanitasvitae/crypto/pgpainless/key/generation/KeySpecBuilder.java b/src/main/java/de/vanitasvitae/crypto/pgpainless/key/generation/KeySpecBuilder.java new file mode 100644 index 00000000..e1429fff --- /dev/null +++ b/src/main/java/de/vanitasvitae/crypto/pgpainless/key/generation/KeySpecBuilder.java @@ -0,0 +1,140 @@ +package de.vanitasvitae.crypto.pgpainless.key.generation; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + +import de.vanitasvitae.crypto.pgpainless.key.algorithm.AlgorithmSuite; +import de.vanitasvitae.crypto.pgpainless.key.algorithm.CompressionAlgorithm; +import de.vanitasvitae.crypto.pgpainless.key.algorithm.Feature; +import de.vanitasvitae.crypto.pgpainless.key.algorithm.HashAlgorithm; +import de.vanitasvitae.crypto.pgpainless.key.algorithm.KeyFlag; +import de.vanitasvitae.crypto.pgpainless.key.algorithm.SymmetricKeyAlgorithm; +import de.vanitasvitae.crypto.pgpainless.key.generation.type.KeyType; + +public class KeySpecBuilder implements KeySpecBuilderInterface { + + private KeyType type; + private int keyFlags; + private AlgorithmSuite algorithmSuite = AlgorithmSuite.getDefaultAlgorithmSuite(); + private Set features = new HashSet<>(); + + @Override + public WithKeyFlags ofType(KeyType type) { + KeySpecBuilder.this.type = type; + return new WithKeyFlagsImpl(); + } + + class WithKeyFlagsImpl implements WithKeyFlags { + + @Override + public WithDetailedConfiguration withKeyFlags(KeyFlag... flags) { + int val = 0; + for (KeyFlag f : flags) { + val |= f.getFlag(); + } + KeySpecBuilder.this.keyFlags = val; + return new WithDetailedConfigurationImpl(); + } + + @Override + public WithDetailedConfiguration withDefaultKeyFlags() { + return withKeyFlags( + KeyFlag.CERTIFY_OTHER, + KeyFlag.SIGN_DATA, + KeyFlag.ENCRYPT_COMMS, + KeyFlag.ENCRYPT_STORAGE, + KeyFlag.AUTHENTICATION); + } + } + + class WithDetailedConfigurationImpl implements WithDetailedConfiguration { + + @Deprecated + @Override + public WithPreferredSymmetricAlgorithms withDetailedConfiguration() { + return new WithPreferredSymmetricAlgorithmsImpl(); + } + + @Override + public KeySpec withStandardConfiguration() { + return new KeySpec( + KeySpecBuilder.this.type, + KeySpecBuilder.this.keyFlags, + KeySpecBuilder.this.algorithmSuite, + KeySpecBuilder.this.features); + } + } + + class WithPreferredSymmetricAlgorithmsImpl implements WithPreferredSymmetricAlgorithms { + + @Override + public WithPreferredHashAlgorithms withPreferredSymmetricAlgorithms(SymmetricKeyAlgorithm... algorithms) { + KeySpecBuilder.this.algorithmSuite.setSymmetricKeyAlgorithms(Arrays.asList(algorithms)); + return new WithPreferredHashAlgorithmsImpl(); + } + + @Override + public WithPreferredHashAlgorithms withDefaultSymmetricAlgorithms() { + KeySpecBuilder.this.algorithmSuite.setSymmetricKeyAlgorithms( + AlgorithmSuite.getDefaultAlgorithmSuite().getSymmetricKeyAlgorithms()); + return new WithPreferredHashAlgorithmsImpl(); + } + + @Override + public WithFeatures withDefaultAlgorithms() { + KeySpecBuilder.this.algorithmSuite = AlgorithmSuite.getDefaultAlgorithmSuite(); + return new WithFeaturesImpl(); + } + } + + class WithPreferredHashAlgorithmsImpl implements WithPreferredHashAlgorithms { + + @Override + public WithPreferredCompressionAlgorithms withPreferredHashAlgorithms(HashAlgorithm... algorithms) { + KeySpecBuilder.this.algorithmSuite.setHashAlgorithms(Arrays.asList(algorithms)); + return new WithPreferredCompressionAlgorithmsImpl(); + } + + @Override + public WithPreferredCompressionAlgorithms withDefaultHashAlgorithms() { + KeySpecBuilder.this.algorithmSuite.setHashAlgorithms( + AlgorithmSuite.getDefaultAlgorithmSuite().getHashAlgorithms()); + return new WithPreferredCompressionAlgorithmsImpl(); + } + } + + class WithPreferredCompressionAlgorithmsImpl implements WithPreferredCompressionAlgorithms { + + @Override + public WithFeatures withPreferredCompressionAlgorithms(CompressionAlgorithm... algorithms) { + KeySpecBuilder.this.algorithmSuite.setCompressionAlgorithms(Arrays.asList(algorithms)); + return new WithFeaturesImpl(); + } + + @Override + public WithFeatures withDefaultCompressionAlgorithms() { + KeySpecBuilder.this.algorithmSuite.setCompressionAlgorithms( + AlgorithmSuite.getDefaultAlgorithmSuite().getCompressionAlgorithms()); + return new WithFeaturesImpl(); + } + } + + class WithFeaturesImpl implements WithFeatures { + + @Override + public WithFeatures withFeature(Feature feature) { + KeySpecBuilder.this.features.add(feature); + return this; + } + + @Override + public KeySpec done() { + return new KeySpec( + KeySpecBuilder.this.type, + KeySpecBuilder.this.keyFlags, + KeySpecBuilder.this.algorithmSuite, + KeySpecBuilder.this.features); + } + } +} diff --git a/src/main/java/de/vanitasvitae/crypto/pgpainless/key/generation/KeySpecBuilderInterface.java b/src/main/java/de/vanitasvitae/crypto/pgpainless/key/generation/KeySpecBuilderInterface.java new file mode 100644 index 00000000..63a458ed --- /dev/null +++ b/src/main/java/de/vanitasvitae/crypto/pgpainless/key/generation/KeySpecBuilderInterface.java @@ -0,0 +1,62 @@ +package de.vanitasvitae.crypto.pgpainless.key.generation; + +import de.vanitasvitae.crypto.pgpainless.key.algorithm.AlgorithmSuite; +import de.vanitasvitae.crypto.pgpainless.key.algorithm.CompressionAlgorithm; +import de.vanitasvitae.crypto.pgpainless.key.algorithm.Feature; +import de.vanitasvitae.crypto.pgpainless.key.algorithm.HashAlgorithm; +import de.vanitasvitae.crypto.pgpainless.key.algorithm.KeyFlag; +import de.vanitasvitae.crypto.pgpainless.key.algorithm.SymmetricKeyAlgorithm; +import de.vanitasvitae.crypto.pgpainless.key.generation.type.KeyType; + +public interface KeySpecBuilderInterface { + + WithKeyFlags ofType(KeyType type); + + interface WithKeyFlags { + + WithDetailedConfiguration withKeyFlags(KeyFlag... flags); + + WithDetailedConfiguration withDefaultKeyFlags(); + } + + interface WithDetailedConfiguration { + + WithPreferredSymmetricAlgorithms withDetailedConfiguration(); + + KeySpec withStandardConfiguration(); + } + + interface WithPreferredSymmetricAlgorithms { + + WithPreferredHashAlgorithms withPreferredSymmetricAlgorithms(SymmetricKeyAlgorithm... algorithms); + + WithPreferredHashAlgorithms withDefaultSymmetricAlgorithms(); + + WithFeatures withDefaultAlgorithms(); + + } + + interface WithPreferredHashAlgorithms { + + WithPreferredCompressionAlgorithms withPreferredHashAlgorithms(HashAlgorithm... algorithms); + + WithPreferredCompressionAlgorithms withDefaultHashAlgorithms(); + + } + + interface WithPreferredCompressionAlgorithms { + + WithFeatures withPreferredCompressionAlgorithms(CompressionAlgorithm... algorithms); + + WithFeatures withDefaultCompressionAlgorithms(); + + } + + interface WithFeatures { + + WithFeatures withFeature(Feature feature); + + KeySpec done(); + } + +} diff --git a/src/main/java/de/vanitasvitae/crypto/pgpainless/key/generation/type/DSA.java b/src/main/java/de/vanitasvitae/crypto/pgpainless/key/generation/type/DSA.java new file mode 100644 index 00000000..65bcdb0b --- /dev/null +++ b/src/main/java/de/vanitasvitae/crypto/pgpainless/key/generation/type/DSA.java @@ -0,0 +1,36 @@ +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; + } +} diff --git a/src/main/java/de/vanitasvitae/crypto/pgpainless/key/generation/type/ElGamal_ENCRYPT.java b/src/main/java/de/vanitasvitae/crypto/pgpainless/key/generation/type/ElGamal_ENCRYPT.java new file mode 100644 index 00000000..89233777 --- /dev/null +++ b/src/main/java/de/vanitasvitae/crypto/pgpainless/key/generation/type/ElGamal_ENCRYPT.java @@ -0,0 +1,32 @@ +package de.vanitasvitae.crypto.pgpainless.key.generation.type; + +import de.vanitasvitae.crypto.pgpainless.key.algorithm.PublicKeyAlgorithm; + +public enum ElGamal_ENCRYPT implements KeyType { + + _1024(1024), + _2048(2048), + _3072(3072), + ; + + private final int length; + + ElGamal_ENCRYPT(int length) { + this.length = length; + } + + @Override + public int getLength() { + return length; + } + + @Override + public String getName() { + return "ElGamal"; + } + + @Override + public PublicKeyAlgorithm getAlgorithm() { + return PublicKeyAlgorithm.ELGAMAL_ENCRYPT; + } +} diff --git a/src/main/java/de/vanitasvitae/crypto/pgpainless/key/generation/type/KeyType.java b/src/main/java/de/vanitasvitae/crypto/pgpainless/key/generation/type/KeyType.java new file mode 100644 index 00000000..0f9ce131 --- /dev/null +++ b/src/main/java/de/vanitasvitae/crypto/pgpainless/key/generation/type/KeyType.java @@ -0,0 +1,12 @@ +package de.vanitasvitae.crypto.pgpainless.key.generation.type; + +import de.vanitasvitae.crypto.pgpainless.key.algorithm.PublicKeyAlgorithm; + +public interface KeyType { + + int getLength(); + + String getName(); + + PublicKeyAlgorithm getAlgorithm(); +} diff --git a/src/main/java/de/vanitasvitae/crypto/pgpainless/key/generation/type/RSA_GENERAL.java b/src/main/java/de/vanitasvitae/crypto/pgpainless/key/generation/type/RSA_GENERAL.java new file mode 100644 index 00000000..b3a44b9b --- /dev/null +++ b/src/main/java/de/vanitasvitae/crypto/pgpainless/key/generation/type/RSA_GENERAL.java @@ -0,0 +1,36 @@ +package de.vanitasvitae.crypto.pgpainless.key.generation.type; + +import de.vanitasvitae.crypto.pgpainless.key.algorithm.PublicKeyAlgorithm; + +public enum RSA_GENERAL implements KeyType { + + @Deprecated + _1024(1024), + @Deprecated + _2048(2048), + _3072(3072), + _4096(4096), + _8192(8192), + ; + + private final int length; + + RSA_GENERAL(int length) { + this.length = length; + } + + @Override + public int getLength() { + return length; + } + + @Override + public String getName() { + return "RSA"; + } + + @Override + public PublicKeyAlgorithm getAlgorithm() { + return PublicKeyAlgorithm.RSA_GENERAL; + } +}