diff --git a/.gitignore b/.gitignore
index c58348b..e2de616 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,6 +8,11 @@
*.war
*.ear
+# gradle
+!gradle-wrapper.jar
+.gradle
+/build/
+
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
diff --git a/.travis.yml b/.travis.yml
index a7bd7ad..df45553 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -2,7 +2,13 @@ sudo: false
language: java
jdk:
- - oraclejdk8
+ - oraclejdk9
+
+install:
+- ./gradlew assemble -x signArchives -i
+
+script:
+- ./gradlew check -x signArchives -i
after_failure:
chmod +x $TRAVIS_BUILD_DIR/print_surefire_reports.sh; $TRAVIS_BUILD_DIR/print_surefire_reports.sh
diff --git a/build.gradle b/build.gradle
new file mode 100644
index 0000000..fd795ca
--- /dev/null
+++ b/build.gradle
@@ -0,0 +1,117 @@
+// Apply the java-library plugin to add support for Java Library
+apply plugin: 'java-library'
+apply plugin: 'signing'
+apply plugin: 'maven'
+
+group = "org.rootservices"
+version = "1.3"
+archivesBaseName="jwt"
+
+description = """JSON Web Tokens"""
+
+sourceCompatibility = 1.9
+targetCompatibility = 1.9
+
+buildscript {
+ repositories {
+ mavenCentral()
+ }
+}
+
+repositories {
+ mavenCentral()
+ mavenLocal()
+}
+
+configurations {
+ deployerJars
+}
+
+ext {
+ jacksonVersion = '2.8.8'
+ log4jVersion = '2.11.0'
+}
+
+dependencies {
+ implementation "com.fasterxml.jackson.core:jackson-core:${jacksonVersion}"
+ implementation "com.fasterxml.jackson.core:jackson-databind:${jacksonVersion}"
+ implementation "com.fasterxml.jackson.datatype:jackson-datatype-jdk8:${jacksonVersion}"
+ implementation "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:${jacksonVersion}"
+ implementation "org.apache.logging.log4j:log4j-api:${log4jVersion}"
+ implementation "org.apache.logging.log4j:log4j-core:${log4jVersion}"
+
+ testImplementation group: 'junit', name: 'junit', version:'4.12'
+ testImplementation group: 'org.hamcrest', name: 'hamcrest-all', version:'1.3'
+ testImplementation group: 'org.mockito', name: 'mockito-all', version:'1.9.5'
+}
+
+task javadocJar(type: Jar) {
+ classifier = 'javadoc'
+ from javadoc
+}
+
+task sourcesJar(type: Jar) {
+ classifier = 'sources'
+ from sourceSets.main.allSource
+}
+
+artifacts {
+ archives javadocJar, sourcesJar
+}
+
+signing {
+ sign configurations.archives
+}
+
+uploadArchives {
+ repositories {
+ mavenDeployer {
+ if(!project.ext.properties.containsKey("ossrhUser")) {
+ project.ext.ossrhUser = 'wrongUser'
+ project.ext.ossrhPassword = 'wrongPassword'
+ }
+
+ beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) }
+ snapshotRepository(url: "https://oss.sonatype.org/content/repositories/snapshots") {
+ authentication(userName: ossrhUser, password: ossrhPassword)
+ }
+ repository(url: "https://oss.sonatype.org/service/local/staging/deploy/maven2/") {
+ authentication(userName: ossrhUser, password: ossrhPassword)
+ }
+ pom.project {
+ groupId 'org.rootservices'
+ artifactId project.name
+ version project.version
+ name project.name
+ description project.description
+ packaging 'jar'
+ url 'https://github.com/RootServices/jwt'
+
+ scm {
+ connection 'git@github.com:RootServices/jwt.git'
+ developerConnection 'git@github.com:RootServices/jwt.git'
+ url 'https://github.com/RootServices/jwt'
+ }
+
+ licenses {
+ license {
+ name 'The MIT License (MIT)'
+ url 'https://github.com/RootServices/jwt/blob/development/LICENSE'
+ }
+ }
+
+ developers {
+ developer {
+ id 'tmackenzie'
+ name 'Tom MacKenzie'
+ email 'tom@rootservices.org'
+ }
+ }
+ }
+ }
+ }
+}
+
+task wrapper(type: Wrapper) {
+ gradleVersion = '4.6'
+}
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..7a3265e
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 0000000..143f0cc
--- /dev/null
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Thu Mar 22 07:28:59 CDT 2018
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip
diff --git a/gradlew b/gradlew
new file mode 100755
index 0000000..cccdd3d
--- /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 0000000..e95643d
--- /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/pom.xml b/pom.xml
deleted file mode 100644
index df18535..0000000
--- a/pom.xml
+++ /dev/null
@@ -1,172 +0,0 @@
-
-
- 4.0.0
-
-
- org.sonatype.oss
- oss-parent
- 8
-
-
- JWT
- Java implementation of JWT
- org.rootservices
- jwt
- 1.2
- jar
-
-
- UTF-8
- 1.8
-
-
-
-
-
- com.fasterxml.jackson.core
- jackson-core
- 2.4.6
-
-
-
- com.fasterxml.jackson.core
- jackson-databind
- 2.4.6
-
-
-
- com.fasterxml.jackson.datatype
- jackson-datatype-jdk8
- 2.5.4
-
-
-
- org.bouncycastle
- bcpkix-jdk15on
- 1.53
-
-
-
-
- junit
- junit
- 4.11
- test
-
-
-
- org.easytesting
- fest-assert-core
- 2.0M10
- test
-
-
-
- org.mockito
- mockito-all
- 1.9.5
- test
-
-
-
-
-
-
-
-
- org.apache.maven.plugins
- maven-surefire-plugin
- 2.5
-
- methods
- 5
-
-
-
- org.apache.maven.plugins
- maven-compiler-plugin
- 3.1
-
-
- ${java.version}
- true
- true
- -Xlint:unchecked
-
-
-
- org.apache.maven.plugins
- maven-source-plugin
- 2.4
-
-
-
- jar
-
-
-
-
-
- org.apache.maven.plugins
- maven-javadoc-plugin
- 2.9.1
-
-
- attach-javadocs
-
- jar
-
-
-
-
-
-
-
-
-
- sonatype-nexus-snapshots
- Sonatype Nexus snapshot repository
- https://oss.sonatype.org/content/repositories/snapshots
-
-
- sonatype-nexus-staging
- Sonatype Nexus release repository
- https://oss.sonatype.org/service/local/staging/deploy/maven2
-
-
-
-
-
- release-sign-artifacts
-
-
- performRelease
- true
-
-
-
-
-
- org.apache.maven.plugins
- maven-gpg-plugin
- 1.4
-
- ${gpg.passphrase}
-
-
-
- sign-artifacts
- verify
-
- sign
-
-
-
-
-
-
-
-
-
diff --git a/settings.gradle b/settings.gradle
new file mode 100644
index 0000000..f4f12d9
--- /dev/null
+++ b/settings.gradle
@@ -0,0 +1,18 @@
+/*
+ * This settings file was generated by the Gradle 'init' task.
+ *
+ * The settings file is used to specify which projects to include in your build.
+ * In a single project build this file can be empty or even removed.
+ *
+ * Detailed information about configuring a multi-project build in Gradle can be found
+ * in the user guide at https://docs.gradle.org/4.1/userguide/multi_project_builds.html
+ */
+
+/*
+// To declare projects as part of a multi-project build use the 'include' method
+include 'shared'
+include 'api'
+include 'services:webservice'
+*/
+
+rootProject.name = 'jwt'
diff --git a/src/main/java/org/rootservices/jwt/SecureJwtEncoder.java b/src/main/java/org/rootservices/jwt/SecureJwtEncoder.java
deleted file mode 100644
index 018b188..0000000
--- a/src/main/java/org/rootservices/jwt/SecureJwtEncoder.java
+++ /dev/null
@@ -1,41 +0,0 @@
-package org.rootservices.jwt;
-
-
-import org.rootservices.jwt.entity.jwt.Claims;
-import org.rootservices.jwt.entity.jwt.JsonWebToken;
-import org.rootservices.jwt.factory.SecureJwtFactory;
-import org.rootservices.jwt.factory.UnSecureJwtFactory;
-import org.rootservices.jwt.serializer.JWTSerializer;
-import org.rootservices.jwt.serializer.exception.JwtToJsonException;
-
-/**
- * Created by tommackenzie on 9/1/16.
- */
-public class SecureJwtEncoder {
- private SecureJwtFactory secureJwtFactory;
- private JWTSerializer jwtSerializer;
-
- public SecureJwtEncoder(SecureJwtFactory secureJwtFactory, JWTSerializer jwtSerializer) {
- this.secureJwtFactory = secureJwtFactory;
- this.jwtSerializer = jwtSerializer;
- }
-
- public String encode(Claims claims) throws JwtToJsonException {
-
- JsonWebToken jsonWebToken = null;
- try {
- jsonWebToken = secureJwtFactory.makeJwt(claims);
- } catch (JwtToJsonException e) {
- throw e;
- }
-
- String jwt = null;
- try {
- jwt = jwtSerializer.jwtToString(jsonWebToken);
- } catch (JwtToJsonException e) {
- throw e;
- }
-
- return jwt;
- }
-}
diff --git a/src/main/java/org/rootservices/jwt/UnSecureJwtEncoder.java b/src/main/java/org/rootservices/jwt/UnSecureJwtEncoder.java
deleted file mode 100644
index 15fafe2..0000000
--- a/src/main/java/org/rootservices/jwt/UnSecureJwtEncoder.java
+++ /dev/null
@@ -1,34 +0,0 @@
-package org.rootservices.jwt;
-
-import org.rootservices.jwt.entity.jwt.Claims;
-import org.rootservices.jwt.entity.jwt.JsonWebToken;
-import org.rootservices.jwt.factory.UnSecureJwtFactory;
-import org.rootservices.jwt.serializer.JWTSerializer;
-import org.rootservices.jwt.serializer.exception.JwtToJsonException;
-
-/**
- * Created by tommackenzie on 7/12/16.
- */
-public class UnSecureJwtEncoder {
- private UnSecureJwtFactory unSecureJwtFactory;
- private JWTSerializer jwtSerializer;
-
- public UnSecureJwtEncoder(UnSecureJwtFactory unSecureJwtFactory, JWTSerializer jwtSerializer) {
- this.unSecureJwtFactory = unSecureJwtFactory;
- this.jwtSerializer = jwtSerializer;
- }
-
- public String encode(Claims claims) {
-
- JsonWebToken jsonWebToken = unSecureJwtFactory.makeJwt(claims);
-
- String encodedJwt = null;
- try {
- encodedJwt = jwtSerializer.jwtToString(jsonWebToken);
- } catch (JwtToJsonException e) {
- e.printStackTrace();
- }
-
- return encodedJwt;
- }
-}
diff --git a/src/main/java/org/rootservices/jwt/config/AppFactory.java b/src/main/java/org/rootservices/jwt/config/AppFactory.java
deleted file mode 100644
index c2dc7f2..0000000
--- a/src/main/java/org/rootservices/jwt/config/AppFactory.java
+++ /dev/null
@@ -1,155 +0,0 @@
-package org.rootservices.jwt.config;
-
-import com.fasterxml.jackson.annotation.JsonInclude;
-import com.fasterxml.jackson.core.JsonParser;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.PropertyNamingStrategy;
-import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
-import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
-import org.rootservices.jwt.SecureJwtEncoder;
-import org.rootservices.jwt.UnSecureJwtEncoder;
-import org.rootservices.jwt.signature.signer.factory.exception.InvalidAlgorithmException;
-import org.rootservices.jwt.signature.signer.factory.exception.InvalidJsonWebKeyException;
-import org.rootservices.jwt.translator.CSRToRSAPublicKey;
-import org.rootservices.jwt.translator.PemToRSAKeyPair;
-import org.rootservices.jwt.factory.SecureJwtFactory;
-import org.rootservices.jwt.factory.UnSecureJwtFactory;
-import org.rootservices.jwt.entity.jwk.Key;
-import org.rootservices.jwt.entity.jwt.header.Algorithm;
-import org.rootservices.jwt.serializer.JWTSerializer;
-import org.rootservices.jwt.serializer.Serializer;
-import org.rootservices.jwt.signature.signer.factory.hmac.MacFactory;
-import org.rootservices.jwt.signature.signer.factory.rsa.PrivateKeySignatureFactory;
-import org.rootservices.jwt.signature.signer.factory.rsa.PublicKeySignatureFactory;
-import org.rootservices.jwt.signature.verifier.VerifySignature;
-import org.rootservices.jwt.signature.signer.Signer;
-import org.rootservices.jwt.signature.signer.factory.*;
-import org.rootservices.jwt.signature.verifier.factory.VerifySignatureFactory;
-
-
-import java.security.KeyFactory;
-import java.security.NoSuchAlgorithmException;
-import java.security.Security;
-import java.util.Base64;
-
-/**
- * Created by tommackenzie on 8/13/15.
- */
-public class AppFactory {
-
- public ObjectMapper objectMapper() {
- return new ObjectMapper()
- .setPropertyNamingStrategy(
- PropertyNamingStrategy.CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES
- )
- .configure(JsonParser.Feature.STRICT_DUPLICATE_DETECTION, true)
- .registerModule(new Jdk8Module())
- .setSerializationInclusion(JsonInclude.Include.NON_NULL)
- .setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
- }
-
- public Serializer serializer() {
- return new Serializer(objectMapper());
- }
-
- public Base64.Decoder decoder() {
- return Base64.getDecoder();
- }
-
- public Base64.Decoder urlDecoder() {
- return Base64.getUrlDecoder();
- }
-
- public Base64.Encoder encoder() {
- return Base64.getUrlEncoder().withoutPadding();
- }
-
- public JWTSerializer jwtSerializer() {
- return new JWTSerializer(
- serializer(),
- encoder(),
- decoder()
- );
- }
-
- public PublicKeySignatureFactory publicKeySignatureFactory() {
- return new PublicKeySignatureFactory(rsaKeyFactory());
- }
-
- public MacFactory macFactory() {
- return new MacFactory(urlDecoder());
- }
-
- public PrivateKeySignatureFactory privateKeySignatureFactory() {
- return new PrivateKeySignatureFactory(rsaKeyFactory());
- }
-
- public SignerFactory signerFactory() {
- return new SignerFactory(
- macFactory(),
- privateKeySignatureFactory(),
- jwtSerializer(),
- encoder()
- );
- }
-
- public VerifySignatureFactory verifySignatureFactory() {
- return new VerifySignatureFactory(signerFactory(), publicKeySignatureFactory(), urlDecoder());
- }
-
- public VerifySignature verifySignature(Algorithm algorithm, Key key) throws InvalidAlgorithmException, InvalidJsonWebKeyException {
- return verifySignatureFactory().makeVerifySignature(algorithm, key);
- }
-
- public UnSecureJwtFactory unsecureJwtFactory(){
- return new UnSecureJwtFactory();
- }
-
- public SecureJwtFactory secureJwtFactory(Algorithm alg, Key jwk) throws InvalidAlgorithmException, InvalidJsonWebKeyException {
- Signer signer = signerFactory().makeSigner(alg, jwk);
- return new SecureJwtFactory(signer, alg, jwk.getKeyId());
- }
-
- public SecureJwtEncoder secureJwtEncoder(Algorithm alg, Key jwk) throws InvalidAlgorithmException, InvalidJsonWebKeyException {
- SecureJwtFactory secureJwtFactory = null;
- try {
- secureJwtFactory = secureJwtFactory(alg, jwk);
- } catch (InvalidAlgorithmException e) {
- throw e;
- } catch (InvalidJsonWebKeyException e) {
- throw e;
- }
-
- JWTSerializer jwtSerializer = jwtSerializer();
-
- return new SecureJwtEncoder(secureJwtFactory, jwtSerializer);
- }
-
- public UnSecureJwtEncoder unSecureJwtEncoder() {
- return new UnSecureJwtEncoder(unsecureJwtFactory(), jwtSerializer());
- }
-
- public JcaPEMKeyConverter jcaPEMKeyConverter() {
- Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
- return new JcaPEMKeyConverter().setProvider("BC");
- }
-
- protected KeyFactory rsaKeyFactory() {
- KeyFactory RSAKeyFactory = null;
- try {
- RSAKeyFactory = KeyFactory.getInstance("RSA");
- } catch (NoSuchAlgorithmException e) {
- // will never reach here.
- e.printStackTrace();
- }
- return RSAKeyFactory;
- }
-
- public PemToRSAKeyPair pemToRSAKeyPair() {
- return new PemToRSAKeyPair(jcaPEMKeyConverter(), rsaKeyFactory());
- }
-
- public CSRToRSAPublicKey csrToRSAPublicKey() {
- return new CSRToRSAPublicKey();
- }
-}
diff --git a/src/main/java/org/rootservices/jwt/config/JwtAppFactory.java b/src/main/java/org/rootservices/jwt/config/JwtAppFactory.java
new file mode 100644
index 0000000..dff2b18
--- /dev/null
+++ b/src/main/java/org/rootservices/jwt/config/JwtAppFactory.java
@@ -0,0 +1,236 @@
+package org.rootservices.jwt.config;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.PropertyNamingStrategy;
+import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.rootservices.jwt.jwe.serialization.direct.JweDirectDesializer;
+import org.rootservices.jwt.jwe.serialization.direct.JweDirectSerializer;
+import org.rootservices.jwt.jwe.serialization.rsa.JweRsaSerializer;
+import org.rootservices.jwt.jws.serialization.SecureJwtSerializer;
+import org.rootservices.jwt.exception.SignatureException;
+import org.rootservices.jwt.serialization.JwtSerde;
+import org.rootservices.jwt.serialization.Serdes;
+import org.rootservices.jwt.serialization.UnSecureJwtSerializer;
+import org.rootservices.jwt.entity.jwk.RSAPublicKey;
+import org.rootservices.jwt.jwe.Transformation;
+import org.rootservices.jwt.jwe.factory.CipherRSAFactory;
+import org.rootservices.jwt.jwe.factory.CipherSymmetricFactory;
+import org.rootservices.jwt.jwe.factory.exception.CipherException;
+import org.rootservices.jwt.jwk.PrivateKeyFactory;
+import org.rootservices.jwt.jwk.PublicKeyFactory;
+import org.rootservices.jwt.jwk.SecretKeyFactory;
+import org.rootservices.jwt.jws.signer.factory.rsa.exception.PublicKeyException;
+import org.rootservices.jwt.serialization.HeaderDeserializer;
+import org.rootservices.jwt.jwe.serialization.rsa.JweRsaDeserializer;
+import org.rootservices.jwt.jws.signer.factory.exception.InvalidAlgorithmException;
+import org.rootservices.jwt.jws.signer.factory.exception.InvalidJsonWebKeyException;
+import org.rootservices.jwt.factory.SecureJwtFactory;
+import org.rootservices.jwt.factory.UnSecureJwtFactory;
+import org.rootservices.jwt.entity.jwk.Key;
+import org.rootservices.jwt.entity.jwt.header.Algorithm;
+import org.rootservices.jwt.jws.signer.factory.hmac.MacFactory;
+import org.rootservices.jwt.jws.signer.factory.rsa.PrivateKeySignatureFactory;
+import org.rootservices.jwt.jws.signer.factory.rsa.PublicKeySignatureFactory;
+import org.rootservices.jwt.jws.verifier.VerifySignature;
+import org.rootservices.jwt.jws.signer.Signer;
+import org.rootservices.jwt.jws.signer.factory.*;
+import org.rootservices.jwt.jws.verifier.factory.VerifySignatureFactory;
+
+
+import javax.crypto.Cipher;
+import java.security.KeyFactory;
+import java.security.NoSuchAlgorithmException;
+import java.util.Base64;
+
+
+public class JwtAppFactory {
+ private static final Logger LOGGER = LogManager.getLogger(JwtAppFactory.class);
+ public static final String KEY_WAS_INVALID = "Could not construct Signer. Key was invalid.";
+ public static final String ALG_WAS_INVALID = "Could not construct Signer. Algorithm was invalid.";
+ public static final String RSA = "RSA";
+ private static ObjectMapper objectMapper;
+ private static KeyFactory RSAKeyFactory;
+
+ public ObjectMapper objectMapper() {
+ if (objectMapper == null) {
+ this.objectMapper = new ObjectMapper()
+ .setPropertyNamingStrategy(
+ PropertyNamingStrategy.SNAKE_CASE
+ )
+ .configure(JsonParser.Feature.STRICT_DUPLICATE_DETECTION, true)
+ .registerModule(new Jdk8Module())
+ .setSerializationInclusion(JsonInclude.Include.NON_NULL)
+ .setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
+ }
+ return objectMapper;
+ }
+
+ public Serdes serdes() {
+ return new Serdes(objectMapper());
+ }
+
+ public Base64.Decoder decoder() {
+ return Base64.getDecoder();
+ }
+
+ public Base64.Decoder urlDecoder() {
+ return Base64.getUrlDecoder();
+ }
+
+ public Base64.Encoder encoder() {
+ return Base64.getUrlEncoder().withoutPadding();
+ }
+
+ public HeaderDeserializer headerDeserializer() {
+ return new HeaderDeserializer(decoder(), serdes());
+ }
+
+ public JwtSerde jwtSerde() {
+ return new JwtSerde(
+ serdes(),
+ encoder(),
+ decoder()
+ );
+ }
+
+ public CipherRSAFactory cipherRSAFactory() {
+ return new CipherRSAFactory();
+ }
+
+ public CipherSymmetricFactory cipherSymmetricFactory() {
+ return new CipherSymmetricFactory();
+ }
+
+ public JweRsaDeserializer jweRsaDeserializer() {
+
+ return new JweRsaDeserializer(
+ serdes(),
+ urlDecoder(),
+ privateKeyFactory(),
+ cipherRSAFactory(),
+ cipherSymmetricFactory()
+ );
+ }
+
+ public JweDirectDesializer jweDirectDesializer() {
+ return new JweDirectDesializer(
+ serdes(),
+ urlDecoder(),
+ cipherSymmetricFactory()
+ );
+ }
+
+ public PublicKeyFactory publicKeyFactory() {
+ return new PublicKeyFactory(rsaKeyFactory());
+ }
+
+ public PublicKeySignatureFactory publicKeySignatureFactory() {
+ return new PublicKeySignatureFactory(rsaKeyFactory());
+ }
+
+ public MacFactory macFactory() {
+ return new MacFactory(urlDecoder());
+ }
+
+ public PrivateKeyFactory privateKeyFactory() {
+ return new PrivateKeyFactory(rsaKeyFactory());
+ }
+
+ public PrivateKeySignatureFactory privateKeySignatureFactory() {
+ return new PrivateKeySignatureFactory(rsaKeyFactory());
+ }
+
+ public SignerFactory signerFactory() {
+ return new SignerFactory(
+ macFactory(),
+ privateKeySignatureFactory(),
+ jwtSerde(),
+ encoder()
+ );
+ }
+
+ public VerifySignatureFactory verifySignatureFactory() {
+ return new VerifySignatureFactory(signerFactory(), publicKeySignatureFactory(), urlDecoder());
+ }
+
+ public VerifySignature verifySignature(Algorithm algorithm, Key key) throws SignatureException {
+ return verifySignatureFactory().makeVerifySignature(algorithm, key);
+ }
+
+ public UnSecureJwtFactory unsecureJwtFactory(){
+ return new UnSecureJwtFactory();
+ }
+
+ public SecureJwtFactory secureJwtFactory(Algorithm alg, Key jwk) throws InvalidAlgorithmException, InvalidJsonWebKeyException {
+ Signer signer = signerFactory().makeSigner(alg, jwk);
+ return new SecureJwtFactory(signer, alg, jwk.getKeyId());
+ }
+
+ public SecureJwtSerializer secureJwtSerializer(Algorithm alg, Key jwk) throws SignatureException {
+ SecureJwtFactory secureJwtFactory;
+ try {
+ secureJwtFactory = secureJwtFactory(alg, jwk);
+ } catch (InvalidAlgorithmException e) {
+ throw new SignatureException(ALG_WAS_INVALID, e);
+ } catch (InvalidJsonWebKeyException e) {
+ throw new SignatureException(KEY_WAS_INVALID, e);
+ }
+
+ JwtSerde jwtSerde = jwtSerde();
+
+ return new SecureJwtSerializer(secureJwtFactory, jwtSerde);
+ }
+
+ public JweRsaSerializer jweRsaSerializer(RSAPublicKey jwk) throws PublicKeyException, CipherException {
+ java.security.interfaces.RSAPublicKey jdkKey;
+ try {
+ jdkKey = publicKeyFactory().makePublicKey(jwk);
+ } catch (PublicKeyException e) {
+ throw e;
+ }
+
+ Cipher rsaEncryptCipher;
+ try {
+ rsaEncryptCipher = cipherRSAFactory().forEncrypt(Transformation.RSA_OAEP, jdkKey);
+ } catch (CipherException e) {
+ throw e;
+ }
+
+ return new JweRsaSerializer(
+ serdes(),
+ encoder(),
+ rsaEncryptCipher,
+ new SecretKeyFactory(),
+ cipherSymmetricFactory()
+ );
+ }
+
+ public JweDirectSerializer jweDirectSerializer() {
+
+ return new JweDirectSerializer(
+ serdes(),
+ encoder(),
+ cipherSymmetricFactory()
+ );
+ }
+
+ public UnSecureJwtSerializer unSecureJwtSerializer() {
+ return new UnSecureJwtSerializer(unsecureJwtFactory(), jwtSerde());
+ }
+
+ protected KeyFactory rsaKeyFactory() {
+ if (this.RSAKeyFactory == null) {
+ try {
+ RSAKeyFactory = KeyFactory.getInstance(RSA);
+ } catch (NoSuchAlgorithmException e) {
+ // will never reach here.
+ LOGGER.error(e.getMessage(), e);
+ }
+ }
+ return RSAKeyFactory;
+ }
+}
diff --git a/src/main/java/org/rootservices/jwt/entity/jwe/EncryptionAlgorithm.java b/src/main/java/org/rootservices/jwt/entity/jwe/EncryptionAlgorithm.java
new file mode 100644
index 0000000..45fadc2
--- /dev/null
+++ b/src/main/java/org/rootservices/jwt/entity/jwe/EncryptionAlgorithm.java
@@ -0,0 +1,18 @@
+package org.rootservices.jwt.entity.jwe;
+
+import com.fasterxml.jackson.annotation.JsonValue;
+
+public enum EncryptionAlgorithm {
+ AES_GCM_256 ("A256GCM");
+
+ private String value;
+
+ EncryptionAlgorithm(String value) {
+ this.value = value;
+ }
+
+ @JsonValue
+ public String getValue() {
+ return value;
+ }
+}
diff --git a/src/main/java/org/rootservices/jwt/entity/jwk/KeyType.java b/src/main/java/org/rootservices/jwt/entity/jwk/KeyType.java
index 974138e..3d77881 100644
--- a/src/main/java/org/rootservices/jwt/entity/jwk/KeyType.java
+++ b/src/main/java/org/rootservices/jwt/entity/jwk/KeyType.java
@@ -9,11 +9,10 @@ public enum KeyType {
private String value;
- private KeyType(String value) {
+ KeyType(String value) {
this.value = value;
}
-
public String getValue() {
return value;
}
diff --git a/src/main/java/org/rootservices/jwt/entity/jwt/JsonWebToken.java b/src/main/java/org/rootservices/jwt/entity/jwt/JsonWebToken.java
index 625b670..89d6581 100644
--- a/src/main/java/org/rootservices/jwt/entity/jwt/JsonWebToken.java
+++ b/src/main/java/org/rootservices/jwt/entity/jwt/JsonWebToken.java
@@ -11,7 +11,7 @@
public class JsonWebToken {
private Header header;
private Claims claims;
- private Optional signature = Optional.empty();
+ private Optional signature = Optional.empty();
private Optional jwt = Optional.empty();
public JsonWebToken() {}
@@ -43,11 +43,11 @@ public void setClaims(Claims claims) {
this.claims = claims;
}
- public Optional getSignature() {
+ public Optional getSignature() {
return signature;
}
- public void setSignature(Optional signature) {
+ public void setSignature(Optional signature) {
this.signature = signature;
}
diff --git a/src/main/java/org/rootservices/jwt/entity/jwt/header/Algorithm.java b/src/main/java/org/rootservices/jwt/entity/jwt/header/Algorithm.java
index 3006442..136ae04 100644
--- a/src/main/java/org/rootservices/jwt/entity/jwt/header/Algorithm.java
+++ b/src/main/java/org/rootservices/jwt/entity/jwt/header/Algorithm.java
@@ -8,14 +8,18 @@
*/
@JsonFormat(shape = JsonFormat.Shape.OBJECT)
public enum Algorithm {
- NONE ("none"),
- HS256 ("HS256"),
- RS256 ("RS256");
+ NONE ("none", AlgorithmFor.JWS),
+ HS256 ("HS256", AlgorithmFor.JWS),
+ RS256 ("RS256", AlgorithmFor.JWS),
+ DIRECT ("dir", AlgorithmFor.JWE),
+ RSAES_OAEP ("RSA-OAEP", AlgorithmFor.JWE);
private String value;
+ private AlgorithmFor algorithmFor;
- Algorithm(String value) {
+ Algorithm(String value, AlgorithmFor algorithmFor) {
this.value = value;
+ this.algorithmFor = algorithmFor;
}
@JsonValue
@@ -26,4 +30,8 @@ public String getValue() {
public void setValue(String value) {
this.value = value;
}
+
+ public AlgorithmFor getAlgorithmFor() {
+ return algorithmFor;
+ }
}
diff --git a/src/main/java/org/rootservices/jwt/entity/jwt/header/AlgorithmFor.java b/src/main/java/org/rootservices/jwt/entity/jwt/header/AlgorithmFor.java
new file mode 100644
index 0000000..a0d1a8a
--- /dev/null
+++ b/src/main/java/org/rootservices/jwt/entity/jwt/header/AlgorithmFor.java
@@ -0,0 +1,5 @@
+package org.rootservices.jwt.entity.jwt.header;
+
+public enum AlgorithmFor {
+ JWS, JWE
+}
diff --git a/src/main/java/org/rootservices/jwt/entity/jwt/header/Header.java b/src/main/java/org/rootservices/jwt/entity/jwt/header/Header.java
index c69c9c7..a56f9eb 100644
--- a/src/main/java/org/rootservices/jwt/entity/jwt/header/Header.java
+++ b/src/main/java/org/rootservices/jwt/entity/jwt/header/Header.java
@@ -1,6 +1,8 @@
package org.rootservices.jwt.entity.jwt.header;
+import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
+import org.rootservices.jwt.entity.jwe.EncryptionAlgorithm;
import java.util.Optional;
@@ -11,11 +13,13 @@
*/
public class Header {
@JsonProperty(value="typ")
- Optional type;
+ private Optional type = Optional.empty();;
@JsonProperty(value="alg")
- Algorithm algorithm;
+ private Algorithm algorithm;
@JsonProperty(value="kid")
private Optional keyId = Optional.empty();
+ @JsonProperty(value="enc")
+ private Optional encryptionAlgorithm = Optional.empty();
public Optional getType() {
return type;
@@ -40,4 +44,12 @@ public Optional getKeyId() {
public void setKeyId(Optional keyId) {
this.keyId = keyId;
}
+
+ public Optional getEncryptionAlgorithm() {
+ return encryptionAlgorithm;
+ }
+
+ public void setEncryptionAlgorithm(Optional encryptionAlgorithm) {
+ this.encryptionAlgorithm = encryptionAlgorithm;
+ }
}
diff --git a/src/main/java/org/rootservices/jwt/exception/InvalidJWT.java b/src/main/java/org/rootservices/jwt/exception/InvalidJWT.java
new file mode 100644
index 0000000..f2266d3
--- /dev/null
+++ b/src/main/java/org/rootservices/jwt/exception/InvalidJWT.java
@@ -0,0 +1,7 @@
+package org.rootservices.jwt.exception;
+
+public class InvalidJWT extends Exception {
+ public InvalidJWT(String message) {
+ super(message);
+ }
+}
diff --git a/src/main/java/org/rootservices/jwt/exception/SignatureException.java b/src/main/java/org/rootservices/jwt/exception/SignatureException.java
new file mode 100644
index 0000000..a9e54d8
--- /dev/null
+++ b/src/main/java/org/rootservices/jwt/exception/SignatureException.java
@@ -0,0 +1,10 @@
+package org.rootservices.jwt.exception;
+
+/**
+ * Represents when a Signer could not be constructed due to a invalid key or algorithm.
+ */
+public class SignatureException extends Exception {
+ public SignatureException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/src/main/java/org/rootservices/jwt/factory/SecureJwtFactory.java b/src/main/java/org/rootservices/jwt/factory/SecureJwtFactory.java
index eb03e3e..53343eb 100644
--- a/src/main/java/org/rootservices/jwt/factory/SecureJwtFactory.java
+++ b/src/main/java/org/rootservices/jwt/factory/SecureJwtFactory.java
@@ -5,14 +5,12 @@
import org.rootservices.jwt.entity.jwt.header.Algorithm;
import org.rootservices.jwt.entity.jwt.header.Header;
import org.rootservices.jwt.entity.jwt.header.TokenType;
-import org.rootservices.jwt.serializer.exception.JwtToJsonException;
-import org.rootservices.jwt.signature.signer.Signer;
+import org.rootservices.jwt.serialization.exception.JwtToJsonException;
+import org.rootservices.jwt.jws.signer.Signer;
import java.util.Optional;
-/**
- * Created by tommackenzie on 9/15/15.
- */
+
public class SecureJwtFactory {
private Signer signer;
private Algorithm algorithm;
@@ -34,7 +32,7 @@ public JsonWebToken makeJwt(Claims claimNames) throws JwtToJsonException {
jwt.setHeader(header);
jwt.setClaims(claimNames);
- String signature = signer.run(jwt);
+ byte[] signature = signer.run(jwt);
jwt.setSignature(Optional.of(signature));
return jwt;
diff --git a/src/main/java/org/rootservices/jwt/factory/UnSecureJwtFactory.java b/src/main/java/org/rootservices/jwt/factory/UnSecureJwtFactory.java
index 35a00c4..d54699f 100644
--- a/src/main/java/org/rootservices/jwt/factory/UnSecureJwtFactory.java
+++ b/src/main/java/org/rootservices/jwt/factory/UnSecureJwtFactory.java
@@ -20,7 +20,7 @@ public JsonWebToken makeJwt(Claims claimNames) {
JsonWebToken jwt = new JsonWebToken();
jwt.setHeader(header);
jwt.setClaims(claimNames);
- jwt.setSignature(Optional.empty());
+ jwt.setSignature(Optional.empty());
return jwt;
}
diff --git a/src/main/java/org/rootservices/jwt/jwe/Transformation.java b/src/main/java/org/rootservices/jwt/jwe/Transformation.java
new file mode 100644
index 0000000..05c72c7
--- /dev/null
+++ b/src/main/java/org/rootservices/jwt/jwe/Transformation.java
@@ -0,0 +1,17 @@
+package org.rootservices.jwt.jwe;
+
+public enum Transformation {
+ // RSA_OAEP ("RSA/ECB/OAEPWithSHA-1AndMGF1Padding"),
+ RSA_OAEP ("RSA/ECB/OAEPPadding"),
+ AES_GCM_NO_PADDING ("AES/GCM/NoPadding");
+
+ private String value;
+
+ Transformation(String value) {
+ this.value = value;
+ }
+
+ public String getValue() {
+ return value;
+ }
+}
diff --git a/src/main/java/org/rootservices/jwt/jwe/entity/JWE.java b/src/main/java/org/rootservices/jwt/jwe/entity/JWE.java
new file mode 100644
index 0000000..d771892
--- /dev/null
+++ b/src/main/java/org/rootservices/jwt/jwe/entity/JWE.java
@@ -0,0 +1,61 @@
+package org.rootservices.jwt.jwe.entity;
+
+import org.rootservices.jwt.entity.jwt.header.Header;
+
+public class JWE {
+ private Header header;
+ private byte[] payload;
+ private byte[] cek;
+ private byte[] iv;
+ private byte[] authTag;
+
+ public JWE() {}
+
+ public JWE(Header header, byte[] payload, byte[] cek, byte[] iv, byte[] authTag) {
+ this.header = header;
+ this.payload = payload;
+ this.cek = cek;
+ this.iv = iv;
+ this.authTag = authTag;
+ }
+
+ public Header getHeader() {
+ return header;
+ }
+
+ public void setHeader(Header header) {
+ this.header = header;
+ }
+
+ public byte[] getPayload() {
+ return payload;
+ }
+
+ public void setPayload(byte[] payload) {
+ this.payload = payload;
+ }
+
+ public byte[] getCek() {
+ return cek;
+ }
+
+ public void setCek(byte[] cek) {
+ this.cek = cek;
+ }
+
+ public byte[] getIv() {
+ return iv;
+ }
+
+ public void setIv(byte[] iv) {
+ this.iv = iv;
+ }
+
+ public byte[] getAuthTag() {
+ return authTag;
+ }
+
+ public void setAuthTag(byte[] authTag) {
+ this.authTag = authTag;
+ }
+}
diff --git a/src/main/java/org/rootservices/jwt/jwe/exception/EncryptException.java b/src/main/java/org/rootservices/jwt/jwe/exception/EncryptException.java
new file mode 100644
index 0000000..a505ee6
--- /dev/null
+++ b/src/main/java/org/rootservices/jwt/jwe/exception/EncryptException.java
@@ -0,0 +1,7 @@
+package org.rootservices.jwt.jwe.exception;
+
+public class EncryptException extends Exception {
+ public EncryptException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/src/main/java/org/rootservices/jwt/jwe/factory/CipherRSAFactory.java b/src/main/java/org/rootservices/jwt/jwe/factory/CipherRSAFactory.java
new file mode 100644
index 0000000..ab58ff8
--- /dev/null
+++ b/src/main/java/org/rootservices/jwt/jwe/factory/CipherRSAFactory.java
@@ -0,0 +1,65 @@
+package org.rootservices.jwt.jwe.factory;
+
+import org.rootservices.jwt.jwe.Transformation;
+import org.rootservices.jwt.jwe.factory.exception.CipherException;
+
+import javax.crypto.Cipher;
+import javax.crypto.NoSuchPaddingException;
+import javax.crypto.spec.OAEPParameterSpec;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.Key;
+import java.security.NoSuchAlgorithmException;
+import java.security.spec.AlgorithmParameterSpec;
+
+/**
+ * https://docs.oracle.com/javase/9/docs/api/javax/crypto/spec/OAEPParameterSpec.html
+ * https://security.stackexchange.com/questions/97548/breaking-down-rsa-ecb-oaepwithsha-256andmgf1padding
+ */
+public class CipherRSAFactory {
+ public static final String ALGORITHM_WAS_INVALID = "Algorithm, %s, was invalid";
+ public static final String PADDING_WAS_INVALID = "Padding for algorithm, %s, was invalid";
+ public static final String KEY_WAS_INVALID_INIT_CIPHER = "Key was invalid when initializing cipher";
+ public static final String ALGORITHM_WAS_INVALID_INIT_CIPHER = "Algorithm, %s, was invalid when initializing cipher";
+
+ public Cipher forEncrypt(Transformation transformation, Key key) throws CipherException {
+ AlgorithmParameterSpec spec = makeSpec(transformation);
+ Cipher cipher = makeCipher(transformation, key, Cipher.ENCRYPT_MODE, spec);
+ return cipher;
+ }
+
+ public Cipher forDecrypt(Transformation transformation, Key key) throws CipherException {
+ AlgorithmParameterSpec spec = makeSpec(transformation);
+ Cipher cipher = makeCipher(transformation, key, Cipher.DECRYPT_MODE, spec);
+ return cipher;
+ }
+
+ protected AlgorithmParameterSpec makeSpec(Transformation transformation) {
+ AlgorithmParameterSpec spec = null;
+ if (transformation == Transformation.RSA_OAEP) {
+ spec = OAEPParameterSpec.DEFAULT;
+ }
+ return spec;
+ }
+
+ protected Cipher makeCipher(Transformation transformation, Key key, int mode, AlgorithmParameterSpec spec) throws CipherException {
+ Cipher cipher;
+ try {
+ cipher = Cipher.getInstance(transformation.getValue());
+ } catch (NoSuchAlgorithmException e) {
+ throw new CipherException(String.format(ALGORITHM_WAS_INVALID, transformation.getValue()), e);
+ } catch (NoSuchPaddingException e) {
+ throw new CipherException(String.format(PADDING_WAS_INVALID, transformation.getValue()), e);
+ }
+
+ try {
+ cipher.init(mode, key, spec);
+ } catch (InvalidKeyException e) {
+ throw new CipherException(KEY_WAS_INVALID_INIT_CIPHER, e);
+ } catch (InvalidAlgorithmParameterException e) {
+ throw new CipherException(String.format(ALGORITHM_WAS_INVALID_INIT_CIPHER, transformation.getValue()), e);
+ }
+
+ return cipher;
+ }
+}
diff --git a/src/main/java/org/rootservices/jwt/jwe/factory/CipherSymmetricFactory.java b/src/main/java/org/rootservices/jwt/jwe/factory/CipherSymmetricFactory.java
new file mode 100644
index 0000000..ee52487
--- /dev/null
+++ b/src/main/java/org/rootservices/jwt/jwe/factory/CipherSymmetricFactory.java
@@ -0,0 +1,101 @@
+package org.rootservices.jwt.jwe.factory;
+
+import org.rootservices.jwt.jwe.Transformation;
+import org.rootservices.jwt.jwe.factory.exception.CipherException;
+import org.rootservices.jwt.jwk.KeyAlgorithm;
+
+import javax.crypto.Cipher;
+import javax.crypto.NoSuchPaddingException;
+import javax.crypto.SecretKey;
+import javax.crypto.spec.GCMParameterSpec;
+import javax.crypto.spec.OAEPParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+import java.security.*;
+import java.security.spec.AlgorithmParameterSpec;
+
+/**
+ * AES-GCM
+ * https://wiki.sei.cmu.edu/confluence/display/java/MSC61-J.+Do+not+use+insecure+or+weak+cryptographic+algorithms
+ * https://gist.github.com/praseodym/f2499b3e14d872fe5b4a
+ *
+ * OAEP
+ * https://stackoverflow.com/questions/32161720/breaking-down-rsa-ecb-oaepwithsha-256andmgf1padding
+ * https://docs.oracle.com/javase/9/docs/api/javax/crypto/spec/OAEPParameterSpec.html
+ * https://docs.oracle.com/cd/E23943_01/security.1111/e10037/crypto.htm#BJFCICAE
+ *
+ * https://docs.oracle.com/javase/9/docs/api/javax/crypto/spec/OAEPParameterSpec.html
+ * https://security.stackexchange.com/questions/97548/breaking-down-rsa-ecb-oaepwithsha-256andmgf1padding
+ */
+public class CipherSymmetricFactory {
+ public static final int GCM_TAG_LENGTH = 128;
+ public static final int GCM_IV_LENGTH = 96;
+ public static final String ALGORITHM_WAS_INVALID = "Algorithm, %s, was invalid";
+ public static final String PADDING_WAS_INVALID = "Padding for algorithm, %s, was invalid";
+ public static final String KEY_WAS_INVALID_INIT_CIPHER = "Key was invalid when initializing cipher";
+ public static final String ALGORITHM_WAS_INVALID_INIT_CIPHER = "Algorithm, %s, was invalid when initializing cipher";
+
+ private static SecureRandom secureRandom = new SecureRandom();
+
+ public Cipher forEncrypt(Transformation transformation, Key key, byte[] aad) throws CipherException {
+
+ byte[] initVector = makeInitVector();
+ AlgorithmParameterSpec spec = makeSpec(transformation, initVector);
+ Cipher cipher = makeCipher(transformation, key, Cipher.ENCRYPT_MODE, spec, aad);
+ return cipher;
+ }
+
+ public Cipher forDecrypt(Transformation transformation, Key key, byte[] initVector, byte[] aad) throws CipherException {
+ AlgorithmParameterSpec spec = makeSpec(transformation, initVector);
+ Cipher cipher = makeCipher(transformation, key, Cipher.DECRYPT_MODE, spec, aad);
+ return cipher;
+ }
+
+ public Cipher forDecrypt(Transformation transformation, byte[] cek, byte[] initVector, byte[] aad) throws CipherException {
+ SecretKey key = new SecretKeySpec(cek, KeyAlgorithm.AES.getValue());
+ Cipher cipher;
+ try {
+ cipher = forDecrypt(transformation, key, initVector, aad);
+ } catch (CipherException e) {
+ throw e;
+ }
+
+ return cipher;
+ }
+
+ public byte[] makeInitVector() {
+ byte[] initVector = new byte[GCM_IV_LENGTH];
+ secureRandom.nextBytes(initVector);
+ return initVector;
+ }
+
+ protected AlgorithmParameterSpec makeSpec(Transformation transformation, byte[] initVector) {
+ AlgorithmParameterSpec spec = null;
+ if (transformation == Transformation.AES_GCM_NO_PADDING) {
+ spec = new GCMParameterSpec(GCM_TAG_LENGTH, initVector);
+ }
+ return spec;
+ }
+
+ protected Cipher makeCipher(Transformation transformation, Key key, int mode, AlgorithmParameterSpec spec, byte[] aad) throws CipherException {
+ Cipher cipher;
+ try {
+ cipher = Cipher.getInstance(transformation.getValue());
+ } catch (NoSuchAlgorithmException e) {
+ throw new CipherException(String.format(ALGORITHM_WAS_INVALID, transformation.getValue()), e);
+ } catch (NoSuchPaddingException e) {
+ throw new CipherException(String.format(PADDING_WAS_INVALID, transformation.getValue()), e);
+ }
+
+ try {
+ cipher.init(mode, key, spec);
+ } catch (InvalidKeyException e) {
+ throw new CipherException(KEY_WAS_INVALID_INIT_CIPHER, e);
+ } catch (InvalidAlgorithmParameterException e) {
+ throw new CipherException(String.format(ALGORITHM_WAS_INVALID_INIT_CIPHER, transformation.getValue()), e);
+ }
+
+ cipher.updateAAD(aad);
+ return cipher;
+ }
+
+}
diff --git a/src/main/java/org/rootservices/jwt/jwe/factory/exception/CipherException.java b/src/main/java/org/rootservices/jwt/jwe/factory/exception/CipherException.java
new file mode 100644
index 0000000..b7c21e8
--- /dev/null
+++ b/src/main/java/org/rootservices/jwt/jwe/factory/exception/CipherException.java
@@ -0,0 +1,7 @@
+package org.rootservices.jwt.jwe.factory.exception;
+
+public class CipherException extends Exception {
+ public CipherException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/src/main/java/org/rootservices/jwt/jwe/serialization/JweDeserializer.java b/src/main/java/org/rootservices/jwt/jwe/serialization/JweDeserializer.java
new file mode 100644
index 0000000..284c36f
--- /dev/null
+++ b/src/main/java/org/rootservices/jwt/jwe/serialization/JweDeserializer.java
@@ -0,0 +1,33 @@
+package org.rootservices.jwt.jwe.serialization;
+
+import org.rootservices.jwt.entity.jwk.Key;
+import org.rootservices.jwt.jwe.entity.JWE;
+import org.rootservices.jwt.jwe.factory.exception.CipherException;
+import org.rootservices.jwt.jwe.serialization.exception.KeyException;
+import org.rootservices.jwt.serialization.exception.DecryptException;
+import org.rootservices.jwt.serialization.exception.JsonToJwtException;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+
+public interface JweDeserializer {
+ String JWT_SPLITTER = "\\.";
+ String COMPACT_JWE_INVALID = "Compact JWE is invalid";
+ String COULD_NOT_DECRYPT_ENCRYPTED_KEY = "Could not Decrypt encrypted key";
+ String COULD_NOT_DECRYPT_CIPHER_TEXT = "Could not decrypt cipher text";
+ String COULD_NOT_COMBINE_CIPHER_TEXT_AND_AT = "Could not combine cipher text with authentication tag";
+
+ JWE stringToJWE(String compactJWE, Key cek) throws JsonToJwtException, DecryptException, CipherException, KeyException;
+
+ default byte[] cipherTextWithAuthTag(byte[] cipherText, byte[] authTag) throws DecryptException {
+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream( );
+ try {
+ outputStream.write(cipherText);
+ outputStream.write(authTag);
+ } catch (IOException e) {
+ throw new DecryptException(COULD_NOT_COMBINE_CIPHER_TEXT_AND_AT, e);
+ }
+
+ return outputStream.toByteArray();
+ }
+}
diff --git a/src/main/java/org/rootservices/jwt/jwe/serialization/JweSerializer.java b/src/main/java/org/rootservices/jwt/jwe/serialization/JweSerializer.java
new file mode 100644
index 0000000..5929d2a
--- /dev/null
+++ b/src/main/java/org/rootservices/jwt/jwe/serialization/JweSerializer.java
@@ -0,0 +1,59 @@
+package org.rootservices.jwt.jwe.serialization;
+
+import org.rootservices.jwt.jwe.entity.JWE;
+import org.rootservices.jwt.jwe.factory.CipherSymmetricFactory;
+import org.rootservices.jwt.jwe.factory.exception.CipherException;
+import org.rootservices.jwt.serialization.exception.EncryptException;
+import org.rootservices.jwt.serialization.exception.JsonToJwtException;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.List;
+
+public interface JweSerializer {
+ byte[] DELIMITER = ".".getBytes();
+ String COULD_NOT_COMPACT = "Could not compact";
+ ByteArrayOutputStream JWEToCompact(JWE jwe) throws JsonToJwtException, CipherException, EncryptException;
+
+ default byte[] extractCipherText(byte[] cipherTextWithAuthTag) {
+ int tagLength = CipherSymmetricFactory.GCM_TAG_LENGTH / Byte.SIZE;
+ int cipherTextEnd = cipherTextWithAuthTag.length - tagLength;
+
+ byte[] cipherText = new byte[cipherTextEnd];
+ System.arraycopy(cipherTextWithAuthTag, 0, cipherText, 0, cipherTextEnd);
+ return cipherText;
+ }
+
+ default byte[] extractAuthTag(byte[] cipherTextWithAuthTag) {
+ int tagLength = CipherSymmetricFactory.GCM_TAG_LENGTH / Byte.SIZE;
+ int cipherTextEnd = cipherTextWithAuthTag.length - tagLength;
+
+ byte[] authTag = new byte[tagLength];
+ System.arraycopy(cipherTextWithAuthTag, cipherTextEnd, authTag, 0, tagLength);
+ return authTag;
+ }
+
+ default ByteArrayOutputStream toCompact(List jweParts) throws EncryptException {
+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream( );
+
+ for(int i=0; i < jweParts.size(); i++) {
+ if (jweParts.get(i) != null) {
+ try {
+ outputStream.write(jweParts.get(i));
+ } catch (IOException e) {
+ throw new EncryptException(COULD_NOT_COMPACT, e);
+ }
+ }
+
+ if (i < jweParts.size() - 1) {
+ try {
+ outputStream.write(DELIMITER);
+ } catch (IOException e) {
+ throw new EncryptException(COULD_NOT_COMPACT, e);
+ }
+ }
+ }
+
+ return outputStream;
+ }
+}
diff --git a/src/main/java/org/rootservices/jwt/jwe/serialization/direct/JweDirectDesializer.java b/src/main/java/org/rootservices/jwt/jwe/serialization/direct/JweDirectDesializer.java
new file mode 100644
index 0000000..e8c96b9
--- /dev/null
+++ b/src/main/java/org/rootservices/jwt/jwe/serialization/direct/JweDirectDesializer.java
@@ -0,0 +1,72 @@
+package org.rootservices.jwt.jwe.serialization.direct;
+
+import org.rootservices.jwt.entity.jwk.Key;
+import org.rootservices.jwt.entity.jwk.SymmetricKey;
+import org.rootservices.jwt.entity.jwt.header.Header;
+import org.rootservices.jwt.jwe.Transformation;
+import org.rootservices.jwt.jwe.entity.JWE;
+import org.rootservices.jwt.jwe.factory.CipherSymmetricFactory;
+import org.rootservices.jwt.jwe.factory.exception.CipherException;
+import org.rootservices.jwt.jwe.serialization.JweDeserializer;
+import org.rootservices.jwt.serialization.Serdes;
+import org.rootservices.jwt.serialization.exception.DecryptException;
+import org.rootservices.jwt.serialization.exception.JsonException;
+import org.rootservices.jwt.serialization.exception.JsonToJwtException;
+
+import javax.crypto.BadPaddingException;
+import javax.crypto.Cipher;
+import javax.crypto.IllegalBlockSizeException;
+import java.nio.charset.StandardCharsets;
+import java.util.Base64;
+
+
+public class JweDirectDesializer implements JweDeserializer {
+ private Serdes serdes;
+ private Base64.Decoder decoder;
+ private CipherSymmetricFactory cipherSymmetricFactory;
+
+ public JweDirectDesializer(Serdes serdes, Base64.Decoder decoder, CipherSymmetricFactory cipherSymmetricFactory) {
+ this.serdes = serdes;
+ this.decoder = decoder;
+ this.cipherSymmetricFactory = cipherSymmetricFactory;
+ }
+
+ @Override
+ public JWE stringToJWE(String compactJWE, Key key) throws JsonToJwtException, DecryptException, CipherException {
+ String[] jweParts = compactJWE.split(JWT_SPLITTER);
+ byte[] protectedHeader = decoder.decode(jweParts[0]);
+ byte[] initVector = decoder.decode(jweParts[2]);
+ byte[] cipherText = decoder.decode(jweParts[3]);
+ byte[] authenticationTag = decoder.decode(jweParts[4]);
+
+ Header header;
+ try {
+ header = (Header) serdes.jsonBytesToObject(protectedHeader, Header.class);
+ } catch (JsonException e) {
+ throw new JsonToJwtException(COMPACT_JWE_INVALID, e);
+ }
+
+ byte[] aad = jweParts[0].getBytes(StandardCharsets.US_ASCII);
+
+ byte[] cek = decoder.decode(((SymmetricKey) key).getKey().getBytes());
+ Cipher symmetricCipher;
+ try {
+ symmetricCipher = cipherSymmetricFactory.forDecrypt(Transformation.AES_GCM_NO_PADDING, cek, initVector, aad);
+ } catch (CipherException e) {
+ throw e;
+ }
+
+ byte[] cipherTextWithAuthTag = cipherTextWithAuthTag(cipherText, authenticationTag);
+
+ byte[] payload;
+ try {
+ payload = symmetricCipher.doFinal(cipherTextWithAuthTag);
+ } catch (IllegalBlockSizeException e) {
+ throw new DecryptException(COULD_NOT_DECRYPT_CIPHER_TEXT, e);
+ } catch (BadPaddingException e) {
+ throw new DecryptException(COULD_NOT_DECRYPT_CIPHER_TEXT, e);
+ }
+
+ return new JWE(header, payload, cek, initVector, authenticationTag);
+ }
+}
diff --git a/src/main/java/org/rootservices/jwt/jwe/serialization/direct/JweDirectSerializer.java b/src/main/java/org/rootservices/jwt/jwe/serialization/direct/JweDirectSerializer.java
new file mode 100644
index 0000000..76a9379
--- /dev/null
+++ b/src/main/java/org/rootservices/jwt/jwe/serialization/direct/JweDirectSerializer.java
@@ -0,0 +1,95 @@
+package org.rootservices.jwt.jwe.serialization.direct;
+
+import org.rootservices.jwt.jwe.Transformation;
+import org.rootservices.jwt.jwe.entity.JWE;
+import org.rootservices.jwt.jwe.factory.CipherSymmetricFactory;
+import org.rootservices.jwt.jwe.factory.exception.CipherException;
+import org.rootservices.jwt.jwe.serialization.JweSerializer;
+import org.rootservices.jwt.jwk.KeyAlgorithm;
+import org.rootservices.jwt.serialization.Serdes;
+import org.rootservices.jwt.serialization.exception.EncryptException;
+import org.rootservices.jwt.serialization.exception.JsonException;
+import org.rootservices.jwt.serialization.exception.JsonToJwtException;
+
+import javax.crypto.BadPaddingException;
+import javax.crypto.Cipher;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.SecretKey;
+import javax.crypto.spec.SecretKeySpec;
+import java.io.ByteArrayOutputStream;
+import java.util.ArrayList;
+import java.util.Base64;
+import java.util.List;
+
+public class JweDirectSerializer implements JweSerializer {
+ public static final String COULD_NOT_ENCRYPT = "Could not encrypt content";
+ public static final String HEADER_IS_INVALID = "Header is invalid. Could not serialize to it to JSON";
+
+ private Serdes serdes;
+ private Base64.Encoder encoder;
+ private CipherSymmetricFactory cipherSymmetricFactory;
+
+ public JweDirectSerializer(Serdes serdes, Base64.Encoder encoder, CipherSymmetricFactory cipherSymmetricFactory) {
+ this.serdes = serdes;
+ this.encoder = encoder;
+ this.cipherSymmetricFactory = cipherSymmetricFactory;
+ }
+
+ /**
+ * Generates a compact JWE.
+ *
+ * Ignores the value for the jwe iv and generates a new one.
+ *
+ * The variable symmetricCipher is a propagating dependency. It cannot be reused per
+ * encryption attempt because it requires a new iv and aad per attempt.
+ *
+ * @param jwe must have values for header, cek, payload. Ignores the value for iv and generates a new one.
+ * @return a ByteArrayOutputStream that is a compact JWE
+ * @throws JsonToJwtException if the header cannot be serialized.
+ * @throws CipherException if the cipher for encryption could not be instantiated
+ * @throws EncryptException if the payload could not be encrypted
+ */
+ @Override
+ public ByteArrayOutputStream JWEToCompact(JWE jwe) throws JsonToJwtException, CipherException, EncryptException {
+ byte[] protectedHeader;
+ try {
+ protectedHeader = serdes.objectToByte(jwe.getHeader());
+ } catch (JsonException e) {
+ throw new JsonToJwtException(HEADER_IS_INVALID, e);
+ }
+
+ byte[] aad = encoder.encode(protectedHeader);
+
+ SecretKey key = new SecretKeySpec(jwe.getCek(), KeyAlgorithm.AES.getValue());
+
+ Cipher symmetricCipher;
+ try {
+ symmetricCipher = cipherSymmetricFactory.forEncrypt(Transformation.AES_GCM_NO_PADDING, key, aad);
+ } catch (CipherException e) {
+ throw e;
+ }
+
+ byte[] cipherTextWithAuthTag;
+ try {
+ cipherTextWithAuthTag = symmetricCipher.doFinal(jwe.getPayload());
+ } catch (IllegalBlockSizeException e) {
+ throw new EncryptException(COULD_NOT_ENCRYPT, e);
+ } catch (BadPaddingException e) {
+ throw new EncryptException(COULD_NOT_ENCRYPT, e);
+ }
+
+
+ byte[] initVector = symmetricCipher.getIV();
+ byte[] cipherText = extractCipherText(cipherTextWithAuthTag);
+ byte[] authTag = extractAuthTag(cipherTextWithAuthTag);
+
+ List jweParts = new ArrayList<>();
+ jweParts.add(encoder.encode(protectedHeader));
+ jweParts.add(null);
+ jweParts.add(encoder.encode(initVector));
+ jweParts.add(encoder.encode(cipherText));
+ jweParts.add(encoder.encode(authTag));
+
+ return toCompact(jweParts);
+ }
+}
diff --git a/src/main/java/org/rootservices/jwt/jwe/serialization/exception/KeyException.java b/src/main/java/org/rootservices/jwt/jwe/serialization/exception/KeyException.java
new file mode 100644
index 0000000..5d3dae6
--- /dev/null
+++ b/src/main/java/org/rootservices/jwt/jwe/serialization/exception/KeyException.java
@@ -0,0 +1,7 @@
+package org.rootservices.jwt.jwe.serialization.exception;
+
+public class KeyException extends Exception {
+ public KeyException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/src/main/java/org/rootservices/jwt/jwe/serialization/rsa/JweRsaDeserializer.java b/src/main/java/org/rootservices/jwt/jwe/serialization/rsa/JweRsaDeserializer.java
new file mode 100644
index 0000000..4c874a0
--- /dev/null
+++ b/src/main/java/org/rootservices/jwt/jwe/serialization/rsa/JweRsaDeserializer.java
@@ -0,0 +1,104 @@
+package org.rootservices.jwt.jwe.serialization.rsa;
+
+import org.rootservices.jwt.entity.jwk.Key;
+import org.rootservices.jwt.entity.jwk.RSAKeyPair;
+import org.rootservices.jwt.jwe.Transformation;
+import org.rootservices.jwt.jwe.entity.JWE;
+import org.rootservices.jwt.jwe.factory.CipherRSAFactory;
+import org.rootservices.jwt.jwe.factory.CipherSymmetricFactory;
+import org.rootservices.jwt.jwe.factory.exception.CipherException;
+import org.rootservices.jwt.entity.jwt.header.Header;
+import org.rootservices.jwt.jwe.serialization.JweDeserializer;
+import org.rootservices.jwt.jwe.serialization.exception.KeyException;
+import org.rootservices.jwt.jwk.PrivateKeyFactory;
+import org.rootservices.jwt.jws.signer.factory.rsa.exception.PrivateKeyException;
+import org.rootservices.jwt.serialization.Serdes;
+import org.rootservices.jwt.serialization.exception.DecryptException;
+import org.rootservices.jwt.serialization.exception.JsonException;
+import org.rootservices.jwt.serialization.exception.JsonToJwtException;
+
+
+import javax.crypto.*;
+
+import java.nio.charset.StandardCharsets;
+import java.security.interfaces.RSAPrivateCrtKey;
+import java.util.Base64;
+
+public class JweRsaDeserializer implements JweDeserializer {
+
+ private Serdes serdes;
+ private Base64.Decoder decoder;
+ private PrivateKeyFactory privateKeyFactory;
+ private CipherRSAFactory cipherRSAFactory;
+ private CipherSymmetricFactory cipherSymmetricFactory;
+
+ public JweRsaDeserializer(Serdes serdes, Base64.Decoder decoder, PrivateKeyFactory privateKeyFactory, CipherRSAFactory cipherRSAFactory, CipherSymmetricFactory cipherSymmetricFactory) {
+ this.serdes = serdes;
+ this.decoder = decoder;
+ this.privateKeyFactory = privateKeyFactory;
+ this.cipherRSAFactory = cipherRSAFactory;
+ this.cipherSymmetricFactory = cipherSymmetricFactory;
+ }
+
+ public JWE stringToJWE(String compactJWE, Key key) throws JsonToJwtException, DecryptException, CipherException, KeyException {
+ String[] jweParts = compactJWE.split(JWT_SPLITTER);
+ byte[] protectedHeader = decoder.decode(jweParts[0]);
+ byte[] encryptedKey = decoder.decode(jweParts[1]);
+ byte[] initVector = decoder.decode(jweParts[2]);
+ byte[] cipherText = decoder.decode(jweParts[3]);
+ byte[] authenticationTag = decoder.decode(jweParts[4]);
+
+ Header header;
+ try {
+ header = (Header) serdes.jsonBytesToObject(protectedHeader, Header.class);
+ } catch (JsonException e) {
+ throw new JsonToJwtException(COMPACT_JWE_INVALID, e);
+ }
+
+ RSAKeyPair keyPair = (RSAKeyPair) key;
+ RSAPrivateCrtKey jdkKey;
+ try {
+ jdkKey = privateKeyFactory.makePrivateKey(keyPair);
+ } catch (PrivateKeyException e) {
+ throw new KeyException("", e);
+ }
+
+ Cipher rsaDecryptCipher;
+ try {
+ rsaDecryptCipher = cipherRSAFactory.forDecrypt(Transformation.RSA_OAEP, jdkKey);
+ } catch (CipherException e) {
+ throw e;
+ }
+
+ byte[] cek;
+ try {
+ cek = rsaDecryptCipher.doFinal(encryptedKey);
+ } catch (IllegalBlockSizeException e) {
+ throw new DecryptException(COULD_NOT_DECRYPT_ENCRYPTED_KEY, e);
+ } catch (BadPaddingException e) {
+ throw new DecryptException(COULD_NOT_DECRYPT_ENCRYPTED_KEY, e);
+ }
+
+ byte[] aad = jweParts[0].getBytes(StandardCharsets.US_ASCII);
+
+ Cipher symmetricCipher;
+ try {
+ symmetricCipher = cipherSymmetricFactory.forDecrypt(Transformation.AES_GCM_NO_PADDING, cek, initVector, aad);
+ } catch (CipherException e) {
+ throw e;
+ }
+
+ byte[] cipherTextWithAuthTag = cipherTextWithAuthTag(cipherText, authenticationTag);
+
+ byte[] payload;
+ try {
+ payload = symmetricCipher.doFinal(cipherTextWithAuthTag);
+ } catch (IllegalBlockSizeException e) {
+ throw new DecryptException(COULD_NOT_DECRYPT_CIPHER_TEXT, e);
+ } catch (BadPaddingException e) {
+ throw new DecryptException(COULD_NOT_DECRYPT_CIPHER_TEXT, e);
+ }
+
+ return new JWE(header, payload, cek, initVector, authenticationTag);
+ }
+}
diff --git a/src/main/java/org/rootservices/jwt/jwe/serialization/rsa/JweRsaSerializer.java b/src/main/java/org/rootservices/jwt/jwe/serialization/rsa/JweRsaSerializer.java
new file mode 100644
index 0000000..3b59e41
--- /dev/null
+++ b/src/main/java/org/rootservices/jwt/jwe/serialization/rsa/JweRsaSerializer.java
@@ -0,0 +1,112 @@
+package org.rootservices.jwt.jwe.serialization.rsa;
+
+import org.rootservices.jwt.jwe.Transformation;
+import org.rootservices.jwt.jwe.entity.JWE;
+import org.rootservices.jwt.jwe.factory.CipherSymmetricFactory;
+import org.rootservices.jwt.jwe.factory.exception.CipherException;
+import org.rootservices.jwt.jwe.serialization.JweSerializer;
+import org.rootservices.jwt.jwk.KeyAlgorithm;
+import org.rootservices.jwt.jwk.SecretKeyFactory;
+import org.rootservices.jwt.jwk.exception.SecretKeyException;
+import org.rootservices.jwt.serialization.Serdes;
+import org.rootservices.jwt.serialization.exception.EncryptException;
+import org.rootservices.jwt.serialization.exception.JsonException;
+import org.rootservices.jwt.serialization.exception.JsonToJwtException;
+
+import javax.crypto.BadPaddingException;
+import javax.crypto.Cipher;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.SecretKey;
+import java.io.ByteArrayOutputStream;
+import java.util.ArrayList;
+import java.util.Base64;
+import java.util.List;
+
+public class JweRsaSerializer implements JweSerializer {
+ public static final String COULD_NOT_ENCRYPT_CEK = "Could not encrypt Content Encryption Key";
+ public static final String COULD_NOT_ENCRYPT = "Could not encrypt content";
+ public static final String HEADER_IS_INVALID = "Header is invalid. Could not serialize to it to JSON";
+ public static final String FAILED_TO_CREATE_CONTENT_ENCRYPTION_KEY = "Failed to create Content Encryption Key";
+ private Serdes serdes;
+ private Base64.Encoder encoder;
+ private Cipher RSAEncryptCipher;
+ private SecretKeyFactory secretKeyFactory;
+ private CipherSymmetricFactory cipherSymmetricFactory;
+
+ public JweRsaSerializer(Serdes serdes, Base64.Encoder encoder, Cipher RSAEncryptCipher, SecretKeyFactory secretKeyFactory, CipherSymmetricFactory cipherSymmetricFactory) {
+ this.serdes = serdes;
+ this.encoder = encoder;
+ this.RSAEncryptCipher = RSAEncryptCipher;
+ this.secretKeyFactory = secretKeyFactory;
+ this.cipherSymmetricFactory = cipherSymmetricFactory;
+ }
+
+ public ByteArrayOutputStream JWEToCompact(JWE jwe) throws JsonToJwtException, CipherException, EncryptException {
+
+ byte[] protectedHeader;
+ try {
+ protectedHeader = serdes.objectToByte(jwe.getHeader());
+ } catch (JsonException e) {
+ throw new JsonToJwtException(HEADER_IS_INVALID, e);
+ }
+
+ byte[] aad = encoder.encode(protectedHeader);
+
+
+ SecretKey cek;
+ try {
+ cek = secretKeyFactory.makeKey(KeyAlgorithm.AES);
+ } catch (SecretKeyException e) {
+ throw new EncryptException(FAILED_TO_CREATE_CONTENT_ENCRYPTION_KEY, e);
+ }
+
+ Cipher symmetricCipher;
+ try {
+ symmetricCipher = symmetricCipherForEncrypt(cek, aad);
+ } catch (CipherException e) {
+ throw e;
+ }
+
+ byte[] cipherTextWithAuthTag;
+ try {
+ cipherTextWithAuthTag = symmetricCipher.doFinal(jwe.getPayload());
+ } catch (IllegalBlockSizeException e) {
+ throw new EncryptException(COULD_NOT_ENCRYPT, e);
+ } catch (BadPaddingException e) {
+ throw new EncryptException(COULD_NOT_ENCRYPT, e);
+ }
+
+ byte[] encryptedKey;
+ try {
+ encryptedKey = RSAEncryptCipher.doFinal(cek.getEncoded());
+ } catch (IllegalBlockSizeException e) {
+ throw new EncryptException(COULD_NOT_ENCRYPT_CEK, e);
+ } catch (BadPaddingException e) {
+ throw new EncryptException(COULD_NOT_ENCRYPT_CEK, e);
+ }
+
+ byte[] initVector = symmetricCipher.getIV();
+ byte[] cipherText = extractCipherText(cipherTextWithAuthTag);
+ byte[] authTag = extractAuthTag(cipherTextWithAuthTag);
+
+ List jweParts = new ArrayList<>();
+ jweParts.add(encoder.encode(protectedHeader));
+ jweParts.add(encoder.encode(encryptedKey));
+ jweParts.add(encoder.encode(initVector));
+ jweParts.add(encoder.encode(cipherText));
+ jweParts.add(encoder.encode(authTag));
+
+ return toCompact(jweParts);
+ }
+
+ protected Cipher symmetricCipherForEncrypt(SecretKey cek, byte[] aad) throws CipherException {
+ Cipher cipher;
+ try {
+ cipher = cipherSymmetricFactory.forEncrypt(Transformation.AES_GCM_NO_PADDING, cek, aad);
+ } catch (CipherException e) {
+ throw e;
+ }
+
+ return cipher;
+ }
+}
diff --git a/src/main/java/org/rootservices/jwt/jwk/KeyAlgorithm.java b/src/main/java/org/rootservices/jwt/jwk/KeyAlgorithm.java
new file mode 100644
index 0000000..744162a
--- /dev/null
+++ b/src/main/java/org/rootservices/jwt/jwk/KeyAlgorithm.java
@@ -0,0 +1,19 @@
+package org.rootservices.jwt.jwk;
+
+/**
+ * https://docs.oracle.com/javase/7/docs/technotes/guides/security/StandardNames.html#KeyGenerator
+ */
+public enum KeyAlgorithm {
+ AES ("AES");
+
+ private String value;
+
+ KeyAlgorithm(String value) {
+ this.value = value;
+ }
+
+ public String getValue() {
+ return value;
+ }
+}
+
diff --git a/src/main/java/org/rootservices/jwt/jwk/PrivateKeyFactory.java b/src/main/java/org/rootservices/jwt/jwk/PrivateKeyFactory.java
new file mode 100644
index 0000000..8126622
--- /dev/null
+++ b/src/main/java/org/rootservices/jwt/jwk/PrivateKeyFactory.java
@@ -0,0 +1,55 @@
+package org.rootservices.jwt.jwk;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.rootservices.jwt.entity.jwk.RSAKeyPair;
+import org.rootservices.jwt.jws.signer.factory.rsa.exception.PrivateKeyException;
+
+import java.security.KeyFactory;
+import java.security.interfaces.RSAPrivateCrtKey;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.RSAPrivateCrtKeySpec;
+import java.security.spec.RSAPrivateKeySpec;
+
+
+public class PrivateKeyFactory {
+ private static final Logger LOGGER = LogManager.getLogger(PrivateKeyFactory.class);
+ public static final String PRIVATE_KEY_ERROR_MSG = "Could not make RSAPrivateCrtKey";
+ private KeyFactory RSAKeyFactory;
+
+ public PrivateKeyFactory(KeyFactory RSAKeyFactory) {
+ this.RSAKeyFactory = RSAKeyFactory;
+ }
+
+ /**
+ * Returns a, RSAPrivateCrtKey, which is built from the input parameter, jwk.
+ * A RSAPrivateCrtKey is needed per, https://tools.ietf.org/html/rfc7517#section-9.3
+ *
+ * @param jwk a RSAKeyPair
+ * @return an instance of RSAPrivateCrtKey
+ * @throws PrivateKeyException if jwk is invalid.
+ */
+ public RSAPrivateCrtKey makePrivateKey(RSAKeyPair jwk) throws PrivateKeyException {
+ RSAPrivateKeySpec keySpec;
+
+ keySpec = new RSAPrivateCrtKeySpec(
+ jwk.getN(), // modulus
+ jwk.getE(), // publicExponent
+ jwk.getD(), // privateExponent
+ jwk.getP(), // primeP
+ jwk.getQ(), // primeQ
+ jwk.getDp(), // primeExponentP
+ jwk.getDq(), // primeExponentQ
+ jwk.getQi() // crtCoefficient
+ );
+
+ RSAPrivateCrtKey privateKey;
+ try {
+ privateKey = (RSAPrivateCrtKey) RSAKeyFactory.generatePrivate(keySpec);
+ } catch (InvalidKeySpecException e) {
+ throw new PrivateKeyException(PRIVATE_KEY_ERROR_MSG, e);
+ }
+
+ return privateKey;
+ }
+}
diff --git a/src/main/java/org/rootservices/jwt/jwk/PublicKeyFactory.java b/src/main/java/org/rootservices/jwt/jwk/PublicKeyFactory.java
new file mode 100644
index 0000000..569e531
--- /dev/null
+++ b/src/main/java/org/rootservices/jwt/jwk/PublicKeyFactory.java
@@ -0,0 +1,30 @@
+package org.rootservices.jwt.jwk;
+
+import org.rootservices.jwt.entity.jwk.RSAPublicKey;
+import org.rootservices.jwt.jws.signer.factory.rsa.exception.PublicKeyException;
+
+import java.security.KeyFactory;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.RSAPublicKeySpec;
+
+public class PublicKeyFactory {
+ private KeyFactory RSAKeyFactory;
+
+ public PublicKeyFactory(KeyFactory RSAKeyFactory) {
+ this.RSAKeyFactory = RSAKeyFactory;
+ }
+
+ public java.security.interfaces.RSAPublicKey makePublicKey(RSAPublicKey jwk) throws PublicKeyException {
+
+ RSAPublicKeySpec rsaPublicKeySpec = new RSAPublicKeySpec(jwk.getN(), jwk.getE());
+ java.security.interfaces.RSAPublicKey publicKey = null;
+ try {
+ publicKey = (java.security.interfaces.RSAPublicKey) RSAKeyFactory.generatePublic(rsaPublicKeySpec);
+ } catch (InvalidKeySpecException e) {
+ // will only reach here if there's something wrong with the RSAPublicKey
+ throw new PublicKeyException("Could not make java.security.interfaces.RSAPublicKey", e);
+ }
+
+ return publicKey;
+ }
+}
diff --git a/src/main/java/org/rootservices/jwt/jwk/SecretKeyFactory.java b/src/main/java/org/rootservices/jwt/jwk/SecretKeyFactory.java
new file mode 100644
index 0000000..cc92d55
--- /dev/null
+++ b/src/main/java/org/rootservices/jwt/jwk/SecretKeyFactory.java
@@ -0,0 +1,28 @@
+package org.rootservices.jwt.jwk;
+
+import org.rootservices.jwt.jwk.exception.SecretKeyException;
+
+import javax.crypto.KeyGenerator;
+import javax.crypto.SecretKey;
+import java.security.NoSuchAlgorithmException;
+
+
+public class SecretKeyFactory {
+ public static final String MESSAGE = "Could not construct key generator";
+ private static int keySize = 256;
+
+ public SecretKey makeKey(KeyAlgorithm keyAlgorithm) throws SecretKeyException {
+ // docs say KeyGenerators can be reused as long as they use the same init values.
+ // Depending on the cost to create these this could be held onto for future use.
+ KeyGenerator keyGenerator = null;
+ try {
+ keyGenerator = KeyGenerator.getInstance(keyAlgorithm.getValue());
+ } catch (NoSuchAlgorithmException e) {
+ throw new SecretKeyException(MESSAGE, e);
+ }
+
+ keyGenerator.init(keySize);
+
+ return keyGenerator.generateKey();
+ }
+}
diff --git a/src/main/java/org/rootservices/jwt/jwk/exception/SecretKeyException.java b/src/main/java/org/rootservices/jwt/jwk/exception/SecretKeyException.java
new file mode 100644
index 0000000..ae36b97
--- /dev/null
+++ b/src/main/java/org/rootservices/jwt/jwk/exception/SecretKeyException.java
@@ -0,0 +1,7 @@
+package org.rootservices.jwt.jwk.exception;
+
+public class SecretKeyException extends Exception {
+ public SecretKeyException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/src/main/java/org/rootservices/jwt/jws/serialization/SecureJwtSerializer.java b/src/main/java/org/rootservices/jwt/jws/serialization/SecureJwtSerializer.java
new file mode 100644
index 0000000..a1eb9b9
--- /dev/null
+++ b/src/main/java/org/rootservices/jwt/jws/serialization/SecureJwtSerializer.java
@@ -0,0 +1,43 @@
+package org.rootservices.jwt.jws.serialization;
+
+
+import org.rootservices.jwt.entity.jwt.Claims;
+import org.rootservices.jwt.entity.jwt.JsonWebToken;
+import org.rootservices.jwt.factory.SecureJwtFactory;
+import org.rootservices.jwt.serialization.JwtSerde;
+import org.rootservices.jwt.serialization.exception.JwtToJsonException;
+
+import java.io.ByteArrayOutputStream;
+
+
+public class SecureJwtSerializer {
+ private SecureJwtFactory secureJwtFactory;
+ private JwtSerde jwtSerde;
+
+ public SecureJwtSerializer(SecureJwtFactory secureJwtFactory, JwtSerde jwtSerde) {
+ this.secureJwtFactory = secureJwtFactory;
+ this.jwtSerde = jwtSerde;
+ }
+
+ public String compactJwtToString(Claims claims) throws JwtToJsonException {
+ return compactJwt(claims).toString();
+ }
+
+ public ByteArrayOutputStream compactJwt(Claims claims) throws JwtToJsonException {
+ JsonWebToken jsonWebToken;
+ try {
+ jsonWebToken = secureJwtFactory.makeJwt(claims);
+ } catch (JwtToJsonException e) {
+ throw e;
+ }
+
+ ByteArrayOutputStream compactJwt;
+ try {
+ compactJwt = jwtSerde.compactJwt(jsonWebToken);
+ } catch (JwtToJsonException e) {
+ throw e;
+ }
+
+ return compactJwt;
+ }
+}
diff --git a/src/main/java/org/rootservices/jwt/jws/signer/MacSigner.java b/src/main/java/org/rootservices/jwt/jws/signer/MacSigner.java
new file mode 100644
index 0000000..b044263
--- /dev/null
+++ b/src/main/java/org/rootservices/jwt/jws/signer/MacSigner.java
@@ -0,0 +1,31 @@
+package org.rootservices.jwt.jws.signer;
+
+
+import org.rootservices.jwt.serialization.JwtSerde;
+
+import javax.crypto.Mac;
+import java.util.Base64.Encoder;
+
+
+/**
+ * Created by tommackenzie on 8/19/15.
+ *
+ */
+public class MacSigner extends Signer {
+ private Mac mac;
+
+ public MacSigner(JwtSerde jwtSerde, Mac mac, Encoder encoder) {
+ super(jwtSerde, encoder);
+ this.mac = mac;
+ }
+
+ @Override
+ public byte[] run(byte[] input) {
+ return sign(input);
+ }
+
+ private byte[] sign(byte[] input) {
+ byte[] signature = mac.doFinal(input);
+ return encode(signature);
+ }
+}
diff --git a/src/main/java/org/rootservices/jwt/signature/signer/RSASigner.java b/src/main/java/org/rootservices/jwt/jws/signer/RSASigner.java
similarity index 62%
rename from src/main/java/org/rootservices/jwt/signature/signer/RSASigner.java
rename to src/main/java/org/rootservices/jwt/jws/signer/RSASigner.java
index e57082a..8378d83 100644
--- a/src/main/java/org/rootservices/jwt/signature/signer/RSASigner.java
+++ b/src/main/java/org/rootservices/jwt/jws/signer/RSASigner.java
@@ -1,25 +1,22 @@
-package org.rootservices.jwt.signature.signer;
+package org.rootservices.jwt.jws.signer;
-import org.rootservices.jwt.serializer.JWTSerializer;
-import org.rootservices.jwt.serializer.Serializer;
+import org.rootservices.jwt.serialization.JwtSerde;
import java.security.Signature;
import java.security.SignatureException;
import java.util.Base64.Encoder;
-/**
- * Created by tommackenzie on 11/3/15.
- */
+
public class RSASigner extends Signer {
private Signature signature;
- public RSASigner(Signature signature, JWTSerializer jwtSerializer, Encoder encoder) {
- super(jwtSerializer, encoder);
+ public RSASigner(Signature signature, JwtSerde jwtSerde, Encoder encoder) {
+ super(jwtSerde, encoder);
this.signature = signature;
}
@Override
- public String run(byte[] input) {
+ public byte[] run(byte[] input) {
try {
signature.update(input);
} catch (SignatureException e) {
diff --git a/src/main/java/org/rootservices/jwt/signature/signer/SignAlgorithm.java b/src/main/java/org/rootservices/jwt/jws/signer/SignAlgorithm.java
similarity index 94%
rename from src/main/java/org/rootservices/jwt/signature/signer/SignAlgorithm.java
rename to src/main/java/org/rootservices/jwt/jws/signer/SignAlgorithm.java
index 1da4d3a..66c390e 100644
--- a/src/main/java/org/rootservices/jwt/signature/signer/SignAlgorithm.java
+++ b/src/main/java/org/rootservices/jwt/jws/signer/SignAlgorithm.java
@@ -1,4 +1,4 @@
-package org.rootservices.jwt.signature.signer;
+package org.rootservices.jwt.jws.signer;
import org.rootservices.jwt.entity.jwt.header.Algorithm;
diff --git a/src/main/java/org/rootservices/jwt/jws/signer/Signer.java b/src/main/java/org/rootservices/jwt/jws/signer/Signer.java
new file mode 100644
index 0000000..ae2dcaf
--- /dev/null
+++ b/src/main/java/org/rootservices/jwt/jws/signer/Signer.java
@@ -0,0 +1,32 @@
+package org.rootservices.jwt.jws.signer;
+
+import org.rootservices.jwt.entity.jwt.JsonWebToken;
+import org.rootservices.jwt.serialization.JwtSerde;
+import org.rootservices.jwt.serialization.exception.JwtToJsonException;
+
+import java.nio.charset.Charset;
+import java.util.Base64.Encoder;
+
+/**
+ * Created by tommackenzie on 8/19/15.
+ */
+public abstract class Signer {
+ private JwtSerde jwtSerde;
+ private Encoder encoder;
+
+ public Signer(JwtSerde jwtSerde, Encoder encoder) {
+ this.jwtSerde = jwtSerde;
+ this.encoder = encoder;
+ }
+
+ public byte[] run(JsonWebToken jwt) throws JwtToJsonException {
+ byte[] signInput = jwtSerde.makeSignInput(jwt.getHeader(), jwt.getClaims());
+ return run(signInput);
+ }
+
+ protected byte[] encode(byte[] input) {
+ return encoder.encode(input);
+ }
+
+ public abstract byte[] run(byte[] input);
+}
diff --git a/src/main/java/org/rootservices/jwt/signature/signer/factory/SignerFactory.java b/src/main/java/org/rootservices/jwt/jws/signer/factory/SignerFactory.java
similarity index 64%
rename from src/main/java/org/rootservices/jwt/signature/signer/factory/SignerFactory.java
rename to src/main/java/org/rootservices/jwt/jws/signer/factory/SignerFactory.java
index 99ff6eb..d602ae7 100644
--- a/src/main/java/org/rootservices/jwt/signature/signer/factory/SignerFactory.java
+++ b/src/main/java/org/rootservices/jwt/jws/signer/factory/SignerFactory.java
@@ -1,22 +1,22 @@
-package org.rootservices.jwt.signature.signer.factory;
+package org.rootservices.jwt.jws.signer.factory;
import org.rootservices.jwt.entity.jwk.Key;
import org.rootservices.jwt.entity.jwk.KeyType;
import org.rootservices.jwt.entity.jwk.RSAKeyPair;
import org.rootservices.jwt.entity.jwk.SymmetricKey;
import org.rootservices.jwt.entity.jwt.header.Algorithm;
-import org.rootservices.jwt.serializer.JWTSerializer;
-import org.rootservices.jwt.signature.signer.MacSigner;
-import org.rootservices.jwt.signature.signer.RSASigner;
-import org.rootservices.jwt.signature.signer.SignAlgorithm;
-import org.rootservices.jwt.signature.signer.Signer;
-import org.rootservices.jwt.signature.signer.factory.exception.InvalidAlgorithmException;
-import org.rootservices.jwt.signature.signer.factory.exception.InvalidJsonWebKeyException;
-import org.rootservices.jwt.signature.signer.factory.hmac.MacFactory;
-import org.rootservices.jwt.signature.signer.factory.hmac.exception.SecurityKeyException;
-import org.rootservices.jwt.signature.signer.factory.rsa.PrivateKeySignatureFactory;
-import org.rootservices.jwt.signature.signer.factory.rsa.exception.PrivateKeyException;
-import org.rootservices.jwt.signature.signer.factory.rsa.exception.RSAPrivateKeyException;
+import org.rootservices.jwt.serialization.JwtSerde;
+import org.rootservices.jwt.jws.signer.MacSigner;
+import org.rootservices.jwt.jws.signer.RSASigner;
+import org.rootservices.jwt.jws.signer.SignAlgorithm;
+import org.rootservices.jwt.jws.signer.Signer;
+import org.rootservices.jwt.jws.signer.factory.exception.InvalidAlgorithmException;
+import org.rootservices.jwt.jws.signer.factory.exception.InvalidJsonWebKeyException;
+import org.rootservices.jwt.jws.signer.factory.hmac.MacFactory;
+import org.rootservices.jwt.jws.signer.factory.hmac.exception.SecurityKeyException;
+import org.rootservices.jwt.jws.signer.factory.rsa.PrivateKeySignatureFactory;
+import org.rootservices.jwt.jws.signer.factory.rsa.exception.PrivateKeyException;
+import org.rootservices.jwt.jws.signer.factory.rsa.exception.RSAPrivateKeyException;
import javax.crypto.Mac;
@@ -32,12 +32,12 @@ public class SignerFactory {
private MacFactory macFactory;
private PrivateKeySignatureFactory privateKeySignatureFactory;
private Base64.Encoder encoder;
- private JWTSerializer jwtSerializer;
+ private JwtSerde jwtSerde;
- public SignerFactory(MacFactory macFactory, PrivateKeySignatureFactory privateKeySignatureFactory, JWTSerializer jwtSerializer, Base64.Encoder encoder){
+ public SignerFactory(MacFactory macFactory, PrivateKeySignatureFactory privateKeySignatureFactory, JwtSerde jwtSerde, Base64.Encoder encoder){
this.macFactory = macFactory;
this.privateKeySignatureFactory = privateKeySignatureFactory;
- this.jwtSerializer = jwtSerializer;
+ this.jwtSerde = jwtSerde;
this.encoder = encoder;
}
@@ -64,11 +64,11 @@ public Signer makeMacSigner(Algorithm alg, Key key) throws InvalidAlgorithmExcep
throw e;
}
- return new MacSigner(jwtSerializer, mac, encoder);
+ return new MacSigner(jwtSerde, mac, encoder);
}
private Signer makeRSASigner(Algorithm alg, RSAKeyPair keyPair) throws InvalidAlgorithmException, InvalidJsonWebKeyException {
- Signature signature = null;
+ Signature signature;
SignAlgorithm signAlgorithm = SignAlgorithm.valueOf(alg.getValue());
@@ -81,6 +81,6 @@ private Signer makeRSASigner(Algorithm alg, RSAKeyPair keyPair) throws InvalidAl
} catch (InvalidAlgorithmException e) {
throw e;
}
- return new RSASigner(signature, jwtSerializer, encoder);
+ return new RSASigner(signature, jwtSerde, encoder);
}
}
diff --git a/src/main/java/org/rootservices/jwt/signature/signer/factory/exception/InvalidAlgorithmException.java b/src/main/java/org/rootservices/jwt/jws/signer/factory/exception/InvalidAlgorithmException.java
similarity index 77%
rename from src/main/java/org/rootservices/jwt/signature/signer/factory/exception/InvalidAlgorithmException.java
rename to src/main/java/org/rootservices/jwt/jws/signer/factory/exception/InvalidAlgorithmException.java
index fd65881..c5aac3a 100644
--- a/src/main/java/org/rootservices/jwt/signature/signer/factory/exception/InvalidAlgorithmException.java
+++ b/src/main/java/org/rootservices/jwt/jws/signer/factory/exception/InvalidAlgorithmException.java
@@ -1,4 +1,4 @@
-package org.rootservices.jwt.signature.signer.factory.exception;
+package org.rootservices.jwt.jws.signer.factory.exception;
/**
* Created by tommackenzie on 12/12/15.
diff --git a/src/main/java/org/rootservices/jwt/signature/signer/factory/exception/InvalidJsonWebKeyException.java b/src/main/java/org/rootservices/jwt/jws/signer/factory/exception/InvalidJsonWebKeyException.java
similarity index 77%
rename from src/main/java/org/rootservices/jwt/signature/signer/factory/exception/InvalidJsonWebKeyException.java
rename to src/main/java/org/rootservices/jwt/jws/signer/factory/exception/InvalidJsonWebKeyException.java
index a844ac9..0b1110b 100644
--- a/src/main/java/org/rootservices/jwt/signature/signer/factory/exception/InvalidJsonWebKeyException.java
+++ b/src/main/java/org/rootservices/jwt/jws/signer/factory/exception/InvalidJsonWebKeyException.java
@@ -1,4 +1,4 @@
-package org.rootservices.jwt.signature.signer.factory.exception;
+package org.rootservices.jwt.jws.signer.factory.exception;
/**
* Created by tommackenzie on 12/13/15.
diff --git a/src/main/java/org/rootservices/jwt/signature/signer/factory/exception/SignerException.java b/src/main/java/org/rootservices/jwt/jws/signer/factory/exception/SignerException.java
similarity index 75%
rename from src/main/java/org/rootservices/jwt/signature/signer/factory/exception/SignerException.java
rename to src/main/java/org/rootservices/jwt/jws/signer/factory/exception/SignerException.java
index 19276cc..fe03649 100644
--- a/src/main/java/org/rootservices/jwt/signature/signer/factory/exception/SignerException.java
+++ b/src/main/java/org/rootservices/jwt/jws/signer/factory/exception/SignerException.java
@@ -1,4 +1,4 @@
-package org.rootservices.jwt.signature.signer.factory.exception;
+package org.rootservices.jwt.jws.signer.factory.exception;
/**
* Created by tommackenzie on 12/6/15.
diff --git a/src/main/java/org/rootservices/jwt/signature/signer/factory/hmac/MacFactory.java b/src/main/java/org/rootservices/jwt/jws/signer/factory/hmac/MacFactory.java
similarity index 80%
rename from src/main/java/org/rootservices/jwt/signature/signer/factory/hmac/MacFactory.java
rename to src/main/java/org/rootservices/jwt/jws/signer/factory/hmac/MacFactory.java
index 7e5a71c..97bee99 100644
--- a/src/main/java/org/rootservices/jwt/signature/signer/factory/hmac/MacFactory.java
+++ b/src/main/java/org/rootservices/jwt/jws/signer/factory/hmac/MacFactory.java
@@ -1,9 +1,9 @@
-package org.rootservices.jwt.signature.signer.factory.hmac;
+package org.rootservices.jwt.jws.signer.factory.hmac;
import org.rootservices.jwt.entity.jwk.SymmetricKey;
-import org.rootservices.jwt.signature.signer.SignAlgorithm;
-import org.rootservices.jwt.signature.signer.factory.exception.InvalidAlgorithmException;
-import org.rootservices.jwt.signature.signer.factory.hmac.exception.SecurityKeyException;
+import org.rootservices.jwt.jws.signer.SignAlgorithm;
+import org.rootservices.jwt.jws.signer.factory.exception.InvalidAlgorithmException;
+import org.rootservices.jwt.jws.signer.factory.hmac.exception.SecurityKeyException;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
diff --git a/src/main/java/org/rootservices/jwt/signature/signer/factory/hmac/exception/SecurityKeyException.java b/src/main/java/org/rootservices/jwt/jws/signer/factory/hmac/exception/SecurityKeyException.java
similarity index 80%
rename from src/main/java/org/rootservices/jwt/signature/signer/factory/hmac/exception/SecurityKeyException.java
rename to src/main/java/org/rootservices/jwt/jws/signer/factory/hmac/exception/SecurityKeyException.java
index 70df18d..734aee0 100644
--- a/src/main/java/org/rootservices/jwt/signature/signer/factory/hmac/exception/SecurityKeyException.java
+++ b/src/main/java/org/rootservices/jwt/jws/signer/factory/hmac/exception/SecurityKeyException.java
@@ -1,4 +1,4 @@
-package org.rootservices.jwt.signature.signer.factory.hmac.exception;
+package org.rootservices.jwt.jws.signer.factory.hmac.exception;
/**
* Created by tommackenzie on 12/13/15.
diff --git a/src/main/java/org/rootservices/jwt/signature/signer/factory/rsa/PrivateKeySignatureFactory.java b/src/main/java/org/rootservices/jwt/jws/signer/factory/rsa/PrivateKeySignatureFactory.java
similarity index 82%
rename from src/main/java/org/rootservices/jwt/signature/signer/factory/rsa/PrivateKeySignatureFactory.java
rename to src/main/java/org/rootservices/jwt/jws/signer/factory/rsa/PrivateKeySignatureFactory.java
index f800c27..aa17c60 100644
--- a/src/main/java/org/rootservices/jwt/signature/signer/factory/rsa/PrivateKeySignatureFactory.java
+++ b/src/main/java/org/rootservices/jwt/jws/signer/factory/rsa/PrivateKeySignatureFactory.java
@@ -1,10 +1,10 @@
-package org.rootservices.jwt.signature.signer.factory.rsa;
+package org.rootservices.jwt.jws.signer.factory.rsa;
import org.rootservices.jwt.entity.jwk.RSAKeyPair;
-import org.rootservices.jwt.signature.signer.SignAlgorithm;
-import org.rootservices.jwt.signature.signer.factory.exception.InvalidAlgorithmException;
-import org.rootservices.jwt.signature.signer.factory.rsa.exception.PrivateKeyException;
-import org.rootservices.jwt.signature.signer.factory.rsa.exception.RSAPrivateKeyException;
+import org.rootservices.jwt.jws.signer.SignAlgorithm;
+import org.rootservices.jwt.jws.signer.factory.exception.InvalidAlgorithmException;
+import org.rootservices.jwt.jws.signer.factory.rsa.exception.PrivateKeyException;
+import org.rootservices.jwt.jws.signer.factory.rsa.exception.RSAPrivateKeyException;
import java.security.*;
import java.security.interfaces.RSAPrivateCrtKey;
@@ -28,8 +28,9 @@ public PrivateKeySignatureFactory(KeyFactory RSAKeyFactory) {
* Returns a, RSAPrivateCrtKey, which is built from the input parameter, jwk.
* A RSAPrivateCrtKey is needed per, https://tools.ietf.org/html/rfc7517#section-9.3
*
- * @param jwk
- * @return
+ * @param jwk a RSAKeyPair
+ * @return an instance of RSAPrivateCrtKey
+ * @throws PrivateKeyException if jwk is invalid.
*/
public RSAPrivateCrtKey makePrivateKey(RSAKeyPair jwk) throws PrivateKeyException {
RSAPrivateKeySpec keySpec;
diff --git a/src/main/java/org/rootservices/jwt/signature/signer/factory/rsa/PublicKeySignatureFactory.java b/src/main/java/org/rootservices/jwt/jws/signer/factory/rsa/PublicKeySignatureFactory.java
similarity index 80%
rename from src/main/java/org/rootservices/jwt/signature/signer/factory/rsa/PublicKeySignatureFactory.java
rename to src/main/java/org/rootservices/jwt/jws/signer/factory/rsa/PublicKeySignatureFactory.java
index cb4a89d..69ee629 100644
--- a/src/main/java/org/rootservices/jwt/signature/signer/factory/rsa/PublicKeySignatureFactory.java
+++ b/src/main/java/org/rootservices/jwt/jws/signer/factory/rsa/PublicKeySignatureFactory.java
@@ -1,11 +1,10 @@
-package org.rootservices.jwt.signature.signer.factory.rsa;
+package org.rootservices.jwt.jws.signer.factory.rsa;
import org.rootservices.jwt.entity.jwk.RSAPublicKey;
-import org.rootservices.jwt.entity.jwt.header.Algorithm;
-import org.rootservices.jwt.signature.signer.SignAlgorithm;
-import org.rootservices.jwt.signature.signer.factory.exception.InvalidAlgorithmException;
-import org.rootservices.jwt.signature.signer.factory.rsa.exception.PublicKeyException;
-import org.rootservices.jwt.signature.signer.factory.rsa.exception.RSAPublicKeyException;
+import org.rootservices.jwt.jws.signer.SignAlgorithm;
+import org.rootservices.jwt.jws.signer.factory.exception.InvalidAlgorithmException;
+import org.rootservices.jwt.jws.signer.factory.rsa.exception.PublicKeyException;
+import org.rootservices.jwt.jws.signer.factory.rsa.exception.RSAPublicKeyException;
import java.security.*;
import java.security.spec.InvalidKeySpecException;
@@ -39,7 +38,7 @@ public java.security.interfaces.RSAPublicKey makePublicKey(RSAPublicKey jwk) thr
public Signature makeSignature(SignAlgorithm alg, RSAPublicKey jwk) throws PublicKeyException, InvalidAlgorithmException, RSAPublicKeyException {
java.security.interfaces.RSAPublicKey securityPublicKey = makePublicKey(jwk);
- Signature signature = null;
+ Signature signature;
try {
signature = Signature.getInstance(alg.getJdkAlgorithm());
} catch (NoSuchAlgorithmException e) {
diff --git a/src/main/java/org/rootservices/jwt/signature/signer/factory/rsa/exception/PrivateKeyException.java b/src/main/java/org/rootservices/jwt/jws/signer/factory/rsa/exception/PrivateKeyException.java
similarity index 74%
rename from src/main/java/org/rootservices/jwt/signature/signer/factory/rsa/exception/PrivateKeyException.java
rename to src/main/java/org/rootservices/jwt/jws/signer/factory/rsa/exception/PrivateKeyException.java
index 6cb124e..2e87e07 100644
--- a/src/main/java/org/rootservices/jwt/signature/signer/factory/rsa/exception/PrivateKeyException.java
+++ b/src/main/java/org/rootservices/jwt/jws/signer/factory/rsa/exception/PrivateKeyException.java
@@ -1,4 +1,4 @@
-package org.rootservices.jwt.signature.signer.factory.rsa.exception;
+package org.rootservices.jwt.jws.signer.factory.rsa.exception;
/**
* Created by tommackenzie on 12/7/15.
diff --git a/src/main/java/org/rootservices/jwt/signature/signer/factory/rsa/exception/PublicKeyException.java b/src/main/java/org/rootservices/jwt/jws/signer/factory/rsa/exception/PublicKeyException.java
similarity index 74%
rename from src/main/java/org/rootservices/jwt/signature/signer/factory/rsa/exception/PublicKeyException.java
rename to src/main/java/org/rootservices/jwt/jws/signer/factory/rsa/exception/PublicKeyException.java
index 40782ec..2e00433 100644
--- a/src/main/java/org/rootservices/jwt/signature/signer/factory/rsa/exception/PublicKeyException.java
+++ b/src/main/java/org/rootservices/jwt/jws/signer/factory/rsa/exception/PublicKeyException.java
@@ -1,4 +1,4 @@
-package org.rootservices.jwt.signature.signer.factory.rsa.exception;
+package org.rootservices.jwt.jws.signer.factory.rsa.exception;
/**
* Created by tommackenzie on 12/7/15.
diff --git a/src/main/java/org/rootservices/jwt/signature/signer/factory/rsa/exception/RSAPrivateKeyException.java b/src/main/java/org/rootservices/jwt/jws/signer/factory/rsa/exception/RSAPrivateKeyException.java
similarity index 75%
rename from src/main/java/org/rootservices/jwt/signature/signer/factory/rsa/exception/RSAPrivateKeyException.java
rename to src/main/java/org/rootservices/jwt/jws/signer/factory/rsa/exception/RSAPrivateKeyException.java
index 3e0fa7d..45c8048 100644
--- a/src/main/java/org/rootservices/jwt/signature/signer/factory/rsa/exception/RSAPrivateKeyException.java
+++ b/src/main/java/org/rootservices/jwt/jws/signer/factory/rsa/exception/RSAPrivateKeyException.java
@@ -1,4 +1,4 @@
-package org.rootservices.jwt.signature.signer.factory.rsa.exception;
+package org.rootservices.jwt.jws.signer.factory.rsa.exception;
/**
* Created by tommackenzie on 12/13/15.
diff --git a/src/main/java/org/rootservices/jwt/signature/signer/factory/rsa/exception/RSAPublicKeyException.java b/src/main/java/org/rootservices/jwt/jws/signer/factory/rsa/exception/RSAPublicKeyException.java
similarity index 75%
rename from src/main/java/org/rootservices/jwt/signature/signer/factory/rsa/exception/RSAPublicKeyException.java
rename to src/main/java/org/rootservices/jwt/jws/signer/factory/rsa/exception/RSAPublicKeyException.java
index e6d289e..6c7bc00 100644
--- a/src/main/java/org/rootservices/jwt/signature/signer/factory/rsa/exception/RSAPublicKeyException.java
+++ b/src/main/java/org/rootservices/jwt/jws/signer/factory/rsa/exception/RSAPublicKeyException.java
@@ -1,4 +1,4 @@
-package org.rootservices.jwt.signature.signer.factory.rsa.exception;
+package org.rootservices.jwt.jws.signer.factory.rsa.exception;
/**
* Created by tommackenzie on 12/13/15.
diff --git a/src/main/java/org/rootservices/jwt/signature/signer/factory/rsa/exception/SignatureException.java b/src/main/java/org/rootservices/jwt/jws/signer/factory/rsa/exception/SignatureException.java
similarity index 74%
rename from src/main/java/org/rootservices/jwt/signature/signer/factory/rsa/exception/SignatureException.java
rename to src/main/java/org/rootservices/jwt/jws/signer/factory/rsa/exception/SignatureException.java
index cf2b8e2..5a795fd 100644
--- a/src/main/java/org/rootservices/jwt/signature/signer/factory/rsa/exception/SignatureException.java
+++ b/src/main/java/org/rootservices/jwt/jws/signer/factory/rsa/exception/SignatureException.java
@@ -1,4 +1,4 @@
-package org.rootservices.jwt.signature.signer.factory.rsa.exception;
+package org.rootservices.jwt.jws.signer.factory.rsa.exception;
/**
* Created by tommackenzie on 12/6/15.
diff --git a/src/main/java/org/rootservices/jwt/signature/verifier/VerifyMacSignature.java b/src/main/java/org/rootservices/jwt/jws/verifier/VerifyMacSignature.java
similarity index 65%
rename from src/main/java/org/rootservices/jwt/signature/verifier/VerifyMacSignature.java
rename to src/main/java/org/rootservices/jwt/jws/verifier/VerifyMacSignature.java
index 12ac378..5e0edb4 100644
--- a/src/main/java/org/rootservices/jwt/signature/verifier/VerifyMacSignature.java
+++ b/src/main/java/org/rootservices/jwt/jws/verifier/VerifyMacSignature.java
@@ -1,13 +1,12 @@
-package org.rootservices.jwt.signature.verifier;
+package org.rootservices.jwt.jws.verifier;
import org.rootservices.jwt.entity.jwt.JsonWebToken;
-import org.rootservices.jwt.signature.signer.Signer;
+import org.rootservices.jwt.jws.signer.Signer;
+
+import java.util.Arrays;
+
-/**
- * Created by tommackenzie on 8/26/15.
- *
- */
public class VerifyMacSignature extends VerifySignature {
private Signer macSigner;
@@ -18,14 +17,14 @@ public VerifyMacSignature(Signer macSigner) {
@Override
public boolean run(JsonWebToken token) {
- String generatedSignature = "";
- String actualSignature = "";
+ byte[] generatedSignature = null;
+ byte[] actualSignature = null;
if ( token.getSignature().isPresent()) {
byte[] input = createSignInput(token.getJwt().get());
generatedSignature = macSigner.run(input);
actualSignature = token.getSignature().get();
}
- return actualSignature.equals(generatedSignature);
+ return Arrays.equals(actualSignature, generatedSignature);
}
}
diff --git a/src/main/java/org/rootservices/jwt/signature/verifier/VerifyRsaSignature.java b/src/main/java/org/rootservices/jwt/jws/verifier/VerifyRsaSignature.java
similarity index 95%
rename from src/main/java/org/rootservices/jwt/signature/verifier/VerifyRsaSignature.java
rename to src/main/java/org/rootservices/jwt/jws/verifier/VerifyRsaSignature.java
index 4314292..b023985 100644
--- a/src/main/java/org/rootservices/jwt/signature/verifier/VerifyRsaSignature.java
+++ b/src/main/java/org/rootservices/jwt/jws/verifier/VerifyRsaSignature.java
@@ -1,4 +1,4 @@
-package org.rootservices.jwt.signature.verifier;
+package org.rootservices.jwt.jws.verifier;
import org.rootservices.jwt.entity.jwt.JsonWebToken;
diff --git a/src/main/java/org/rootservices/jwt/signature/verifier/VerifySignature.java b/src/main/java/org/rootservices/jwt/jws/verifier/VerifySignature.java
similarity index 89%
rename from src/main/java/org/rootservices/jwt/signature/verifier/VerifySignature.java
rename to src/main/java/org/rootservices/jwt/jws/verifier/VerifySignature.java
index 9c6eb6e..8afc717 100644
--- a/src/main/java/org/rootservices/jwt/signature/verifier/VerifySignature.java
+++ b/src/main/java/org/rootservices/jwt/jws/verifier/VerifySignature.java
@@ -1,4 +1,4 @@
-package org.rootservices.jwt.signature.verifier;
+package org.rootservices.jwt.jws.verifier;
import org.rootservices.jwt.entity.jwt.JsonWebToken;
diff --git a/src/main/java/org/rootservices/jwt/signature/verifier/factory/VerifySignatureFactory.java b/src/main/java/org/rootservices/jwt/jws/verifier/factory/VerifySignatureFactory.java
similarity index 51%
rename from src/main/java/org/rootservices/jwt/signature/verifier/factory/VerifySignatureFactory.java
rename to src/main/java/org/rootservices/jwt/jws/verifier/factory/VerifySignatureFactory.java
index 993c600..65bf114 100644
--- a/src/main/java/org/rootservices/jwt/signature/verifier/factory/VerifySignatureFactory.java
+++ b/src/main/java/org/rootservices/jwt/jws/verifier/factory/VerifySignatureFactory.java
@@ -1,20 +1,21 @@
-package org.rootservices.jwt.signature.verifier.factory;
+package org.rootservices.jwt.jws.verifier.factory;
import org.rootservices.jwt.entity.jwk.Key;
import org.rootservices.jwt.entity.jwk.KeyType;
import org.rootservices.jwt.entity.jwk.RSAPublicKey;
import org.rootservices.jwt.entity.jwt.header.Algorithm;
-import org.rootservices.jwt.signature.signer.SignAlgorithm;
-import org.rootservices.jwt.signature.signer.Signer;
-import org.rootservices.jwt.signature.signer.factory.SignerFactory;
-import org.rootservices.jwt.signature.signer.factory.exception.InvalidAlgorithmException;
-import org.rootservices.jwt.signature.signer.factory.exception.InvalidJsonWebKeyException;
-import org.rootservices.jwt.signature.signer.factory.rsa.PublicKeySignatureFactory;
-import org.rootservices.jwt.signature.signer.factory.rsa.exception.PublicKeyException;
-import org.rootservices.jwt.signature.signer.factory.rsa.exception.RSAPublicKeyException;
-import org.rootservices.jwt.signature.verifier.VerifyMacSignature;
-import org.rootservices.jwt.signature.verifier.VerifyRsaSignature;
-import org.rootservices.jwt.signature.verifier.VerifySignature;
+import org.rootservices.jwt.exception.SignatureException;
+import org.rootservices.jwt.jws.signer.SignAlgorithm;
+import org.rootservices.jwt.jws.signer.Signer;
+import org.rootservices.jwt.jws.signer.factory.SignerFactory;
+import org.rootservices.jwt.jws.signer.factory.exception.InvalidAlgorithmException;
+import org.rootservices.jwt.jws.signer.factory.exception.InvalidJsonWebKeyException;
+import org.rootservices.jwt.jws.signer.factory.rsa.PublicKeySignatureFactory;
+import org.rootservices.jwt.jws.signer.factory.rsa.exception.PublicKeyException;
+import org.rootservices.jwt.jws.signer.factory.rsa.exception.RSAPublicKeyException;
+import org.rootservices.jwt.jws.verifier.VerifyMacSignature;
+import org.rootservices.jwt.jws.verifier.VerifyRsaSignature;
+import org.rootservices.jwt.jws.verifier.VerifySignature;
import java.security.Signature;
import java.util.Base64.Decoder;
@@ -23,7 +24,8 @@
* Created by tommackenzie on 11/14/15.
*/
public class VerifySignatureFactory {
-
+ public static final String ALG_WAS_INVALID = "Could not construct Signer. Algorithm was invalid.";
+ public static final String KEY_WAS_INVALID = "Could not construct Signer. Key was invalid.";
private SignerFactory signerFactory;
private PublicKeySignatureFactory publicKeySignatureFactory;
private Decoder decoder;
@@ -34,7 +36,7 @@ public VerifySignatureFactory(SignerFactory signerFactory, PublicKeySignatureFac
this.decoder = decoder;
}
- public VerifySignature makeVerifySignature(Algorithm algorithm, Key key) throws InvalidAlgorithmException, InvalidJsonWebKeyException {
+ public VerifySignature makeVerifySignature(Algorithm algorithm, Key key) throws SignatureException {
VerifySignature verifySignature = null;
if (key.getKeyType() == KeyType.OCT) {
@@ -45,12 +47,20 @@ public VerifySignature makeVerifySignature(Algorithm algorithm, Key key) throws
return verifySignature;
}
- private VerifySignature makeVerifyMacSignature(Algorithm algorithm, Key key) throws InvalidAlgorithmException, InvalidJsonWebKeyException {
- Signer macSigner = signerFactory.makeMacSigner(algorithm, key);
+ private VerifySignature makeVerifyMacSignature(Algorithm algorithm, Key key) throws SignatureException {
+ Signer macSigner;
+ try {
+ macSigner = signerFactory.makeMacSigner(algorithm, key);
+ } catch (InvalidAlgorithmException e) {
+ throw new SignatureException(ALG_WAS_INVALID, e);
+ } catch (InvalidJsonWebKeyException e) {
+ throw new SignatureException(KEY_WAS_INVALID, e);
+ }
+
return new VerifyMacSignature(macSigner);
}
- private VerifySignature makeVerifyRsaSignature(Algorithm algorithm, RSAPublicKey key) throws InvalidJsonWebKeyException, InvalidAlgorithmException {
+ private VerifySignature makeVerifyRsaSignature(Algorithm algorithm, RSAPublicKey key) throws SignatureException {
Signature signature;
SignAlgorithm signAlgorithm = SignAlgorithm.valueOf(algorithm.getValue());
@@ -58,11 +68,11 @@ private VerifySignature makeVerifyRsaSignature(Algorithm algorithm, RSAPublicKey
try {
signature = publicKeySignatureFactory.makeSignature(signAlgorithm, key);
} catch (PublicKeyException e) {
- throw new InvalidJsonWebKeyException("", e);
+ throw new SignatureException(KEY_WAS_INVALID, e);
} catch (RSAPublicKeyException e) {
- throw new InvalidJsonWebKeyException("", e);
+ throw new SignatureException(KEY_WAS_INVALID, e);
} catch (InvalidAlgorithmException e) {
- throw e;
+ throw new SignatureException(ALG_WAS_INVALID, e);
}
return new VerifyRsaSignature(signature, decoder);
diff --git a/src/main/java/org/rootservices/jwt/serialization/HeaderDeserializer.java b/src/main/java/org/rootservices/jwt/serialization/HeaderDeserializer.java
new file mode 100644
index 0000000..c42f223
--- /dev/null
+++ b/src/main/java/org/rootservices/jwt/serialization/HeaderDeserializer.java
@@ -0,0 +1,41 @@
+package org.rootservices.jwt.serialization;
+
+import org.rootservices.jwt.entity.jwt.header.Header;
+import org.rootservices.jwt.exception.InvalidJWT;
+import org.rootservices.jwt.serialization.exception.JsonException;
+import org.rootservices.jwt.serialization.exception.JsonToJwtException;
+
+import java.util.Base64;
+
+public class HeaderDeserializer {
+ public static final String JWT_SPLITTER = "\\.";
+ public static final String INVALID_HEADER = "JOSE Header is invalid";
+ public static final String JWT_IS_NOT_SPLITTABLE = "JWT is not splittable by '.'";
+ private Base64.Decoder decoder;
+ private Serdes serdes;
+
+ public HeaderDeserializer(Base64.Decoder decoder, Serdes serdes) {
+ this.decoder = decoder;
+ this.serdes = serdes;
+ }
+
+ public Header toHeader(String encodedJwt) throws JsonToJwtException, InvalidJWT {
+ String[] jwtParts = encodedJwt.split(JWT_SPLITTER);
+
+ if (jwtParts.length == 0) {
+ throw new InvalidJWT(JWT_IS_NOT_SPLITTABLE);
+ }
+
+ byte[] headerJson = decoder.decode(jwtParts[0]);
+
+ Header header;
+ try {
+ header = (Header) serdes.jsonBytesToObject(headerJson, Header.class);
+ } catch (JsonException e) {
+ throw new JsonToJwtException(INVALID_HEADER, e);
+ }
+
+ return header;
+ }
+
+}
diff --git a/src/main/java/org/rootservices/jwt/serialization/JwtSerde.java b/src/main/java/org/rootservices/jwt/serialization/JwtSerde.java
new file mode 100644
index 0000000..9e1ce9c
--- /dev/null
+++ b/src/main/java/org/rootservices/jwt/serialization/JwtSerde.java
@@ -0,0 +1,180 @@
+package org.rootservices.jwt.serialization;
+
+import org.rootservices.jwt.entity.jwt.Claims;
+import org.rootservices.jwt.entity.jwt.JsonWebToken;
+import org.rootservices.jwt.entity.jwt.header.Header;
+import org.rootservices.jwt.exception.InvalidJWT;
+import org.rootservices.jwt.serialization.exception.JsonToJwtException;
+import org.rootservices.jwt.serialization.exception.JsonException;
+import org.rootservices.jwt.serialization.exception.JwtToJsonException;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+
+import java.util.ArrayList;
+import java.util.Base64.Encoder;
+import java.util.Base64.Decoder;
+import java.util.List;
+import java.util.Optional;
+
+
+/**
+ * A Serializer and Deserializer that converts:
+ * - a jwt as a string to a instance of a JsonWebToken.
+ * - a JsonWebToken to its string representation.
+ */
+public class JwtSerde {
+ public static final String JWT_SPLITTER = "\\.";
+ public static final String INVALID_JSON = "JWT json is invalid";
+ public static final String COULD_NOT_SERIALIZE = "Could not make sign input";
+ public static final String THIS_IS_A_JWE = "This is a JWE";
+ public static final String TOO_MANY_MEMBERS = "Too many members";
+ public static final String COULD_NOT_COMBINE_JWT_MEMBERS = "Could not combine jwt members";
+ public static final String COULD_NOT_COMBINE_SIGN_INPUTS = "Could not combine sign inputs";
+ public final int JWT_LENGTH = 2;
+ public final int JWS_LENGTH = 3;
+ public final int JWE_LENGTH = 5;
+ private Serdes serdes;
+ private Encoder encoder;
+ private Decoder decoder;
+ private final String DELIMITTER = ".";
+ private final byte[] DELIMITER = ".".getBytes();
+
+ public JwtSerde(Serdes serdes, Encoder encoder, Decoder decoder) {
+ this.serdes = serdes;
+ this.encoder = encoder;
+ this.decoder = decoder;
+ }
+
+ public byte[] makeSignInput(Header header, Claims claims) throws JwtToJsonException {
+
+ List members = membersForSigning(header, claims);
+ byte[] signInput;
+
+ try {
+ signInput = compact(members, true).toByteArray();
+ } catch (IOException e) {
+ throw new JwtToJsonException(COULD_NOT_COMBINE_SIGN_INPUTS, e);
+ }
+
+ return signInput;
+ }
+
+ protected List membersForSigning(Header header, Claims claims) throws JwtToJsonException {
+ List members = new ArrayList<>();
+ byte[] headerJson;
+ byte[] claimsJson;
+
+ try {
+ headerJson = serdes.objectToByte(header);
+ claimsJson = serdes.objectToByte(claims);
+ } catch (JsonException e) {
+ throw new JwtToJsonException(COULD_NOT_SERIALIZE, e);
+ }
+
+ members.add(encoder.encode(headerJson));
+ members.add(encoder.encode(claimsJson));
+ return members;
+ }
+
+ public ByteArrayOutputStream compactJwt(JsonWebToken jwt) throws JwtToJsonException {
+
+ List members = membersForSigning(jwt.getHeader(), jwt.getClaims());
+
+ if (jwt.getSignature().isPresent())
+ members.add(jwt.getSignature().get());
+
+ ByteArrayOutputStream compactJwt;
+ try {
+ compactJwt = compact(members, false);
+ } catch (IOException e) {
+ throw new JwtToJsonException(COULD_NOT_COMBINE_JWT_MEMBERS, e);
+ }
+ return compactJwt;
+ }
+
+ public JsonWebToken stringToJwt(String jwtAsText, Class claimClass) throws JsonToJwtException, InvalidJWT {
+ String[] jwtParts = jwtAsText.split(JWT_SPLITTER);
+ JsonWebToken jwt;
+
+ if (jwtParts.length == JWT_LENGTH) {
+ jwt = jwt(jwtParts, claimClass, jwtAsText);
+ } else if (jwtParts.length == JWS_LENGTH && jwtParts[JWS_LENGTH-1] != null) {
+ jwt = jws(jwtParts, claimClass, jwtAsText);
+ } else if (jwtParts.length == JWE_LENGTH) {
+ throw new InvalidJWT(THIS_IS_A_JWE);
+ } else {
+ throw new InvalidJWT(TOO_MANY_MEMBERS);
+ }
+
+ return jwt;
+ }
+
+ protected JsonWebToken jwt(String[] jwtParts, Class claimClass, String jwtAsText) throws JsonToJwtException {
+ byte[] headerJson = decoder.decode(jwtParts[0]);
+ byte[] claimsJson = decoder.decode(jwtParts[1]);
+
+ Header header;
+ Claims claim;
+ try {
+ header = (Header) serdes.jsonBytesToObject(headerJson, Header.class);
+ claim = (Claims) serdes.jsonBytesToObject(claimsJson, claimClass);
+ } catch (JsonException e) {
+ throw new JsonToJwtException(INVALID_JSON, e);
+ }
+
+ JsonWebToken jwt = new JsonWebToken(header, claim, Optional.of(jwtAsText));
+
+ return jwt;
+ }
+
+ protected JsonWebToken jws(String[] jwsParts, Class claimClass, String jwtAsText) throws JsonToJwtException {
+ JsonWebToken jwt = jwt(jwsParts, claimClass, jwtAsText);
+ jwt.setSignature(Optional.of(jwsParts[JWS_LENGTH-1].getBytes()));
+
+ return jwt;
+ }
+
+ protected ByteArrayOutputStream compact(List members, Boolean forSigning) throws IOException {
+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+
+ for(int i=0; i < members.size(); i++) {
+ if (members.get(i) != null) {
+ try {
+ outputStream.write(members.get(i));
+ } catch (IOException e) {
+ throw e;
+ }
+ }
+ if (shouldAppendDelimiter(i, members.size(), forSigning)) {
+ try {
+ outputStream.write(DELIMITER);
+ } catch (IOException e) {
+ throw e;
+ }
+ }
+ }
+ return outputStream;
+ }
+
+ /**
+ * Deteremines if a "." should be appended to the current index of a compact jwt.
+ *
+ * When its not for signing
+ *
+ * Then a unsecure jwt will have a trailing "."
+ * Then a secure jwt (signed) will not have a trailing "."
+ *
+ * When its for signing
+ * Then a unsecure jwt will not have a trailing "."
+ *
+ * @param i the current index of the jwt
+ * @param numberOfMembers the number of members in the jwt
+ * @param forSigning is it being compacted to be signed.
+ * @return true if a "." should be appended. false if not.
+ */
+ protected Boolean shouldAppendDelimiter(int i, int numberOfMembers, Boolean forSigning) {
+ return (i < numberOfMembers - 1 || (forSigning == false && i == numberOfMembers - 1 && i == 1));
+ }
+
+}
diff --git a/src/main/java/org/rootservices/jwt/serializer/Serializer.java b/src/main/java/org/rootservices/jwt/serialization/Serdes.java
similarity index 53%
rename from src/main/java/org/rootservices/jwt/serializer/Serializer.java
rename to src/main/java/org/rootservices/jwt/serialization/Serdes.java
index 8115cdb..70e4916 100644
--- a/src/main/java/org/rootservices/jwt/serializer/Serializer.java
+++ b/src/main/java/org/rootservices/jwt/serialization/Serdes.java
@@ -1,38 +1,35 @@
-package org.rootservices.jwt.serializer;
+package org.rootservices.jwt.serialization;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
-import org.rootservices.jwt.serializer.exception.JsonException;
+import org.rootservices.jwt.serialization.exception.JsonException;
import java.io.IOException;
/**
- * Created by tommackenzie on 8/12/15.
- *
- * A Generic serializer that converts:
- * - a object to json
+ * A Generic serializer and deserializer that converts:
+ * - an object to json
* - json to a object
*
*/
-public class Serializer {
-
+public class Serdes {
+ public static final String COULD_NOT_CREATE_JSON_FROM = "Could not create json from %s";
private ObjectMapper objectMapper;
- public Serializer(ObjectMapper objectMapper) {
+ public Serdes(ObjectMapper objectMapper) {
this.objectMapper = objectMapper;
}
-
- public String objectToJson(Object object) throws JsonException {
+ public byte[] objectToByte(Object object) throws JsonException {
try {
- return objectMapper.writeValueAsString(object);
+ return objectMapper.writeValueAsBytes(object);
} catch (JsonProcessingException e) {
- throw new JsonException("Could not create json from " + object.toString(), e);
+ throw new JsonException(String.format(COULD_NOT_CREATE_JSON_FROM ,object.toString()), e);
}
}
public Object jsonBytesToObject(byte[] json, Class> c) throws JsonException {
- Object object = null;
+ Object object;
try {
object = objectMapper.readValue(json, c);
} catch (IOException e) {
diff --git a/src/main/java/org/rootservices/jwt/serialization/UnSecureJwtSerializer.java b/src/main/java/org/rootservices/jwt/serialization/UnSecureJwtSerializer.java
new file mode 100644
index 0000000..4d8edf6
--- /dev/null
+++ b/src/main/java/org/rootservices/jwt/serialization/UnSecureJwtSerializer.java
@@ -0,0 +1,37 @@
+package org.rootservices.jwt.serialization;
+
+import org.rootservices.jwt.entity.jwt.Claims;
+import org.rootservices.jwt.entity.jwt.JsonWebToken;
+import org.rootservices.jwt.factory.UnSecureJwtFactory;
+import org.rootservices.jwt.serialization.exception.JwtToJsonException;
+
+import java.io.ByteArrayOutputStream;
+
+
+public class UnSecureJwtSerializer {
+ private UnSecureJwtFactory unSecureJwtFactory;
+ private JwtSerde jwtSerde;
+
+ public UnSecureJwtSerializer(UnSecureJwtFactory unSecureJwtFactory, JwtSerde jwtSerde) {
+ this.unSecureJwtFactory = unSecureJwtFactory;
+ this.jwtSerde = jwtSerde;
+ }
+
+ public String compactJwtToString(Claims claims) {
+ return compactJwt(claims).toString();
+ }
+
+ public ByteArrayOutputStream compactJwt(Claims claims) {
+
+ JsonWebToken jsonWebToken = unSecureJwtFactory.makeJwt(claims);
+
+ ByteArrayOutputStream encodedJwt = null;
+ try {
+ encodedJwt = jwtSerde.compactJwt(jsonWebToken);
+ } catch (JwtToJsonException e) {
+ e.printStackTrace();
+ }
+
+ return encodedJwt;
+ }
+}
diff --git a/src/main/java/org/rootservices/jwt/serialization/exception/DecryptException.java b/src/main/java/org/rootservices/jwt/serialization/exception/DecryptException.java
new file mode 100644
index 0000000..8bf295c
--- /dev/null
+++ b/src/main/java/org/rootservices/jwt/serialization/exception/DecryptException.java
@@ -0,0 +1,7 @@
+package org.rootservices.jwt.serialization.exception;
+
+public class DecryptException extends Exception {
+ public DecryptException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/src/main/java/org/rootservices/jwt/serialization/exception/EncryptException.java b/src/main/java/org/rootservices/jwt/serialization/exception/EncryptException.java
new file mode 100644
index 0000000..fe89091
--- /dev/null
+++ b/src/main/java/org/rootservices/jwt/serialization/exception/EncryptException.java
@@ -0,0 +1,7 @@
+package org.rootservices.jwt.serialization.exception;
+
+public class EncryptException extends Exception {
+ public EncryptException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/src/main/java/org/rootservices/jwt/serializer/exception/JsonException.java b/src/main/java/org/rootservices/jwt/serialization/exception/JsonException.java
similarity index 78%
rename from src/main/java/org/rootservices/jwt/serializer/exception/JsonException.java
rename to src/main/java/org/rootservices/jwt/serialization/exception/JsonException.java
index a4e434c..421d530 100644
--- a/src/main/java/org/rootservices/jwt/serializer/exception/JsonException.java
+++ b/src/main/java/org/rootservices/jwt/serialization/exception/JsonException.java
@@ -1,4 +1,4 @@
-package org.rootservices.jwt.serializer.exception;
+package org.rootservices.jwt.serialization.exception;
/**
* Created by tommackenzie on 12/5/15.
diff --git a/src/main/java/org/rootservices/jwt/serializer/exception/JsonToJwtException.java b/src/main/java/org/rootservices/jwt/serialization/exception/JsonToJwtException.java
similarity index 83%
rename from src/main/java/org/rootservices/jwt/serializer/exception/JsonToJwtException.java
rename to src/main/java/org/rootservices/jwt/serialization/exception/JsonToJwtException.java
index 4c58428..340ae4f 100644
--- a/src/main/java/org/rootservices/jwt/serializer/exception/JsonToJwtException.java
+++ b/src/main/java/org/rootservices/jwt/serialization/exception/JsonToJwtException.java
@@ -1,4 +1,4 @@
-package org.rootservices.jwt.serializer.exception;
+package org.rootservices.jwt.serialization.exception;
/**
* Created by tommackenzie on 12/5/15.
diff --git a/src/main/java/org/rootservices/jwt/serializer/exception/JwtToJsonException.java b/src/main/java/org/rootservices/jwt/serialization/exception/JwtToJsonException.java
similarity index 83%
rename from src/main/java/org/rootservices/jwt/serializer/exception/JwtToJsonException.java
rename to src/main/java/org/rootservices/jwt/serialization/exception/JwtToJsonException.java
index f7c3c71..41f4852 100644
--- a/src/main/java/org/rootservices/jwt/serializer/exception/JwtToJsonException.java
+++ b/src/main/java/org/rootservices/jwt/serialization/exception/JwtToJsonException.java
@@ -1,4 +1,4 @@
-package org.rootservices.jwt.serializer.exception;
+package org.rootservices.jwt.serialization.exception;
/**
* Created by tommackenzie on 12/12/15.
diff --git a/src/main/java/org/rootservices/jwt/serializer/JWTSerializer.java b/src/main/java/org/rootservices/jwt/serializer/JWTSerializer.java
deleted file mode 100644
index 1d08294..0000000
--- a/src/main/java/org/rootservices/jwt/serializer/JWTSerializer.java
+++ /dev/null
@@ -1,87 +0,0 @@
-package org.rootservices.jwt.serializer;
-
-import org.rootservices.jwt.entity.jwt.Claims;
-import org.rootservices.jwt.entity.jwt.JsonWebToken;
-import org.rootservices.jwt.entity.jwt.header.Header;
-import org.rootservices.jwt.serializer.exception.JsonToJwtException;
-import org.rootservices.jwt.serializer.exception.JsonException;
-import org.rootservices.jwt.serializer.exception.JwtToJsonException;
-
-import java.nio.charset.Charset;
-
-import java.util.Base64.Encoder;
-import java.util.Base64.Decoder;
-import java.util.Optional;
-
-/**
- * Created by tommackenzie on 8/13/15.
- *
- * A Serializer that converts:
- * - a jwt as a string to a instance of a JsonWebToken.
- * - a JsonWebToken to its string representation.
- */
-public class JWTSerializer {
- private final int SECURE_TOKEN_LENGTH = 3;
- private Serializer serializer;
- private Encoder encoder;
- private Decoder decoder;
- private final String DELIMITTER = ".";
-
- public JWTSerializer(Serializer serializer, Encoder encoder, Decoder decoder) {
- this.serializer = serializer;
- this.encoder = encoder;
- this.decoder = decoder;
- }
-
- public String makeSignInput(Header header, Claims claims) throws JwtToJsonException {
-
- String headerJson = "";
- String claimsJson = "";
-
- try {
- headerJson = serializer.objectToJson(header);
- claimsJson = serializer.objectToJson(claims);
- } catch (JsonException e) {
- throw new JwtToJsonException("Could not make sign input", e);
- }
-
- return encode(headerJson) + DELIMITTER + encode(claimsJson);
- }
-
- public String jwtToString(JsonWebToken jwt) throws JwtToJsonException {
-
- String jwtAsText = makeSignInput(jwt.getHeader(), jwt.getClaims()) + DELIMITTER;
-
- if (jwt.getSignature().isPresent())
- jwtAsText+= jwt.getSignature().get();
-
- return jwtAsText;
- }
-
- private String encode(String input) {
- return encoder.encodeToString(input.getBytes(Charset.forName("UTF-8")));
- }
-
- public JsonWebToken stringToJwt(String jwtAsText, Class claimClass) throws JsonToJwtException {
- String[] jwtParts = jwtAsText.split("\\.");
-
- byte[] headerJson = decoder.decode(jwtParts[0]);
- byte[] claimsJson = decoder.decode(jwtParts[1]);
-
- Header header = null;
- Claims claim = null;
- try {
- header = (Header) serializer.jsonBytesToObject(headerJson, Header.class);
- claim = (Claims) serializer.jsonBytesToObject(claimsJson, claimClass);
- } catch (JsonException e) {
- throw new JsonToJwtException("JWT json is invalid", e);
- }
-
- JsonWebToken jwt = new JsonWebToken(header, claim, Optional.of(jwtAsText));
-
- if (jwtParts.length == SECURE_TOKEN_LENGTH && jwtParts[SECURE_TOKEN_LENGTH-1] != null)
- jwt.setSignature(Optional.of(jwtParts[SECURE_TOKEN_LENGTH-1]));
-
- return jwt;
- }
-}
diff --git a/src/main/java/org/rootservices/jwt/signature/signer/MacSigner.java b/src/main/java/org/rootservices/jwt/signature/signer/MacSigner.java
deleted file mode 100644
index eb60b41..0000000
--- a/src/main/java/org/rootservices/jwt/signature/signer/MacSigner.java
+++ /dev/null
@@ -1,32 +0,0 @@
-package org.rootservices.jwt.signature.signer;
-
-
-import org.rootservices.jwt.serializer.JWTSerializer;
-import org.rootservices.jwt.serializer.Serializer;
-
-import javax.crypto.Mac;
-import java.util.Base64.Encoder;
-
-
-/**
- * Created by tommackenzie on 8/19/15.
- *
- */
-public class MacSigner extends Signer {
- private Mac mac;
-
- public MacSigner(JWTSerializer jwtSerializer, Mac mac, Encoder encoder) {
- super(jwtSerializer, encoder);
- this.mac = mac;
- }
-
- @Override
- public String run(byte[] input) {
- return sign(input);
- }
-
- private String sign(byte[] input) {
- byte[] signature = mac.doFinal(input);
- return encode(signature);
- }
-}
diff --git a/src/main/java/org/rootservices/jwt/signature/signer/Signer.java b/src/main/java/org/rootservices/jwt/signature/signer/Signer.java
deleted file mode 100644
index c340714..0000000
--- a/src/main/java/org/rootservices/jwt/signature/signer/Signer.java
+++ /dev/null
@@ -1,36 +0,0 @@
-package org.rootservices.jwt.signature.signer;
-
-import org.rootservices.jwt.entity.jwt.JsonWebToken;
-import org.rootservices.jwt.serializer.JWTSerializer;
-import org.rootservices.jwt.serializer.exception.JwtToJsonException;
-
-import java.nio.charset.Charset;
-import java.util.Base64.Encoder;
-
-/**
- * Created by tommackenzie on 8/19/15.
- */
-public abstract class Signer {
- private JWTSerializer jwtSerializer;
- private Encoder encoder;
-
- public Signer(JWTSerializer jwtSerializer, Encoder encoder) {
- this.jwtSerializer = jwtSerializer;
- this.encoder = encoder;
- }
-
- private String encode(String input) {
- return encode(input.getBytes(Charset.forName("UTF-8")));
- }
-
- public String run(JsonWebToken jwt) throws JwtToJsonException {
- String signInput = jwtSerializer.makeSignInput(jwt.getHeader(), jwt.getClaims());
- return run(signInput.getBytes());
- }
-
- protected String encode(byte[] input) {
- return encoder.encodeToString(input);
- }
-
- public abstract String run(byte[] input);
-}
diff --git a/src/main/java/org/rootservices/jwt/translator/CSRToRSAPublicKey.java b/src/main/java/org/rootservices/jwt/translator/CSRToRSAPublicKey.java
deleted file mode 100644
index d3538ae..0000000
--- a/src/main/java/org/rootservices/jwt/translator/CSRToRSAPublicKey.java
+++ /dev/null
@@ -1,58 +0,0 @@
-package org.rootservices.jwt.translator;
-
-import org.bouncycastle.openssl.PEMParser;
-import org.bouncycastle.pkcs.PKCS10CertificationRequest;
-import org.bouncycastle.pkcs.jcajce.JcaPKCS10CertificationRequest;
-import org.rootservices.jwt.entity.jwk.KeyType;
-import org.rootservices.jwt.entity.jwk.RSAPublicKey;
-import org.rootservices.jwt.entity.jwk.Use;
-import org.rootservices.jwt.translator.exception.InvalidKeyException;
-import org.rootservices.jwt.translator.exception.InvalidCsrException;
-
-import java.io.FileReader;
-import java.io.IOException;
-import java.security.NoSuchAlgorithmException;
-import java.util.Optional;
-
-/**
- * Created by tommackenzie on 12/1/15.
- */
-public class CSRToRSAPublicKey {
-
- public RSAPublicKey translate(FileReader csr, Optional keyId, Use use) throws InvalidCsrException, InvalidKeyException {
-
- PEMParser pemParser = new PEMParser(csr);
- PKCS10CertificationRequest certRequest = null;
- try {
- certRequest = (PKCS10CertificationRequest) pemParser.readObject();
- } catch (IOException e) {
- throw new InvalidCsrException("invalid file reader", e);
- } catch (ClassCastException e) {
- throw new InvalidCsrException("csr file is not a valid csr", e);
- }
-
- if (certRequest == null) {
- throw new InvalidCsrException("Could not parse the file reader");
- }
-
- JcaPKCS10CertificationRequest jcaPKCS10CertificationRequest = new JcaPKCS10CertificationRequest(certRequest);
-
- java.security.interfaces.RSAPublicKey publicKey = null;
- try {
- publicKey = (java.security.interfaces.RSAPublicKey) jcaPKCS10CertificationRequest.getPublicKey();
- } catch (java.security.InvalidKeyException e) {
- throw new InvalidKeyException("RSA public key from pem file is invalid", e);
- } catch (NoSuchAlgorithmException e) {
- throw new InvalidKeyException("Could not create RSA public key", e);
- }
-
- return new RSAPublicKey(
- keyId,
- KeyType.RSA,
- use,
- publicKey.getModulus(),
- publicKey.getPublicExponent()
- );
- }
-
-}
diff --git a/src/main/java/org/rootservices/jwt/translator/PemToRSAKeyPair.java b/src/main/java/org/rootservices/jwt/translator/PemToRSAKeyPair.java
deleted file mode 100644
index d13625b..0000000
--- a/src/main/java/org/rootservices/jwt/translator/PemToRSAKeyPair.java
+++ /dev/null
@@ -1,81 +0,0 @@
-package org.rootservices.jwt.translator;
-
-import org.bouncycastle.openssl.PEMException;
-import org.bouncycastle.openssl.PEMKeyPair;
-import org.bouncycastle.openssl.PEMParser;
-import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
-import org.rootservices.jwt.entity.jwk.KeyType;
-import org.rootservices.jwt.entity.jwk.RSAKeyPair;
-import org.rootservices.jwt.entity.jwk.Use;
-import org.rootservices.jwt.translator.exception.InvalidKeyException;
-import org.rootservices.jwt.translator.exception.InvalidPemException;
-
-import java.io.FileReader;
-import java.io.IOException;
-import java.security.KeyFactory;
-import java.security.KeyPair;
-import java.security.spec.InvalidKeySpecException;
-import java.security.spec.RSAPrivateCrtKeySpec;
-import java.util.Optional;
-
-/**
- * Created by tommackenzie on 11/30/15.
- */
-public class PemToRSAKeyPair {
-
- private JcaPEMKeyConverter converter;
- private KeyFactory RSAKeyFactory;
-
- public PemToRSAKeyPair(JcaPEMKeyConverter converter, KeyFactory RSAKeyFactory) {
- this.converter = converter;
- this.RSAKeyFactory = RSAKeyFactory;
- }
-
-
- public RSAKeyPair translate(FileReader pemFileReader, Optional keyId, Use use) throws InvalidPemException, InvalidKeyException {
- PEMParser pemParser = new PEMParser(pemFileReader);
-
- PEMKeyPair pemKeyPair = null;
- try {
- pemKeyPair = (PEMKeyPair) pemParser.readObject();
- } catch (IOException e) {
- throw new InvalidPemException("invalid file reader", e);
- } catch (ClassCastException e) {
- throw new InvalidPemException("pem did not not have a key pair", e);
- }
-
- if (pemKeyPair == null) {
- throw new InvalidPemException("Could not parse the file reader");
- }
-
- KeyPair keyPair = null;
- try {
- keyPair = converter.getKeyPair(pemKeyPair);
- } catch (PEMException e) {
- throw new InvalidPemException("Could not translate PEMKeyPair to a KeyPair");
- }
-
- RSAPrivateCrtKeySpec privateKey = null;
- try {
- privateKey = RSAKeyFactory.getKeySpec(keyPair.getPrivate(), RSAPrivateCrtKeySpec.class);
- } catch (InvalidKeySpecException e) {
- throw new InvalidKeyException("Could not create RSAPrivateCrtKeySpec", e);
- }
-
- RSAKeyPair rsaKeyPair = new RSAKeyPair(
- keyId,
- KeyType.RSA,
- use,
- privateKey.getModulus(),
- privateKey.getPublicExponent(),
- privateKey.getPrivateExponent(),
- privateKey.getPrimeP(),
- privateKey.getPrimeQ(),
- privateKey.getPrimeExponentP(),
- privateKey.getPrimeExponentQ(),
- privateKey.getCrtCoefficient()
- );
-
- return rsaKeyPair;
- }
-}
diff --git a/src/main/java/org/rootservices/jwt/translator/exception/InvalidCsrException.java b/src/main/java/org/rootservices/jwt/translator/exception/InvalidCsrException.java
deleted file mode 100644
index 4b8a5ee..0000000
--- a/src/main/java/org/rootservices/jwt/translator/exception/InvalidCsrException.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package org.rootservices.jwt.translator.exception;
-
-/**
- * Created by tommackenzie on 12/8/15.
- */
-public class InvalidCsrException extends Exception {
- public InvalidCsrException(String message) {
- super(message);
- }
-
- public InvalidCsrException(String message, Throwable cause) {
- super(message, cause);
- }
-}
diff --git a/src/main/java/org/rootservices/jwt/translator/exception/InvalidKeyException.java b/src/main/java/org/rootservices/jwt/translator/exception/InvalidKeyException.java
deleted file mode 100644
index c3e8216..0000000
--- a/src/main/java/org/rootservices/jwt/translator/exception/InvalidKeyException.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package org.rootservices.jwt.translator.exception;
-
-/**
- * Created by tommackenzie on 12/8/15.
- */
-public class InvalidKeyException extends Exception {
- public InvalidKeyException(String message) {
- super(message);
- }
-
- public InvalidKeyException(String message, Throwable cause) {
- super(message, cause);
- }
-}
diff --git a/src/main/java/org/rootservices/jwt/translator/exception/InvalidPemException.java b/src/main/java/org/rootservices/jwt/translator/exception/InvalidPemException.java
deleted file mode 100644
index c8bc63f..0000000
--- a/src/main/java/org/rootservices/jwt/translator/exception/InvalidPemException.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package org.rootservices.jwt.translator.exception;
-
-/**
- * Created by tommackenzie on 12/8/15.
- */
-public class InvalidPemException extends Exception {
- public InvalidPemException(String message) {
- super(message);
- }
-
- public InvalidPemException(String message, Throwable cause) {
- super(message, cause);
- }
-}
diff --git a/src/test/java/examples/AsymmetricSignedJsonWebToken.java b/src/test/java/examples/AsymmetricSignedJsonWebToken.java
index bd1f062..c271620 100644
--- a/src/test/java/examples/AsymmetricSignedJsonWebToken.java
+++ b/src/test/java/examples/AsymmetricSignedJsonWebToken.java
@@ -1,21 +1,19 @@
package examples;
import helper.entity.Claim;
-import org.rootservices.jwt.SecureJwtEncoder;
-import org.rootservices.jwt.factory.SecureJwtFactory;
-import org.rootservices.jwt.config.AppFactory;
+import org.rootservices.jwt.jws.serialization.SecureJwtSerializer;
+import org.rootservices.jwt.config.JwtAppFactory;
import org.rootservices.jwt.entity.jwk.KeyType;
import org.rootservices.jwt.entity.jwk.RSAKeyPair;
import org.rootservices.jwt.entity.jwk.RSAPublicKey;
import org.rootservices.jwt.entity.jwk.Use;
import org.rootservices.jwt.entity.jwt.JsonWebToken;
import org.rootservices.jwt.entity.jwt.header.Algorithm;
-import org.rootservices.jwt.serializer.JWTSerializer;
-import org.rootservices.jwt.serializer.exception.JsonToJwtException;
-import org.rootservices.jwt.serializer.exception.JwtToJsonException;
-import org.rootservices.jwt.signature.signer.factory.exception.InvalidAlgorithmException;
-import org.rootservices.jwt.signature.signer.factory.exception.InvalidJsonWebKeyException;
-import org.rootservices.jwt.signature.verifier.VerifySignature;
+import org.rootservices.jwt.exception.SignatureException;
+import org.rootservices.jwt.serialization.JwtSerde;
+import org.rootservices.jwt.serialization.exception.JsonToJwtException;
+import org.rootservices.jwt.serialization.exception.JwtToJsonException;
+import org.rootservices.jwt.jws.verifier.VerifySignature;
import java.math.BigInteger;
import java.util.Optional;
@@ -25,7 +23,7 @@
*/
public class AsymmetricSignedJsonWebToken {
- public String toEncodedJwt() {
+ public String toCompactJwt() {
RSAKeyPair keyPair = new RSAKeyPair(
Optional.of("test-key-id"),
@@ -44,19 +42,17 @@ public String toEncodedJwt() {
Claim claim = new Claim();
claim.setUriIsRoot(true);
- AppFactory appFactory = new AppFactory();
- SecureJwtEncoder secureJwtEncoder = null;
+ JwtAppFactory appFactory = new JwtAppFactory();
+ SecureJwtSerializer secureJwtSerializer = null;
try {
- secureJwtEncoder = appFactory.secureJwtEncoder(Algorithm.RS256, keyPair);
- } catch (InvalidAlgorithmException e) {
- e.printStackTrace();
- } catch (InvalidJsonWebKeyException e) {
+ secureJwtSerializer = appFactory.secureJwtSerializer(Algorithm.RS256, keyPair);
+ } catch (SignatureException e) {
e.printStackTrace();
}
String encodedJwt = null;
try {
- encodedJwt = secureJwtEncoder.encode(claim);
+ encodedJwt = secureJwtSerializer.compactJwtToString(claim);
} catch (JwtToJsonException e) {
e.printStackTrace();
}
@@ -64,7 +60,7 @@ public String toEncodedJwt() {
return encodedJwt;
}
- public Boolean verifySignature() throws JsonToJwtException, InvalidAlgorithmException, InvalidJsonWebKeyException {
+ public Boolean verifySignature() throws Exception {
String jwt = "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJodHRwOi8vZXhhbXBsZS5jb20vaXNfcm9vdCI6dHJ1ZX0.ZaZoTp-lb3C7Sb7BKQm3BZyGiMxtehBtAeN9anuDPgO_F3eR8o9UU4c1RgCFDLqO_Ftg6QCmoZ1SEDuNw8AskJWSqcuJwcOttrqf46BHB89QuGtfmhEb5fIbyuqD-n2XM2hHhvPL6yJvLd3VQNvW2VexSL3fmutC5MYoPa8IfvjGZ_QKMwA7BBwcm4Djnnlu9HwiNg3a_y6-JJxr_jW5GD8VomHZbLasokR6h5N-y-DXIIYL3-oMl-_rE1BPdm_gE76p4Lo49BM-AyUxbShAHDl-EBKsz_Vo-Pgk_4rXkBOMMJQI95FrK5FeJs2yZxMoZ_V_f5_VGnXYNzq3SFJwnQ";
RSAPublicKey publicKey = new RSAPublicKey(
@@ -75,23 +71,21 @@ public Boolean verifySignature() throws JsonToJwtException, InvalidAlgorithmExce
new BigInteger("65537")
);
- AppFactory appFactory = new AppFactory();
- JWTSerializer jwtSerializer = appFactory.jwtSerializer();
- JsonWebToken jsonWebToken = null;
+ JwtAppFactory appFactory = new JwtAppFactory();
+ JwtSerde jwtSerde = appFactory.jwtSerde();
+ JsonWebToken jsonWebToken;
try {
- jsonWebToken = jwtSerializer.stringToJwt(jwt, Claim.class);
+ jsonWebToken = jwtSerde.stringToJwt(jwt, Claim.class);
} catch (JsonToJwtException e) {
// could not serialize JsonWebToken to json string
throw e;
}
- VerifySignature verifySignature = null;
+ VerifySignature verifySignature;
try {
verifySignature = appFactory.verifySignature(Algorithm.RS256, publicKey);
- } catch (InvalidJsonWebKeyException e) {
- throw e;
- } catch (InvalidAlgorithmException e) {
+ } catch (SignatureException e) {
throw e;
}
diff --git a/src/test/java/examples/CSRFileToRSAPublicKey.java b/src/test/java/examples/CSRFileToRSAPublicKey.java
deleted file mode 100644
index 24e2637..0000000
--- a/src/test/java/examples/CSRFileToRSAPublicKey.java
+++ /dev/null
@@ -1,53 +0,0 @@
-package examples;
-
-import org.rootservices.jwt.config.AppFactory;
-import org.rootservices.jwt.entity.jwk.RSAPublicKey;
-import org.rootservices.jwt.entity.jwk.Use;
-import org.rootservices.jwt.translator.CSRToRSAPublicKey;
-import org.rootservices.jwt.translator.exception.InvalidCsrException;
-import org.rootservices.jwt.translator.exception.InvalidKeyException;
-
-import java.io.FileNotFoundException;
-import java.io.FileReader;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.util.Optional;
-
-/**
- * Created by tommackenzie on 12/12/15.
- */
-public class CSRFileToRSAPublicKey {
-
- public RSAPublicKey toRSAPublicKey() throws MalformedURLException, FileNotFoundException, InvalidCsrException, InvalidKeyException {
- AppFactory appFactory = new AppFactory();
- CSRToRSAPublicKey csrToRSAPublicKey = appFactory.csrToRSAPublicKey();
-
- URL privateKeyURL = null;
- try {
- privateKeyURL = new URL("file:///example/rsa-cert.csr");
- } catch (MalformedURLException e) {
- // invalid url.
- throw e;
- }
-
- FileReader fr = null;
- try {
- fr = new FileReader(privateKeyURL.getFile());
- } catch (FileNotFoundException e) {
- throw e;
- }
-
- RSAPublicKey rsaPublicKey = null;
- try {
- rsaPublicKey = csrToRSAPublicKey.translate(fr, Optional.of("test-key-id"), Use.SIGNATURE);
- } catch (InvalidCsrException e) {
- // csr file could not be used.
- throw e;
- } catch (InvalidKeyException e) {
- // key in the csr file could not be used.
- throw e;
- }
-
- return rsaPublicKey;
- }
-}
diff --git a/src/test/java/examples/PemFileToRSAKeyPair.java b/src/test/java/examples/PemFileToRSAKeyPair.java
deleted file mode 100644
index a136f55..0000000
--- a/src/test/java/examples/PemFileToRSAKeyPair.java
+++ /dev/null
@@ -1,53 +0,0 @@
-package examples;
-
-import org.rootservices.jwt.config.AppFactory;
-import org.rootservices.jwt.entity.jwk.RSAKeyPair;
-import org.rootservices.jwt.entity.jwk.Use;
-import org.rootservices.jwt.translator.PemToRSAKeyPair;
-import org.rootservices.jwt.translator.exception.InvalidKeyException;
-import org.rootservices.jwt.translator.exception.InvalidPemException;
-
-import java.io.FileNotFoundException;
-import java.io.FileReader;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.util.Optional;
-
-/**
- * Created by tommackenzie on 12/12/15.
- */
-public class PemFileToRSAKeyPair {
-
- public RSAKeyPair makeRSAKeyPair() throws MalformedURLException, FileNotFoundException, InvalidPemException, InvalidKeyException {
- AppFactory appFactory = new AppFactory();
- PemToRSAKeyPair pemToRSAKeyPair = appFactory.pemToRSAKeyPair();
-
- URL privateKeyURL = null;
- try {
- privateKeyURL = new URL("file:///example/rsa-private-key.pem");
- } catch (MalformedURLException e) {
- // invalid url.
- throw e;
- }
-
- FileReader pemFileReader = null;
- try {
- pemFileReader = new FileReader(privateKeyURL.getFile());
- } catch (FileNotFoundException e) {
- throw e;
- }
-
- RSAKeyPair rsaKeyPair = null;
- try {
- rsaKeyPair = pemToRSAKeyPair.translate(pemFileReader, Optional.of("test-key-id"), Use.SIGNATURE);
- } catch (InvalidPemException e) {
- // pem file could not be used.
- throw e;
- } catch (InvalidKeyException e) {
- // key in pem file could not be used.
- throw e;
- }
-
- return rsaKeyPair;
- }
-}
diff --git a/src/test/java/examples/SymmetricSignedJsonWebToken.java b/src/test/java/examples/SymmetricSignedJsonWebToken.java
index d096e2b..6666b47 100644
--- a/src/test/java/examples/SymmetricSignedJsonWebToken.java
+++ b/src/test/java/examples/SymmetricSignedJsonWebToken.java
@@ -1,19 +1,17 @@
package examples;
import helper.entity.Claim;
-import org.rootservices.jwt.SecureJwtEncoder;
-import org.rootservices.jwt.factory.SecureJwtFactory;
-import org.rootservices.jwt.config.AppFactory;
+import org.rootservices.jwt.jws.serialization.SecureJwtSerializer;
+import org.rootservices.jwt.config.JwtAppFactory;
import org.rootservices.jwt.entity.jwk.SymmetricKey;
import org.rootservices.jwt.entity.jwk.Use;
import org.rootservices.jwt.entity.jwt.JsonWebToken;
import org.rootservices.jwt.entity.jwt.header.Algorithm;
-import org.rootservices.jwt.serializer.JWTSerializer;
-import org.rootservices.jwt.serializer.exception.JsonToJwtException;
-import org.rootservices.jwt.serializer.exception.JwtToJsonException;
-import org.rootservices.jwt.signature.signer.factory.exception.InvalidAlgorithmException;
-import org.rootservices.jwt.signature.signer.factory.exception.InvalidJsonWebKeyException;
-import org.rootservices.jwt.signature.verifier.VerifySignature;
+import org.rootservices.jwt.exception.SignatureException;
+import org.rootservices.jwt.serialization.JwtSerde;
+import org.rootservices.jwt.serialization.exception.JsonToJwtException;
+import org.rootservices.jwt.serialization.exception.JwtToJsonException;
+import org.rootservices.jwt.jws.verifier.VerifySignature;
import java.util.Optional;
@@ -22,9 +20,9 @@
*/
public class SymmetricSignedJsonWebToken {
- public String toEncodedJwt() {
+ public String tocCompactJwt() {
- AppFactory appFactory = new AppFactory();
+ JwtAppFactory appFactory = new JwtAppFactory();
SymmetricKey key = new SymmetricKey(
Optional.of("test-key-id"),
@@ -35,18 +33,16 @@ public String toEncodedJwt() {
Claim claim = new Claim();
claim.setUriIsRoot(true);
- SecureJwtEncoder secureJwtEncoder = null;
+ SecureJwtSerializer secureJwtSerializer = null;
try {
- secureJwtEncoder = appFactory.secureJwtEncoder(Algorithm.HS256, key);
- } catch (InvalidAlgorithmException e) {
- e.printStackTrace();
- } catch (InvalidJsonWebKeyException e) {
+ secureJwtSerializer = appFactory.secureJwtSerializer(Algorithm.HS256, key);
+ } catch (SignatureException e) {
e.printStackTrace();
}
String encodedJwt = null;
try {
- encodedJwt = secureJwtEncoder.encode(claim);
+ encodedJwt = secureJwtSerializer.compactJwtToString(claim);
} catch (JwtToJsonException e) {
e.printStackTrace();
}
@@ -54,16 +50,16 @@ public String toEncodedJwt() {
return encodedJwt;
}
- public Boolean verifySignature() throws JsonToJwtException, InvalidJsonWebKeyException, InvalidAlgorithmException {
+ public Boolean verifySignature() throws Exception {
- AppFactory appFactory = new AppFactory();
+ JwtAppFactory appFactory = new JwtAppFactory();
String jwt = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJodHRwOi8vZXhhbXBsZS5jb20vaXNfcm9vdCI6dHJ1ZX0.TeZ3DKSE-gplbaoA8CK_RMojt8CfA1MTYaM_ZuOeGNw";
- JWTSerializer jwtSerializer = appFactory.jwtSerializer();
+ JwtSerde jwtSerde = appFactory.jwtSerde();
JsonWebToken jsonWebToken = null;
try {
- jsonWebToken = jwtSerializer.stringToJwt(jwt, Claim.class);
+ jsonWebToken = jwtSerde.stringToJwt(jwt, Claim.class);
} catch (JsonToJwtException e) {
// could not create a JsonWebToken from the jwt json.
throw e;
@@ -79,9 +75,7 @@ public Boolean verifySignature() throws JsonToJwtException, InvalidJsonWebKeyExc
VerifySignature verifySignature = null;
try {
verifySignature = appFactory.verifySignature(Algorithm.HS256, key);
- } catch (InvalidJsonWebKeyException e) {
- throw e;
- } catch (InvalidAlgorithmException e) {
+ } catch (SignatureException e) {
throw e;
}
diff --git a/src/test/java/examples/UnsecuredJsonWebTokenEncoder.java b/src/test/java/examples/UnsecuredJsonWebTokenEncoder.java
deleted file mode 100644
index 6f8dfaa..0000000
--- a/src/test/java/examples/UnsecuredJsonWebTokenEncoder.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package examples;
-
-import helper.entity.Claim;
-import org.rootservices.jwt.UnSecureJwtEncoder;
-import org.rootservices.jwt.factory.UnSecureJwtFactory;
-import org.rootservices.jwt.config.AppFactory;
-import org.rootservices.jwt.entity.jwt.JsonWebToken;
-import org.rootservices.jwt.serializer.JWTSerializer;
-import org.rootservices.jwt.serializer.exception.JwtToJsonException;
-
-/**
- * Created by tommackenzie on 12/12/15.
- */
-public class UnsecuredJsonWebTokenEncoder {
-
- public String toEncodedJwt() {
- AppFactory appFactory = new AppFactory();
- UnSecureJwtEncoder unSecureJwtEncoder = appFactory.unSecureJwtEncoder();
-
- Claim claim = new Claim();
- claim.setUriIsRoot(true);
-
- String encodedJwt = unSecureJwtEncoder.encode(claim);
-
- return encodedJwt;
- }
-}
diff --git a/src/test/java/examples/UnsecuredJsonWebTokenSerializer.java b/src/test/java/examples/UnsecuredJsonWebTokenSerializer.java
new file mode 100644
index 0000000..8448576
--- /dev/null
+++ b/src/test/java/examples/UnsecuredJsonWebTokenSerializer.java
@@ -0,0 +1,21 @@
+package examples;
+
+import helper.entity.Claim;
+import org.rootservices.jwt.serialization.UnSecureJwtSerializer;
+import org.rootservices.jwt.config.JwtAppFactory;
+
+
+public class UnsecuredJsonWebTokenSerializer {
+
+ public String toEncodedJwt() {
+ JwtAppFactory appFactory = new JwtAppFactory();
+ UnSecureJwtSerializer unSecureJwtSerializer = appFactory.unSecureJwtSerializer();
+
+ Claim claim = new Claim();
+ claim.setUriIsRoot(true);
+
+ String encodedJwt = unSecureJwtSerializer.compactJwtToString(claim);
+
+ return encodedJwt;
+ }
+}
diff --git a/src/test/java/helper/entity/Factory.java b/src/test/java/helper/entity/Factory.java
index aaf692f..91f7e99 100644
--- a/src/test/java/helper/entity/Factory.java
+++ b/src/test/java/helper/entity/Factory.java
@@ -58,6 +58,16 @@ public static SymmetricKey makeSymmetricKey() {
return key;
}
+ public static SymmetricKey makeSymmetricKeyForJWE() {
+ SymmetricKey key = new SymmetricKey(
+ Optional.empty(),
+ "MMNj8rE5m7NIDhwKYDmHSnlU1wfKuVvW6G--GKPYkRA",
+ Use.ENCRYPTION
+ );
+
+ return key;
+ }
+
public static Claim makeClaim() {
Claim claim = new Claim();
Optional issuer = Optional.of("joe");
@@ -81,4 +91,116 @@ public static JsonWebToken makeToken(Algorithm algorithm, Optional to
return new JsonWebToken(header, claim);
}
+
+ public static byte[] aad() {
+ byte[] aad = "aad".getBytes();
+ return aad;
+ }
+
+ // taken from, https://tools.ietf.org/html/rfc7515#appendix-A.1
+ public static RSAKeyPair makeRSAKeyPairForJWE() {
+
+
+ StringBuilder n = new StringBuilder();
+ n.append("oahUIoWw0K0usKNuOR6H4wkf4oBUXHTxRvgb48E-BVvxkeDNjbC4he8rUW");
+ n.append("cJoZmds2h7M70imEVhRU5djINXtqllXI4DFqcI1DgjT9LewND8MW2Krf3S");
+ n.append("psk_ZkoFnilakGygTwpZ3uesH-PFABNIUYpOiN15dsQRkgr0vEhxN92i2a");
+ n.append("sbOenSZeyaxziK72UwxrrKoExv6kc5twXTq4h-QChLOln0_mtUZwfsRaMS");
+ n.append("tPs6mS6XrgxnxbWhojf663tuEQueGC-FCMfra36C9knDFGzKsNa7LZK2dj");
+ n.append("YgyD3JR_MB_4NUJW_TqOQtwHYbxevoJArm-L5StowjzGy-_bq6Gw");
+
+ StringBuilder e = new StringBuilder();
+ e.append("AQAB");
+
+ StringBuilder d = new StringBuilder();
+ d.append("kLdtIj6GbDks_ApCSTYQtelcNttlKiOyPzMrXHeI-yk1F7-kpDxY4-WY5N");
+ d.append("WV5KntaEeXS1j82E375xxhWMHXyvjYecPT9fpwR_M9gV8n9Hrh2anTpTD9");
+ d.append("3Dt62ypW3yDsJzBnTnrYu1iwWRgBKrEYY46qAZIrA2xAwnm2X7uGR1hghk");
+ d.append("qDp0Vqj3kbSCz1XyfCs6_LehBwtxHIyh8Ripy40p24moOAbgxVw3rxT_vl");
+ d.append("t3UVe4WO3JkJOzlpUf-KTVI2Ptgm-dARxTEtE-id-4OJr0h-K-VFs3VSnd");
+ d.append("VTIznSxfyrj8ILL6MG_Uv8YAu7VILSB3lOW085-4qE3DzgrTjgyQ");
+
+ StringBuilder p = new StringBuilder();
+ p.append("1r52Xk46c-LsfB5P442p7atdPUrxQSy4mti_tZI3Mgf2EuFVbUoDBvaRQ-");
+ p.append("SWxkbkmoEzL7JXroSBjSrK3YIQgYdMgyAEPTPjXv_hI2_1eTSPVZfzL0lf");
+ p.append("fNn03IXqWF5MDFuoUYE0hzb2vhrlN_rKrbfDIwUbTrjjgieRbwC6Cl0");
+
+ StringBuilder q = new StringBuilder();
+ q.append("wLb35x7hmQWZsWJmB_vle87ihgZ19S8lBEROLIsZG4ayZVe9Hi9gDVCOBm");
+ q.append("UDdaDYVTSNx_8Fyw1YYa9XGrGnDew00J28cRUoeBB_jKI1oma0Orv1T9aX");
+ q.append("IWxKwd4gvxFImOWr3QRL9KEBRzk2RatUBnmDZJTIAfwTs0g68UZHvtc");
+
+ StringBuilder dp = new StringBuilder();
+ dp.append("ZK-YwE7diUh0qR1tR7w8WHtolDx3MZ_OTowiFvgfeQ3SiresXjm9gZ5KL");
+ dp.append("hMXvo-uz-KUJWDxS5pFQ_M0evdo1dKiRTjVw_x4NyqyXPM5nULPkcpU827");
+ dp.append("rnpZzAJKpdhWAgqrXGKAECQH0Xt4taznjnd_zVpAmZZq60WPMBMfKcuE");
+
+ StringBuilder dq = new StringBuilder();
+ dq.append("Dq0gfgJ1DdFGXiLvQEZnuKEN0UUmsJBxkjydc3j4ZYdBiMRAy86x0vHCj");
+ dq.append("ywcMlYYg4yoC4YZa9hNVcsjqA3FeiL19rk8g6Qn29Tt0cj8qqyFpz9vNDB");
+ dq.append("UfCAiJVeESOjJDZPYHdHY8v1b-o-Z2X5tvLx-TCekf7oxyeKDUqKWjis");
+
+ StringBuilder qi = new StringBuilder();
+ qi.append("VIMpMYbPf47dT1w_zDUXfPimsSegnMOA1zTaX7aGk_8urY6R8-ZW1FxU7");
+ qi.append("AlWAyLWybqq6t16VFd7hQd0y6flUK4SlOydB61gwanOsXGOAOv82cHq0E3");
+ qi.append("eL4HrtZkUuKvnPrMnsUUFlfUdybVzxyjz9JF_XyaY14ardLSjf4L_FNY");
+
+ return new RSAKeyPair(
+ Optional.empty(),
+ KeyType.RSA,
+ Use.ENCRYPTION,
+ toBigInt(n.toString()),
+ toBigInt(e.toString()),
+ toBigInt(d.toString()),
+ toBigInt(p.toString()),
+ toBigInt(q.toString()),
+ toBigInt(dp.toString()),
+ toBigInt(dq.toString()),
+ toBigInt(qi.toString())
+ );
+ }
+
+ public static RSAPublicKey makeRSAPublicKeyForJWE() {
+ StringBuilder n = new StringBuilder();
+ n.append("oahUIoWw0K0usKNuOR6H4wkf4oBUXHTxRvgb48E-BVvxkeDNjbC4he8rUW");
+ n.append("cJoZmds2h7M70imEVhRU5djINXtqllXI4DFqcI1DgjT9LewND8MW2Krf3S");
+ n.append("psk_ZkoFnilakGygTwpZ3uesH-PFABNIUYpOiN15dsQRkgr0vEhxN92i2a");
+ n.append("sbOenSZeyaxziK72UwxrrKoExv6kc5twXTq4h-QChLOln0_mtUZwfsRaMS");
+ n.append("tPs6mS6XrgxnxbWhojf663tuEQueGC-FCMfra36C9knDFGzKsNa7LZK2dj");
+ n.append("YgyD3JR_MB_4NUJW_TqOQtwHYbxevoJArm-L5StowjzGy-_bq6Gw");
+
+ StringBuilder e = new StringBuilder();
+ e.append("AQAB");
+
+ return new RSAPublicKey(
+ Optional.empty(),
+ KeyType.RSA,
+ Use.ENCRYPTION,
+ toBigInt(n.toString()),
+ toBigInt(e.toString())
+ );
+
+ }
+
+ // taken from, https://tools.ietf.org/html/rfc7516#section-3.3
+ public static String compactJWE() {
+ StringBuilder encoded = new StringBuilder();
+ encoded.append("eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkEyNTZHQ00ifQ.");
+ encoded.append("OKOawDo13gRp2ojaHV7LFpZcgV7T6DVZKTyKOMTYUmKoTCVJRgckCL9kiMT03JGe");
+ encoded.append("ipsEdY3mx_etLbbWSrFr05kLzcSr4qKAq7YN7e9jwQRb23nfa6c9d-StnImGyFDb");
+ encoded.append("Sv04uVuxIp5Zms1gNxKKK2Da14B8S4rzVRltdYwam_lDp5XnZAYpQdb76FdIKLaV");
+ encoded.append("mqgfwX7XWRxv2322i-vDxRfqNzo_tETKzpVLzfiwQyeyPGLBIO56YJ7eObdv0je8");
+ encoded.append("1860ppamavo35UgoRdbYaBcoh9QcfylQr66oc6vFWXRcZ_ZT2LawVCWTIy3brGPi");
+ encoded.append("6UklfCpIMfIjf7iGdXKHzg.");
+ encoded.append("48V1_ALb6US04U3b.");
+ encoded.append("5eym8TW_c8SuK0ltJ3rpYIzOeDQz7TALvtu6UG9oMo4vpzs9tX_EFShS8iB7j6ji");
+ encoded.append("SdiwkIr3ajwQzaBtQD_A.");
+ encoded.append("XFBoMYUZodetZdvTiFvSkQ");
+
+ return encoded.toString();
+ }
+
+ public static String symmetricCompactJWE() {
+ return "eyJhbGciOiJkaXIiLCJlbmMiOiJBMjU2R0NNIn0..0gDRrNTkCcMW_nnA1Q1yKUi0kJEAFxblm2-oUG0QhxEVtbzhWAlUnS5azsiC24Zk7Vv6DYOGCBkt2WSt_Yp2BYWrSHyxWVhNnQ0qtvm2TTh2MHjonN2Kb1NH_ooRLs6Z.NgpZSFNCr7s3SuA4mgoU1jY3bUi5KCp1pZwJ4VZT9yM8qduQaOAZj7qGRbxh.vSdENsFN2CpC1AunaZFJ-w";
+ }
}
diff --git a/src/test/java/org/rootservices/jwt/SecureJwtEncoderTest.java b/src/test/java/org/rootservices/jwt/SecureJwtEncoderTest.java
deleted file mode 100644
index 6264b66..0000000
--- a/src/test/java/org/rootservices/jwt/SecureJwtEncoderTest.java
+++ /dev/null
@@ -1,55 +0,0 @@
-package org.rootservices.jwt;
-
-import helper.entity.Claim;
-import helper.entity.Factory;
-import org.junit.Before;
-import org.junit.Test;
-import org.rootservices.jwt.config.AppFactory;
-import org.rootservices.jwt.entity.jwk.RSAKeyPair;
-import org.rootservices.jwt.entity.jwk.SymmetricKey;
-import org.rootservices.jwt.entity.jwt.header.Algorithm;
-import org.rootservices.jwt.factory.SecureJwtFactory;
-
-import java.util.Optional;
-
-import static org.hamcrest.core.Is.is;
-import static org.junit.Assert.*;
-
-/**
- * Created by tommackenzie on 9/3/16.
- */
-public class SecureJwtEncoderTest {
- private AppFactory appFactory;
-
- @Before
- public void setUp() {
- appFactory = new AppFactory();
- }
-
- @Test
- public void encodeWithSymmetricKeyShouldEncode() throws Exception {
- SymmetricKey key = Factory.makeSymmetricKey();
- key.setKeyId(Optional.of("test-key-id"));
-
- Claim claim = Factory.makeClaim();
-
- SecureJwtEncoder subject = appFactory.secureJwtEncoder(Algorithm.HS256, key);
- String jwt = subject.encode(claim);
-
- assertThat(jwt, is("eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiIsImtpZCI6InRlc3Qta2V5LWlkIn0.eyJpc3MiOiJqb2UiLCJleHAiOjEzMDA4MTkzODAsImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ.YiFm03WWrDAbFn7omROmU2GHACkaGI30xdbWFzyoCNQ"));
-
- }
-
- @Test
- public void encodeWithAsymmetricKeyShouldEncode() throws Exception {
- RSAKeyPair key = Factory.makeRSAKeyPair();
- key.setKeyId(Optional.of("test-key-id"));
-
- Claim claim = Factory.makeClaim();
-
- SecureJwtEncoder subject = appFactory.secureJwtEncoder(Algorithm.RS256, key);
- String jwt = subject.encode(claim);
-
- assertThat(jwt, is("eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6InRlc3Qta2V5LWlkIn0.eyJpc3MiOiJqb2UiLCJleHAiOjEzMDA4MTkzODAsImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ.JmMm15IjKsNB18oMqIIaIPHQ8TuqEXNdbmGyEya5Yuoo2Kj132PhiCt2gbPL2i75IH1Zmjvdc7Fm2eb2Db6P6NXezZEHgZG3WVTWJwl11lQnDnj6hTrTbHnL0XUgcFw0vIwthQF6NNjAy2lTMSG0KTH5y_3D-5pt6FM2cyfvK5RwhCom9v2MDWA7fTqR1u5L-_dfcgRlN5rjQ-QYBsk3oaNTMU9MtXtEuG7erun_-VXQJjXGwDRO_kPmzN-wILyoaOr670xpaHVmFLrTakjvfhCkLrB1YwdQV-B6ZFLqTpQpGr7ydEWMyuoiV0Xg71-mJhNHeml_jFMUwm-Lu-d2Og"));
- }
-}
\ No newline at end of file
diff --git a/src/test/java/org/rootservices/jwt/UnSecureJwtEncoderTest.java b/src/test/java/org/rootservices/jwt/UnSecureJwtEncoderTest.java
deleted file mode 100644
index 029a15a..0000000
--- a/src/test/java/org/rootservices/jwt/UnSecureJwtEncoderTest.java
+++ /dev/null
@@ -1,34 +0,0 @@
-package org.rootservices.jwt;
-
-import helper.entity.Factory;
-import org.junit.Before;
-import org.junit.Test;
-import org.rootservices.jwt.config.AppFactory;
-import org.rootservices.jwt.entity.jwt.Claims;
-
-import static org.hamcrest.core.Is.is;
-import static org.junit.Assert.*;
-
-/**
- * Created by tommackenzie on 9/3/16.
- */
-public class UnSecureJwtEncoderTest {
- private AppFactory appFactory;
-
- @Before
- public void setUp() {
- appFactory = new AppFactory();
- }
-
- @Test
- public void encodeShouldEncode() {
- UnSecureJwtEncoder subject = appFactory.unSecureJwtEncoder();
-
- Claims claims = Factory.makeClaim();
-
- String jwt = subject.encode(claims);
-
- assertThat(jwt, is("eyJhbGciOiJub25lIn0.eyJpc3MiOiJqb2UiLCJleHAiOjEzMDA4MTkzODAsImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ."));
- }
-
-}
\ No newline at end of file
diff --git a/src/test/java/org/rootservices/jwt/factory/SecureJwtFactoryTest.java b/src/test/java/org/rootservices/jwt/factory/SecureJwtFactoryTest.java
index 1adccdc..cd5f976 100644
--- a/src/test/java/org/rootservices/jwt/factory/SecureJwtFactoryTest.java
+++ b/src/test/java/org/rootservices/jwt/factory/SecureJwtFactoryTest.java
@@ -4,15 +4,15 @@
import helper.entity.Factory;
import org.junit.Before;
import org.junit.Test;
-import org.rootservices.jwt.config.AppFactory;
+import org.rootservices.jwt.config.JwtAppFactory;
import org.rootservices.jwt.entity.jwk.RSAKeyPair;
import org.rootservices.jwt.entity.jwk.SymmetricKey;
import org.rootservices.jwt.entity.jwt.JsonWebToken;
import org.rootservices.jwt.entity.jwt.header.Algorithm;
import org.rootservices.jwt.entity.jwt.header.TokenType;
-import org.rootservices.jwt.serializer.exception.JwtToJsonException;
-import org.rootservices.jwt.signature.signer.factory.exception.InvalidAlgorithmException;
-import org.rootservices.jwt.signature.signer.factory.exception.InvalidJsonWebKeyException;
+import org.rootservices.jwt.serialization.exception.JwtToJsonException;
+import org.rootservices.jwt.jws.signer.factory.exception.InvalidAlgorithmException;
+import org.rootservices.jwt.jws.signer.factory.exception.InvalidJsonWebKeyException;
import java.util.Optional;
@@ -23,16 +23,14 @@
import static org.junit.Assert.assertThat;
-/**
- * Created by tommackenzie on 9/15/15.
- */
+
public class SecureJwtFactoryTest {
- private AppFactory appFactory;
+ private JwtAppFactory appFactory;
@Before
public void setUp(){
- appFactory = new AppFactory();
+ appFactory = new JwtAppFactory();
}
@@ -86,7 +84,7 @@ public void buildWithSymmetricKeyShouldHaveValidHeaderClaimsSignature() throws E
// inspect signature.
assertThat(actual.getSignature().isPresent(), is(true));
- assertThat(actual.getSignature().get(), is("lliDzOlRAdGUCfCHCPx_uisb6ZfZ1LRQa0OJLeYTTpY"));
+ assertThat(actual.getSignature().get(), is("lliDzOlRAdGUCfCHCPx_uisb6ZfZ1LRQa0OJLeYTTpY".getBytes()));
// claims ivars that were not assigned.
assertThat(actualClaim.getSubject().isPresent(), is(false));
@@ -137,7 +135,7 @@ public void buildWithRSAKeyPairShouldHaveValidHeaderClaimsSignature() throws Exc
// inspect signature.
assertThat(actual.getSignature().isPresent(), is(true));
- assertThat(actual.getSignature().get(), is("IDcgYnWIJ0my4FurSqfiAAbYBz2BfImT-uSqKKnk-JfncL_Nreo8Phol1KNn9fK0ZmVfcvHL-pUvVUBzI5NrJNCFMiyZWxS7msB2VKl6-jAXr9NqtVjIDyUSr_gpk51xSzHiBPVAnQn8m1Dg3dR0YkP9b5uJ70qpZ37PWOCKYAIfAhinDA77RIP9q4ImwpnJuY3IDuilDKOq9bsb6zWB8USz0PAYReqWierdS4TYAbUFrhuGZ9mPgSLRSQVtibyNTSTQYtfghYkmV9gWyCJUVwMGCM5l1xlylHYiioasBJA1Wr_NAf_sr4G8OVrW1eO01MKhijpaE8pR6DvPYNrTMQ"));
+ assertThat(actual.getSignature().get(), is("IDcgYnWIJ0my4FurSqfiAAbYBz2BfImT-uSqKKnk-JfncL_Nreo8Phol1KNn9fK0ZmVfcvHL-pUvVUBzI5NrJNCFMiyZWxS7msB2VKl6-jAXr9NqtVjIDyUSr_gpk51xSzHiBPVAnQn8m1Dg3dR0YkP9b5uJ70qpZ37PWOCKYAIfAhinDA77RIP9q4ImwpnJuY3IDuilDKOq9bsb6zWB8USz0PAYReqWierdS4TYAbUFrhuGZ9mPgSLRSQVtibyNTSTQYtfghYkmV9gWyCJUVwMGCM5l1xlylHYiioasBJA1Wr_NAf_sr4G8OVrW1eO01MKhijpaE8pR6DvPYNrTMQ".getBytes()));
// claims ivars that were not assigned.
assertThat(actualClaim.getSubject().isPresent(), is(false));
@@ -182,14 +180,14 @@ public void buildTwiceWithRSAKeyPairShouldSignsCorrectly() throws JwtToJsonExcep
assertThat(actual, is(notNullValue()));
assertThat(actual.getSignature().isPresent(), is(true));
- assertThat(actual.getSignature().get(), is("IDcgYnWIJ0my4FurSqfiAAbYBz2BfImT-uSqKKnk-JfncL_Nreo8Phol1KNn9fK0ZmVfcvHL-pUvVUBzI5NrJNCFMiyZWxS7msB2VKl6-jAXr9NqtVjIDyUSr_gpk51xSzHiBPVAnQn8m1Dg3dR0YkP9b5uJ70qpZ37PWOCKYAIfAhinDA77RIP9q4ImwpnJuY3IDuilDKOq9bsb6zWB8USz0PAYReqWierdS4TYAbUFrhuGZ9mPgSLRSQVtibyNTSTQYtfghYkmV9gWyCJUVwMGCM5l1xlylHYiioasBJA1Wr_NAf_sr4G8OVrW1eO01MKhijpaE8pR6DvPYNrTMQ"));
+ assertThat(actual.getSignature().get(), is("IDcgYnWIJ0my4FurSqfiAAbYBz2BfImT-uSqKKnk-JfncL_Nreo8Phol1KNn9fK0ZmVfcvHL-pUvVUBzI5NrJNCFMiyZWxS7msB2VKl6-jAXr9NqtVjIDyUSr_gpk51xSzHiBPVAnQn8m1Dg3dR0YkP9b5uJ70qpZ37PWOCKYAIfAhinDA77RIP9q4ImwpnJuY3IDuilDKOq9bsb6zWB8USz0PAYReqWierdS4TYAbUFrhuGZ9mPgSLRSQVtibyNTSTQYtfghYkmV9gWyCJUVwMGCM5l1xlylHYiioasBJA1Wr_NAf_sr4G8OVrW1eO01MKhijpaE8pR6DvPYNrTMQ".getBytes()));
// second JsonWebToken
actual = subject.makeJwt(claim);
assertThat(actual, is(notNullValue()));
assertThat(actual.getSignature().isPresent(), is(true));
- assertThat(actual.getSignature().get(), is("IDcgYnWIJ0my4FurSqfiAAbYBz2BfImT-uSqKKnk-JfncL_Nreo8Phol1KNn9fK0ZmVfcvHL-pUvVUBzI5NrJNCFMiyZWxS7msB2VKl6-jAXr9NqtVjIDyUSr_gpk51xSzHiBPVAnQn8m1Dg3dR0YkP9b5uJ70qpZ37PWOCKYAIfAhinDA77RIP9q4ImwpnJuY3IDuilDKOq9bsb6zWB8USz0PAYReqWierdS4TYAbUFrhuGZ9mPgSLRSQVtibyNTSTQYtfghYkmV9gWyCJUVwMGCM5l1xlylHYiioasBJA1Wr_NAf_sr4G8OVrW1eO01MKhijpaE8pR6DvPYNrTMQ"));
+ assertThat(actual.getSignature().get(), is("IDcgYnWIJ0my4FurSqfiAAbYBz2BfImT-uSqKKnk-JfncL_Nreo8Phol1KNn9fK0ZmVfcvHL-pUvVUBzI5NrJNCFMiyZWxS7msB2VKl6-jAXr9NqtVjIDyUSr_gpk51xSzHiBPVAnQn8m1Dg3dR0YkP9b5uJ70qpZ37PWOCKYAIfAhinDA77RIP9q4ImwpnJuY3IDuilDKOq9bsb6zWB8USz0PAYReqWierdS4TYAbUFrhuGZ9mPgSLRSQVtibyNTSTQYtfghYkmV9gWyCJUVwMGCM5l1xlylHYiioasBJA1Wr_NAf_sr4G8OVrW1eO01MKhijpaE8pR6DvPYNrTMQ".getBytes()));
}
@@ -208,14 +206,14 @@ public void buildTwiceWithSymmetricKeyShouldSignsCorrectly() throws JwtToJsonExc
assertThat(actual, is(notNullValue()));
assertThat(actual.getSignature().isPresent(), is(true));
- assertThat(actual.getSignature().get(), is("lliDzOlRAdGUCfCHCPx_uisb6ZfZ1LRQa0OJLeYTTpY"));
+ assertThat(actual.getSignature().get(), is("lliDzOlRAdGUCfCHCPx_uisb6ZfZ1LRQa0OJLeYTTpY".getBytes()));
// second JsonWebToken
actual = subject.makeJwt(claim);
assertThat(actual, is(notNullValue()));
assertThat(actual.getSignature().isPresent(), is(true));
- assertThat(actual.getSignature().get(), is("lliDzOlRAdGUCfCHCPx_uisb6ZfZ1LRQa0OJLeYTTpY"));
+ assertThat(actual.getSignature().get(), is("lliDzOlRAdGUCfCHCPx_uisb6ZfZ1LRQa0OJLeYTTpY".getBytes()));
}
}
\ No newline at end of file
diff --git a/src/test/java/org/rootservices/jwt/factory/UnSecureJwtFactoryTest.java b/src/test/java/org/rootservices/jwt/factory/UnSecureJwtFactoryTest.java
index e31e2eb..12d8383 100644
--- a/src/test/java/org/rootservices/jwt/factory/UnSecureJwtFactoryTest.java
+++ b/src/test/java/org/rootservices/jwt/factory/UnSecureJwtFactoryTest.java
@@ -2,7 +2,7 @@
import org.junit.Before;
import org.junit.Test;
-import org.rootservices.jwt.config.AppFactory;
+import org.rootservices.jwt.config.JwtAppFactory;
import org.rootservices.jwt.entity.jwt.JsonWebToken;
import helper.entity.Claim;
@@ -24,7 +24,7 @@ public class UnSecureJwtFactoryTest {
@Before
public void setUp(){
- AppFactory appFactory = new AppFactory();
+ JwtAppFactory appFactory = new JwtAppFactory();
subject = appFactory.unsecureJwtFactory();
}
diff --git a/src/test/java/org/rootservices/jwt/jwe/factory/CipherRSAFactoryTest.java b/src/test/java/org/rootservices/jwt/jwe/factory/CipherRSAFactoryTest.java
new file mode 100644
index 0000000..5a02ed2
--- /dev/null
+++ b/src/test/java/org/rootservices/jwt/jwe/factory/CipherRSAFactoryTest.java
@@ -0,0 +1,59 @@
+package org.rootservices.jwt.jwe.factory;
+
+import helper.entity.Factory;
+import org.junit.Before;
+import org.junit.Test;
+import org.rootservices.jwt.config.JwtAppFactory;
+import org.rootservices.jwt.jwe.Transformation;
+import org.rootservices.jwt.entity.jwk.RSAKeyPair;
+import org.rootservices.jwt.entity.jwk.RSAPublicKey;
+import org.rootservices.jwt.jwk.PrivateKeyFactory;
+import org.rootservices.jwt.jwk.PublicKeyFactory;
+
+import javax.crypto.Cipher;
+
+import java.security.interfaces.RSAPrivateCrtKey;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.notNullValue;
+import static org.hamcrest.CoreMatchers.nullValue;
+import static org.junit.Assert.*;
+
+public class CipherRSAFactoryTest {
+ private PublicKeyFactory publicKeyFactory;
+ private PrivateKeyFactory privateKeyFactory;
+ private CipherRSAFactory subject;
+
+ @Before
+ public void setUp() {
+ JwtAppFactory jwtAppFactory = new JwtAppFactory();
+ publicKeyFactory = jwtAppFactory.publicKeyFactory();
+ privateKeyFactory = jwtAppFactory.privateKeyFactory();
+ subject = new CipherRSAFactory();
+ }
+
+ @Test
+ public void forEncryptWhenPublicKey() throws Exception {
+
+ RSAPublicKey rsaPublicKey = Factory.makeRSAPublicKey();
+ java.security.interfaces.RSAPublicKey jdkPublicKey = publicKeyFactory.makePublicKey(rsaPublicKey);
+
+ Cipher actual = subject.forEncrypt(Transformation.RSA_OAEP, jdkPublicKey);
+
+ assertThat(actual, is(notNullValue()));
+ assertThat(actual.getAlgorithm(), is(Transformation.RSA_OAEP.getValue()));
+ assertThat(actual.getIV(), is(nullValue()));
+ }
+
+ @Test
+ public void forDecryptWhenPrivateKey() throws Exception {
+ RSAKeyPair jwk = Factory.makeRSAKeyPair();
+ RSAPrivateCrtKey jdkPrivateKey = privateKeyFactory.makePrivateKey(jwk);
+
+ Cipher actual = subject.forDecrypt(Transformation.RSA_OAEP, jdkPrivateKey);
+
+ assertThat(actual, is(notNullValue()));
+ assertThat(actual.getAlgorithm(), is(Transformation.RSA_OAEP.getValue()));
+ assertThat(actual.getIV(), is(nullValue()));
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/org/rootservices/jwt/jwe/factory/CipherSymmetricFactoryTest.java b/src/test/java/org/rootservices/jwt/jwe/factory/CipherSymmetricFactoryTest.java
new file mode 100644
index 0000000..940ef81
--- /dev/null
+++ b/src/test/java/org/rootservices/jwt/jwe/factory/CipherSymmetricFactoryTest.java
@@ -0,0 +1,54 @@
+package org.rootservices.jwt.jwe.factory;
+
+
+import helper.entity.Factory;
+import org.junit.Before;
+import org.junit.Test;
+import org.rootservices.jwt.jwe.Transformation;
+import org.rootservices.jwt.jwk.KeyAlgorithm;
+import org.rootservices.jwt.jwk.SecretKeyFactory;
+
+import javax.crypto.Cipher;
+import javax.crypto.SecretKey;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.notNullValue;
+import static org.junit.Assert.*;
+
+public class CipherSymmetricFactoryTest {
+
+ private CipherSymmetricFactory subject;
+
+ @Before
+ public void setUp() {
+ subject = new CipherSymmetricFactory();
+ }
+
+ @Test
+ public void forEncryptWhenSecretKey() throws Exception {
+ SecretKeyFactory secretKeyFactory = new SecretKeyFactory();
+ SecretKey secretKey = secretKeyFactory.makeKey(KeyAlgorithm.AES);
+ byte[] aad = Factory.aad();
+
+ Cipher actual = subject.forEncrypt(Transformation.AES_GCM_NO_PADDING, secretKey, aad);
+
+ assertThat(actual, is(notNullValue()));
+ assertThat(actual.getAlgorithm(), is(Transformation.AES_GCM_NO_PADDING.getValue()));
+ assertThat(actual.getIV(), is(notNullValue()));
+ }
+
+ @Test
+ public void forDecryptWhenSecretKey() throws Exception {
+ SecretKeyFactory secretKeyFactory = new SecretKeyFactory();
+ SecretKey secretKey = secretKeyFactory.makeKey(KeyAlgorithm.AES);
+ byte[] aad = Factory.aad();
+
+ byte[] initVector = subject.makeInitVector();
+ Cipher actual = subject.forDecrypt(Transformation.AES_GCM_NO_PADDING, secretKey, initVector, aad);
+
+ assertThat(actual, is(notNullValue()));
+ assertThat(actual.getAlgorithm(), is(Transformation.AES_GCM_NO_PADDING.getValue()));
+ assertThat(actual.getIV(), is(notNullValue()));
+ assertThat(actual.getIV(), is(initVector));
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/org/rootservices/jwt/jwe/factory/SecretKeyFactoryTest.java b/src/test/java/org/rootservices/jwt/jwe/factory/SecretKeyFactoryTest.java
new file mode 100644
index 0000000..98fd21f
--- /dev/null
+++ b/src/test/java/org/rootservices/jwt/jwe/factory/SecretKeyFactoryTest.java
@@ -0,0 +1,29 @@
+package org.rootservices.jwt.jwe.factory;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.rootservices.jwt.jwk.KeyAlgorithm;
+import org.rootservices.jwt.jwk.SecretKeyFactory;
+
+import javax.crypto.SecretKey;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.notNullValue;
+import static org.junit.Assert.*;
+
+public class SecretKeyFactoryTest {
+ private SecretKeyFactory subject;
+
+ @Before
+ public void setUp() {
+ subject = new SecretKeyFactory();
+ }
+ @Test
+ public void makeKeyForAESAnd256ShouldBeOk() throws Exception {
+ SecretKey actual = subject.makeKey(KeyAlgorithm.AES);
+
+ assertThat(actual, is(notNullValue()));
+ assertThat(actual.getAlgorithm(), is(KeyAlgorithm.AES.getValue()));
+ assertThat(actual.getEncoded(), is(notNullValue()));
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/org/rootservices/jwt/jwe/serialization/direct/JweDirectDesializerTest.java b/src/test/java/org/rootservices/jwt/jwe/serialization/direct/JweDirectDesializerTest.java
new file mode 100644
index 0000000..289a26a
--- /dev/null
+++ b/src/test/java/org/rootservices/jwt/jwe/serialization/direct/JweDirectDesializerTest.java
@@ -0,0 +1,48 @@
+package org.rootservices.jwt.jwe.serialization.direct;
+
+import helper.entity.Factory;
+import org.hamcrest.CoreMatchers;
+import org.junit.Test;
+import org.rootservices.jwt.config.JwtAppFactory;
+import org.rootservices.jwt.entity.jwe.EncryptionAlgorithm;
+import org.rootservices.jwt.entity.jwk.SymmetricKey;
+import org.rootservices.jwt.entity.jwt.header.Algorithm;
+import org.rootservices.jwt.entity.jwt.header.AlgorithmFor;
+import org.rootservices.jwt.jwe.entity.JWE;
+import org.rootservices.jwt.jwe.serialization.JweDeserializer;
+
+import java.nio.charset.StandardCharsets;
+
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.notNullValue;
+import static org.junit.Assert.*;
+
+public class JweDirectDesializerTest {
+ private static JwtAppFactory jwtAppFactory = new JwtAppFactory();
+
+ @Test
+ public void stringToJWE() throws Exception {
+ JweDeserializer subject = jwtAppFactory.jweDirectDesializer();
+
+ SymmetricKey key = Factory.makeSymmetricKeyForJWE();
+ String compactJwe = Factory.symmetricCompactJWE();
+
+ JWE actual = subject.stringToJWE(compactJwe, key);
+
+ assertThat(actual, is(notNullValue()));
+
+ assertThat(actual.getHeader().getKeyId().isPresent(), CoreMatchers.is(false));
+ assertThat(actual.getHeader().getType().isPresent(), CoreMatchers.is(false));
+ assertThat(actual.getHeader().getAlgorithm(), CoreMatchers.is(Algorithm.DIRECT));
+ assertThat(actual.getHeader().getAlgorithm().getAlgorithmFor(), CoreMatchers.is(AlgorithmFor.JWE));
+ assertThat(actual.getHeader().getEncryptionAlgorithm().isPresent(), CoreMatchers.is(true));
+ assertThat(actual.getHeader().getEncryptionAlgorithm().get(), CoreMatchers.is(EncryptionAlgorithm.AES_GCM_256));
+
+ assertThat(actual.getCek(), CoreMatchers.is(CoreMatchers.notNullValue()));
+ assertThat(actual.getIv(), CoreMatchers.is(CoreMatchers.notNullValue()));
+ assertThat(actual.getAuthTag(), CoreMatchers.is(CoreMatchers.notNullValue()));
+
+ String payload = new String(actual.getPayload(), StandardCharsets.UTF_8);
+ assertThat(payload, CoreMatchers.is("Help me, Obi-Wan Kenobi. You're my only hope."));
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/org/rootservices/jwt/jwe/serialization/direct/JweDirectSerdesTest.java b/src/test/java/org/rootservices/jwt/jwe/serialization/direct/JweDirectSerdesTest.java
new file mode 100644
index 0000000..9c5034e
--- /dev/null
+++ b/src/test/java/org/rootservices/jwt/jwe/serialization/direct/JweDirectSerdesTest.java
@@ -0,0 +1,76 @@
+package org.rootservices.jwt.jwe.serialization.direct;
+
+import helper.entity.Factory;
+import org.hamcrest.CoreMatchers;
+import org.junit.Test;
+import org.rootservices.jwt.config.JwtAppFactory;
+import org.rootservices.jwt.entity.jwe.EncryptionAlgorithm;
+import org.rootservices.jwt.entity.jwk.SymmetricKey;
+import org.rootservices.jwt.entity.jwt.header.Algorithm;
+import org.rootservices.jwt.entity.jwt.header.Header;
+import org.rootservices.jwt.jwe.entity.JWE;
+import org.rootservices.jwt.jwe.serialization.JweDeserializer;
+import org.rootservices.jwt.jwe.serialization.JweSerializer;
+import org.rootservices.jwt.jwe.serialization.rsa.JweRsaDeserializer;
+
+import java.io.ByteArrayOutputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.Base64;
+import java.util.Optional;
+
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.notNullValue;
+import static org.junit.Assert.*;
+import static org.mockito.Matchers.notNull;
+
+public class JweDirectSerdesTest {
+ private static JwtAppFactory jwtAppFactory = new JwtAppFactory();
+
+ @Test
+ public void JWEToCompact() throws Exception {
+ JweSerializer subject = jwtAppFactory.jweDirectSerializer();
+
+ SymmetricKey key = Factory.makeSymmetricKeyForJWE();
+
+ Base64.Decoder decoder = jwtAppFactory.urlDecoder();
+
+ Header header = new Header();
+ header.setEncryptionAlgorithm(Optional.of(EncryptionAlgorithm.AES_GCM_256));
+ header.setAlgorithm(Algorithm.DIRECT);
+
+ JWE jwe = new JWE();
+ jwe.setHeader(header);
+ jwe.setCek(decoder.decode(key.getKey()));
+ jwe.setPayload("Help me, Obi-Wan Kenobi. You're my only hope.".getBytes());
+
+ ByteArrayOutputStream actual = subject.JWEToCompact(jwe);
+ assertThat(actual, is(notNullValue()));
+
+ String compactJWE = actual.toString();
+
+ String[] jweParts = compactJWE.split("\\.");
+ String protectedHeader = new String(decoder.decode(jweParts[0]), StandardCharsets.UTF_8);
+ String encryptedKey = new String(decoder.decode(jweParts[1]), StandardCharsets.UTF_8);
+ String initVector = new String(decoder.decode(jweParts[2]), StandardCharsets.UTF_8);
+ String cipherText = new String(decoder.decode(jweParts[3]), StandardCharsets.UTF_8);
+ String authenticationTag = new String(decoder.decode(jweParts[4]), StandardCharsets.UTF_8);
+
+ assertThat(protectedHeader, is(notNullValue()));
+
+ assertThat(encryptedKey, is(notNullValue()));
+ assertThat(encryptedKey, is(""));
+
+ assertThat(initVector, is(notNullValue()));
+ assertThat(cipherText, is(notNullValue()));
+ assertThat(authenticationTag, is(notNullValue()));
+
+ // should be able to deserialize it.
+ JweDeserializer jweDeserializer = jwtAppFactory.jweDirectDesializer();
+
+ JWE leia = jweDeserializer.stringToJWE(compactJWE, key);
+
+ assertThat(leia, CoreMatchers.is(CoreMatchers.notNullValue()));
+ String payload = new String(leia.getPayload());
+ assertThat(payload, CoreMatchers.is("Help me, Obi-Wan Kenobi. You're my only hope."));
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/org/rootservices/jwt/jwe/serialization/rsa/JweRsaDeserializerTest.java b/src/test/java/org/rootservices/jwt/jwe/serialization/rsa/JweRsaDeserializerTest.java
new file mode 100644
index 0000000..fb4bc2e
--- /dev/null
+++ b/src/test/java/org/rootservices/jwt/jwe/serialization/rsa/JweRsaDeserializerTest.java
@@ -0,0 +1,47 @@
+package org.rootservices.jwt.jwe.serialization.rsa;
+
+import helper.entity.Factory;
+import org.junit.Test;
+import org.rootservices.jwt.config.JwtAppFactory;
+import org.rootservices.jwt.entity.jwe.EncryptionAlgorithm;
+import org.rootservices.jwt.entity.jwk.RSAKeyPair;
+import org.rootservices.jwt.entity.jwt.header.Algorithm;
+import org.rootservices.jwt.entity.jwt.header.AlgorithmFor;
+import org.rootservices.jwt.jwe.entity.JWE;
+
+
+import java.nio.charset.StandardCharsets;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.notNullValue;
+import static org.junit.Assert.*;
+
+public class JweRsaDeserializerTest {
+
+ @Test
+ public void stringToJWE() throws Exception {
+ JwtAppFactory jwtAppFactory = new JwtAppFactory();
+ RSAKeyPair jwk = Factory.makeRSAKeyPairForJWE();
+ JweRsaDeserializer subject = jwtAppFactory.jweRsaDeserializer();
+
+ String compactJWE = Factory.compactJWE();
+
+ JWE actual = subject.stringToJWE(compactJWE, jwk);
+
+ assertThat(actual, is(notNullValue()));
+
+ assertThat(actual.getHeader().getKeyId().isPresent(), is(false));
+ assertThat(actual.getHeader().getType().isPresent(), is(false));
+ assertThat(actual.getHeader().getAlgorithm(), is(Algorithm.RSAES_OAEP));
+ assertThat(actual.getHeader().getAlgorithm().getAlgorithmFor(), is(AlgorithmFor.JWE));
+ assertThat(actual.getHeader().getEncryptionAlgorithm().isPresent(), is(true));
+ assertThat(actual.getHeader().getEncryptionAlgorithm().get(), is(EncryptionAlgorithm.AES_GCM_256));
+
+ assertThat(actual.getCek(), is(notNullValue()));
+ assertThat(actual.getIv(), is(notNullValue()));
+ assertThat(actual.getAuthTag(), is(notNullValue()));
+
+ String payload = new String(actual.getPayload(), StandardCharsets.UTF_8);
+ assertThat(payload, is("The true sign of intelligence is not knowledge but imagination."));
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/org/rootservices/jwt/jwe/serialization/rsa/JweRsaSerdesTest.java b/src/test/java/org/rootservices/jwt/jwe/serialization/rsa/JweRsaSerdesTest.java
new file mode 100644
index 0000000..4b02144
--- /dev/null
+++ b/src/test/java/org/rootservices/jwt/jwe/serialization/rsa/JweRsaSerdesTest.java
@@ -0,0 +1,114 @@
+package org.rootservices.jwt.jwe.serialization.rsa;
+
+import helper.entity.Factory;
+import org.junit.Test;
+import org.rootservices.jwt.config.JwtAppFactory;
+import org.rootservices.jwt.entity.jwe.EncryptionAlgorithm;
+import org.rootservices.jwt.entity.jwk.RSAKeyPair;
+import org.rootservices.jwt.entity.jwk.RSAPublicKey;
+import org.rootservices.jwt.entity.jwk.SymmetricKey;
+import org.rootservices.jwt.entity.jwt.header.Algorithm;
+import org.rootservices.jwt.entity.jwt.header.Header;
+import org.rootservices.jwt.jwe.entity.JWE;
+
+
+import java.io.ByteArrayOutputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.Base64;
+import java.util.Optional;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.notNullValue;
+import static org.junit.Assert.*;
+
+public class JweRsaSerdesTest {
+
+ @Test
+ public void extractCipherText() throws Exception {
+ JwtAppFactory jwtAppFactory = new JwtAppFactory();
+ Base64.Decoder decoder = jwtAppFactory.urlDecoder();
+ String compactJWE = Factory.compactJWE();
+
+ String[] jweParts = compactJWE.split(JweRsaDeserializer.JWT_SPLITTER);
+ byte[] protectedHeader = decoder.decode(jweParts[0]);
+ byte[] encryptedKey = decoder.decode(jweParts[1]);
+ byte[] initVector = decoder.decode(jweParts[2]);
+ byte[] cipherText = decoder.decode(jweParts[3]);
+ byte[] authenticationTag = decoder.decode(jweParts[4]);
+
+ RSAKeyPair jwk = Factory.makeRSAKeyPairForJWE();
+ JweRsaDeserializer JweRsaDeserializer = jwtAppFactory.jweRsaDeserializer();
+
+ RSAPublicKey publicKey = Factory.makeRSAPublicKeyForJWE();
+ JweRsaSerializer subject = jwtAppFactory.jweRsaSerializer(publicKey);
+
+ byte[] cipherTextWithAuthTag = JweRsaDeserializer.cipherTextWithAuthTag(cipherText, authenticationTag);
+
+ assertThat(cipherTextWithAuthTag.length, is(cipherText.length + authenticationTag.length));
+
+ byte[] actual = subject.extractCipherText(cipherTextWithAuthTag);
+ assertThat(actual.length, is(cipherText.length));
+ assertThat(actual, is(cipherText));
+ }
+
+ @Test
+ public void extractAuthTag() throws Exception {
+ JwtAppFactory jwtAppFactory = new JwtAppFactory();
+ Base64.Decoder decoder = jwtAppFactory.urlDecoder();
+ String compactJWE = Factory.compactJWE();
+
+ String[] jweParts = compactJWE.split(JweRsaDeserializer.JWT_SPLITTER);
+ byte[] protectedHeader = decoder.decode(jweParts[0]);
+ byte[] encryptedKey = decoder.decode(jweParts[1]);
+ byte[] initVector = decoder.decode(jweParts[2]);
+ byte[] cipherText = decoder.decode(jweParts[3]);
+ byte[] authenticationTag = decoder.decode(jweParts[4]);
+
+
+ RSAKeyPair jwk = Factory.makeRSAKeyPairForJWE();
+ JweRsaDeserializer JweRsaDeserializer = jwtAppFactory.jweRsaDeserializer();
+
+ RSAPublicKey publicKey = Factory.makeRSAPublicKeyForJWE();
+ JweRsaSerializer subject = jwtAppFactory.jweRsaSerializer(publicKey);
+
+ byte[] cipherTextWithAuthTag = JweRsaDeserializer.cipherTextWithAuthTag(cipherText, authenticationTag);
+
+ assertThat(cipherTextWithAuthTag.length, is(cipherText.length + authenticationTag.length));
+
+ byte[] actual = subject.extractAuthTag(cipherTextWithAuthTag);
+ assertThat(actual.length, is(authenticationTag.length));
+ assertThat(actual, is(authenticationTag));
+ }
+
+ @Test
+ public void JWEToCompact() throws Exception {
+ JwtAppFactory jwtAppFactory = new JwtAppFactory();
+
+ RSAPublicKey publicKey = Factory.makeRSAPublicKeyForJWE();
+ JweRsaSerializer subject = jwtAppFactory.jweRsaSerializer(publicKey);
+
+ Header header = new Header();
+ header.setEncryptionAlgorithm(Optional.of(EncryptionAlgorithm.AES_GCM_256));
+ header.setAlgorithm(Algorithm.RSAES_OAEP);
+
+ JWE jwe = new JWE();
+ jwe.setHeader(header);
+ jwe.setPayload("Help me, Obi-Wan Kenobi. You're my only hope.".getBytes());
+
+ ByteArrayOutputStream actual = subject.JWEToCompact(jwe);
+
+ // make sure it can be read.
+ RSAKeyPair jwk = Factory.makeRSAKeyPairForJWE();
+ JweRsaDeserializer JweRsaDeserializer = jwtAppFactory.jweRsaDeserializer();
+
+ String compactJWE = actual.toString();
+
+ JWE leia = JweRsaDeserializer.stringToJWE(compactJWE, jwk);
+
+ assertThat(leia, is(notNullValue()));
+ String payload = new String(leia.getPayload());
+ assertThat(payload, is("Help me, Obi-Wan Kenobi. You're my only hope."));
+
+ }
+
+}
\ No newline at end of file
diff --git a/src/test/java/org/rootservices/jwt/jwk/PrivateKeyFactoryTest.java b/src/test/java/org/rootservices/jwt/jwk/PrivateKeyFactoryTest.java
new file mode 100644
index 0000000..4de92d7
--- /dev/null
+++ b/src/test/java/org/rootservices/jwt/jwk/PrivateKeyFactoryTest.java
@@ -0,0 +1,67 @@
+package org.rootservices.jwt.jwk;
+
+import helper.entity.Factory;
+import org.junit.Before;
+import org.junit.Test;
+import org.rootservices.jwt.config.JwtAppFactory;
+import org.rootservices.jwt.entity.jwk.RSAKeyPair;
+import org.rootservices.jwt.jws.signer.factory.rsa.exception.PrivateKeyException;
+
+import java.math.BigInteger;
+import java.security.interfaces.RSAPrivateCrtKey;
+
+import static org.hamcrest.CoreMatchers.notNullValue;
+import static org.hamcrest.core.Is.is;
+import static org.junit.Assert.*;
+
+public class PrivateKeyFactoryTest {
+ private PrivateKeyFactory subject;
+
+ @Before
+ public void setUp() {
+ JwtAppFactory jwtAppFactory = new JwtAppFactory();
+ subject = jwtAppFactory.privateKeyFactory();
+ }
+
+ @Test
+ public void makePrivateKeyShouldMakeRSAPrivateCrtKey() throws Exception {
+ RSAKeyPair jwk = Factory.makeRSAKeyPair();
+ RSAPrivateCrtKey privateKey = subject.makePrivateKey(jwk);
+
+ // expected values
+ BigInteger modulus = new BigInteger("20446702916744654562596343388758805860065209639960173505037453331270270518732245089773723012043203236097095623402044690115755377345254696448759605707788965848889501746836211206270643833663949992536246985362693736387185145424787922241585721992924045675229348655595626434390043002821512765630397723028023792577935108185822753692574221566930937805031155820097146819964920270008811327036286786392793593121762425048860211859763441770446703722015857250621107855398693133264081150697423188751482418465308470313958250757758547155699749157985955379381294962058862159085915015369381046959790476428631998204940879604226680285601");
+ BigInteger publicExponent = new BigInteger("65537");
+ BigInteger privateExponent = new BigInteger("2358310989939619510179986262349936882924652023566213765118606431955566700506538911356936879137503597382515919515633242482643314423192704128296593672966061810149316320617894021822784026407461403384065351821972350784300967610143459484324068427674639688405917977442472804943075439192026107319532117557545079086537982987982522396626690057355718157403493216553255260857777965627529169195827622139772389760130571754834678679842181142252489617665030109445573978012707793010592737640499220015083392425914877847840457278246402760955883376999951199827706285383471150643561410605789710883438795588594095047409018233862167884701");
+ BigInteger primeP = new BigInteger("157377055902447438395586165028960291914931973278777532798470200156035267537359239071829408411909323208574959800537247728959718236884809685233284537349207654661530801859889389455120932077199406250387226339056140578989122526711937239401762061949364440402067108084155200696015505170135950332209194782224750221639");
+ BigInteger primeQ = new BigInteger("129921752567406358990993347540064445018230073402482260994179328573323861908379211274626956543471664997237185298964648133324343327052852264060322088122401124781249085873464824282666514908127141915943024862618996371026577302203267804867959037802770797169483022132210859867700312376409633383772189122488119155159");
+ BigInteger primeExponentP = new BigInteger("4922760648183732070600601771661330216909692924935440167185924139339187000497222028735680413269055839870281941362914961691371628021024152077883230870590287807744299308982303864732867094286567630701646611762288298013758658158894538059014178662376933683632720014228880806671525788467258162275185762295508460173");
+ BigInteger primeExponentQ = new BigInteger("95501022448116849078110281587424883261489167280943290677534750975651978631525094586933777934986404467352856624385049043666431411835209194330560695076194390729082708437497817187133629692908081460223069101908960299950170666285307890683263785145958472051553704139602453015343925544671829327400421727981791235189");
+ BigInteger crtCoefficient = new BigInteger("23545019917990284444784037831882732213707743418529123971725460465297450415859883707284136179135646366158633580054594447195052813412945775933274620822213099556720089770059982091144435545976515508108465724188242241967967709555336331874325396876783846248039429242763646988988076187339075374375350105207330456437");
+
+ assertThat(privateKey, is(notNullValue()));
+ assertThat(privateKey.getAlgorithm(), is("RSA"));
+ assertThat(privateKey.getModulus(), is(modulus));
+ assertThat(privateKey.getPublicExponent(), is(publicExponent));
+ assertThat(privateKey.getPrivateExponent(), is(privateExponent));
+ assertThat(privateKey.getPrimeP(), is(primeP));
+ assertThat(privateKey.getPrimeQ(), is(primeQ));
+ assertThat(privateKey.getPrimeExponentP(), is(primeExponentP));
+ assertThat(privateKey.getPrimeExponentQ(), is(primeExponentQ));
+ assertThat(privateKey.getCrtCoefficient(), is(crtCoefficient));
+ }
+
+ @Test
+ public void makePrivateKeyWhenKeyIsNot512ShouldThrowPrivateKeyException() throws Exception {
+ RSAKeyPair rsaKeyPair = Factory.makeRSAKeyPair();
+ rsaKeyPair.setN(new BigInteger("1"));
+
+ PrivateKeyException actual = null;
+ try {
+ subject.makePrivateKey(rsaKeyPair);
+ } catch (PrivateKeyException e) {
+ actual = e;
+ }
+
+ assertThat(actual, is(notNullValue()));
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/org/rootservices/jwt/jwk/PublicKeyFactoryTest.java b/src/test/java/org/rootservices/jwt/jwk/PublicKeyFactoryTest.java
new file mode 100644
index 0000000..f341e29
--- /dev/null
+++ b/src/test/java/org/rootservices/jwt/jwk/PublicKeyFactoryTest.java
@@ -0,0 +1,58 @@
+package org.rootservices.jwt.jwk;
+
+import helper.entity.Factory;
+import org.junit.Before;
+import org.junit.Test;
+import org.rootservices.jwt.config.JwtAppFactory;
+import org.rootservices.jwt.entity.jwk.RSAPublicKey;
+import org.rootservices.jwt.jws.signer.factory.rsa.exception.PublicKeyException;
+
+import java.math.BigInteger;
+
+import static org.hamcrest.CoreMatchers.notNullValue;
+import static org.hamcrest.core.Is.is;
+import static org.junit.Assert.*;
+
+public class PublicKeyFactoryTest {
+ private JwtAppFactory appFactory;
+ private PublicKeyFactory subject;
+
+ @Before
+ public void setUp() {
+ this.appFactory = new JwtAppFactory();
+ this.subject = appFactory.publicKeyFactory();
+ }
+
+ @Test
+ public void makePublicKeyShouldBeRsaPublicKey() throws PublicKeyException {
+
+ RSAPublicKey publicKey = Factory.makeRSAPublicKey();
+
+ // expected values
+ BigInteger modulus = new BigInteger("20446702916744654562596343388758805860065209639960173505037453331270270518732245089773723012043203236097095623402044690115755377345254696448759605707788965848889501746836211206270643833663949992536246985362693736387185145424787922241585721992924045675229348655595626434390043002821512765630397723028023792577935108185822753692574221566930937805031155820097146819964920270008811327036286786392793593121762425048860211859763441770446703722015857250621107855398693133264081150697423188751482418465308470313958250757758547155699749157985955379381294962058862159085915015369381046959790476428631998204940879604226680285601");
+ BigInteger publicExponent = new BigInteger("65537");
+
+ java.security.interfaces.RSAPublicKey actual = subject.makePublicKey(publicKey);
+
+ assertThat(actual, is(notNullValue()));
+ assertThat(actual.getAlgorithm(), is("RSA"));
+ assertThat(actual.getModulus(), is(modulus));
+ assertThat(actual.getPublicExponent(), is(publicExponent));
+
+ }
+
+ @Test
+ public void makePublicKeyWhenKeyIsNot512ShouldThrowPublicKeyException() throws PublicKeyException {
+ RSAPublicKey publicKey = Factory.makeRSAPublicKey();
+ publicKey.setN(new BigInteger("1"));
+
+ PublicKeyException actual = null;
+ try {
+ subject.makePublicKey(publicKey);
+ } catch (PublicKeyException e) {
+ actual = e;
+ }
+ assertThat(actual, is(notNullValue()));
+ }
+
+}
\ No newline at end of file
diff --git a/src/test/java/org/rootservices/jwt/jws/serialization/SecureJwtSerializerTest.java b/src/test/java/org/rootservices/jwt/jws/serialization/SecureJwtSerializerTest.java
new file mode 100644
index 0000000..e965d1e
--- /dev/null
+++ b/src/test/java/org/rootservices/jwt/jws/serialization/SecureJwtSerializerTest.java
@@ -0,0 +1,80 @@
+package org.rootservices.jwt.jws.serialization;
+
+import helper.entity.Claim;
+import helper.entity.Factory;
+import org.junit.Before;
+import org.junit.Test;
+import org.rootservices.jwt.config.JwtAppFactory;
+import org.rootservices.jwt.entity.jwk.RSAKeyPair;
+import org.rootservices.jwt.entity.jwk.SymmetricKey;
+import org.rootservices.jwt.entity.jwt.header.Algorithm;
+
+import java.io.ByteArrayOutputStream;
+import java.util.Optional;
+
+import static org.hamcrest.core.Is.is;
+import static org.junit.Assert.*;
+
+
+public class SecureJwtSerializerTest {
+ private JwtAppFactory appFactory;
+
+ @Before
+ public void setUp() {
+ appFactory = new JwtAppFactory();
+ }
+
+ @Test
+ public void compactJwtWithSymmetricKeyShouldEncode() throws Exception {
+ SymmetricKey key = Factory.makeSymmetricKey();
+ key.setKeyId(Optional.of("test-key-id"));
+
+ Claim claim = Factory.makeClaim();
+
+ SecureJwtSerializer subject = appFactory.secureJwtSerializer(Algorithm.HS256, key);
+ ByteArrayOutputStream actual = subject.compactJwt(claim);
+
+ assertThat(actual.toString(), is("eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiIsImtpZCI6InRlc3Qta2V5LWlkIn0.eyJpc3MiOiJqb2UiLCJleHAiOjEzMDA4MTkzODAsImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ.YiFm03WWrDAbFn7omROmU2GHACkaGI30xdbWFzyoCNQ"));
+
+ }
+
+ @Test
+ public void compactJwtWithAsymmetricKeyShouldEncode() throws Exception {
+ RSAKeyPair key = Factory.makeRSAKeyPair();
+ key.setKeyId(Optional.of("test-key-id"));
+
+ Claim claim = Factory.makeClaim();
+
+ SecureJwtSerializer subject = appFactory.secureJwtSerializer(Algorithm.RS256, key);
+ ByteArrayOutputStream actual = subject.compactJwt(claim);
+
+ assertThat(actual.toString(), is("eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6InRlc3Qta2V5LWlkIn0.eyJpc3MiOiJqb2UiLCJleHAiOjEzMDA4MTkzODAsImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ.JmMm15IjKsNB18oMqIIaIPHQ8TuqEXNdbmGyEya5Yuoo2Kj132PhiCt2gbPL2i75IH1Zmjvdc7Fm2eb2Db6P6NXezZEHgZG3WVTWJwl11lQnDnj6hTrTbHnL0XUgcFw0vIwthQF6NNjAy2lTMSG0KTH5y_3D-5pt6FM2cyfvK5RwhCom9v2MDWA7fTqR1u5L-_dfcgRlN5rjQ-QYBsk3oaNTMU9MtXtEuG7erun_-VXQJjXGwDRO_kPmzN-wILyoaOr670xpaHVmFLrTakjvfhCkLrB1YwdQV-B6ZFLqTpQpGr7ydEWMyuoiV0Xg71-mJhNHeml_jFMUwm-Lu-d2Og"));
+ }
+
+ @Test
+ public void compactJwtToStringWithSymmetricKeyShouldEncode() throws Exception {
+ SymmetricKey key = Factory.makeSymmetricKey();
+ key.setKeyId(Optional.of("test-key-id"));
+
+ Claim claim = Factory.makeClaim();
+
+ SecureJwtSerializer subject = appFactory.secureJwtSerializer(Algorithm.HS256, key);
+ String actual = subject.compactJwtToString(claim);
+
+ assertThat(actual, is("eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiIsImtpZCI6InRlc3Qta2V5LWlkIn0.eyJpc3MiOiJqb2UiLCJleHAiOjEzMDA4MTkzODAsImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ.YiFm03WWrDAbFn7omROmU2GHACkaGI30xdbWFzyoCNQ"));
+
+ }
+
+ @Test
+ public void compactJwtToStringWithAsymmetricKeyShouldEncode() throws Exception {
+ RSAKeyPair key = Factory.makeRSAKeyPair();
+ key.setKeyId(Optional.of("test-key-id"));
+
+ Claim claim = Factory.makeClaim();
+
+ SecureJwtSerializer subject = appFactory.secureJwtSerializer(Algorithm.RS256, key);
+ String actual = subject.compactJwtToString(claim);
+
+ assertThat(actual, is("eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6InRlc3Qta2V5LWlkIn0.eyJpc3MiOiJqb2UiLCJleHAiOjEzMDA4MTkzODAsImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ.JmMm15IjKsNB18oMqIIaIPHQ8TuqEXNdbmGyEya5Yuoo2Kj132PhiCt2gbPL2i75IH1Zmjvdc7Fm2eb2Db6P6NXezZEHgZG3WVTWJwl11lQnDnj6hTrTbHnL0XUgcFw0vIwthQF6NNjAy2lTMSG0KTH5y_3D-5pt6FM2cyfvK5RwhCom9v2MDWA7fTqR1u5L-_dfcgRlN5rjQ-QYBsk3oaNTMU9MtXtEuG7erun_-VXQJjXGwDRO_kPmzN-wILyoaOr670xpaHVmFLrTakjvfhCkLrB1YwdQV-B6ZFLqTpQpGr7ydEWMyuoiV0Xg71-mJhNHeml_jFMUwm-Lu-d2Og"));
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/org/rootservices/jwt/signature/signer/MacSignerTest.java b/src/test/java/org/rootservices/jwt/jws/signer/MacSignerTest.java
similarity index 81%
rename from src/test/java/org/rootservices/jwt/signature/signer/MacSignerTest.java
rename to src/test/java/org/rootservices/jwt/jws/signer/MacSignerTest.java
index 29d5d95..cd4f480 100644
--- a/src/test/java/org/rootservices/jwt/signature/signer/MacSignerTest.java
+++ b/src/test/java/org/rootservices/jwt/jws/signer/MacSignerTest.java
@@ -1,19 +1,19 @@
-package org.rootservices.jwt.signature.signer;
+package org.rootservices.jwt.jws.signer;
import helper.entity.Claim;
import helper.entity.Factory;
import org.junit.Before;
import org.junit.Test;
-import org.rootservices.jwt.config.AppFactory;
+import org.rootservices.jwt.config.JwtAppFactory;
import org.rootservices.jwt.entity.jwk.SymmetricKey;
import org.rootservices.jwt.entity.jwt.JsonWebToken;
import org.rootservices.jwt.entity.jwt.header.Algorithm;
import org.rootservices.jwt.entity.jwt.header.Header;
import org.rootservices.jwt.entity.jwt.header.TokenType;
-import org.rootservices.jwt.serializer.exception.JwtToJsonException;
-import org.rootservices.jwt.signature.signer.factory.exception.InvalidAlgorithmException;
-import org.rootservices.jwt.signature.signer.factory.exception.InvalidJsonWebKeyException;
+import org.rootservices.jwt.serialization.exception.JwtToJsonException;
+import org.rootservices.jwt.jws.signer.factory.exception.InvalidAlgorithmException;
+import org.rootservices.jwt.jws.signer.factory.exception.InvalidJsonWebKeyException;
import java.util.Optional;
@@ -30,7 +30,7 @@ public class MacSignerTest {
public void setUp() throws InvalidAlgorithmException, InvalidJsonWebKeyException {
SymmetricKey key = Factory.makeSymmetricKey();
- AppFactory appFactory = new AppFactory();
+ JwtAppFactory appFactory = new JwtAppFactory();
subject = appFactory.signerFactory().makeSigner(Algorithm.HS256, key);
}
@@ -59,8 +59,8 @@ public void shouldSignJwtCorrectly() throws JwtToJsonException {
JsonWebToken jwt = new JsonWebToken(header, claim);
- String actual = subject.run(jwt);
- assertThat(actual, is("lliDzOlRAdGUCfCHCPx_uisb6ZfZ1LRQa0OJLeYTTpY"));
+ byte[] actual = subject.run(jwt);
+ assertThat(actual, is("lliDzOlRAdGUCfCHCPx_uisb6ZfZ1LRQa0OJLeYTTpY".getBytes()));
}
/**
@@ -75,8 +75,8 @@ public void shouldSignBytesCorrectly() {
String input = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9." +
"eyJpc3MiOiJqb2UiLCJleHAiOjEzMDA4MTkzODAsImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ";
- String actual = subject.run(input.getBytes());
+ byte[] actual = subject.run(input.getBytes());
- assertThat(actual, is("lliDzOlRAdGUCfCHCPx_uisb6ZfZ1LRQa0OJLeYTTpY"));
+ assertThat(actual, is("lliDzOlRAdGUCfCHCPx_uisb6ZfZ1LRQa0OJLeYTTpY".getBytes()));
}
}
\ No newline at end of file
diff --git a/src/test/java/org/rootservices/jwt/signature/signer/RSASignerTest.java b/src/test/java/org/rootservices/jwt/jws/signer/RSASignerTest.java
similarity index 81%
rename from src/test/java/org/rootservices/jwt/signature/signer/RSASignerTest.java
rename to src/test/java/org/rootservices/jwt/jws/signer/RSASignerTest.java
index 7528ee5..682746f 100644
--- a/src/test/java/org/rootservices/jwt/signature/signer/RSASignerTest.java
+++ b/src/test/java/org/rootservices/jwt/jws/signer/RSASignerTest.java
@@ -1,15 +1,16 @@
-package org.rootservices.jwt.signature.signer;
+package org.rootservices.jwt.jws.signer;
import helper.entity.Factory;
import org.junit.Before;
import org.junit.Test;
-import org.rootservices.jwt.config.AppFactory;
+import org.rootservices.jwt.config.JwtAppFactory;
import org.rootservices.jwt.entity.jwk.RSAKeyPair;
import org.rootservices.jwt.entity.jwt.JsonWebToken;
import org.rootservices.jwt.entity.jwt.header.Algorithm;
-import org.rootservices.jwt.serializer.exception.JwtToJsonException;
-import org.rootservices.jwt.signature.signer.factory.exception.InvalidAlgorithmException;
-import org.rootservices.jwt.signature.signer.factory.exception.InvalidJsonWebKeyException;
+import org.rootservices.jwt.entity.jwt.header.TokenType;
+import org.rootservices.jwt.serialization.exception.JwtToJsonException;
+import org.rootservices.jwt.jws.signer.factory.exception.InvalidAlgorithmException;
+import org.rootservices.jwt.jws.signer.factory.exception.InvalidJsonWebKeyException;
import java.util.Optional;
@@ -22,11 +23,11 @@
* Created by tommackenzie on 11/12/15.
*/
public class RSASignerTest {
- private AppFactory appFactory;
+ private JwtAppFactory appFactory;
@Before
public void setUp() {
- this.appFactory = new AppFactory();
+ this.appFactory = new JwtAppFactory();
}
/**
@@ -52,10 +53,10 @@ public void signBytesWithRS256ShouldSignCorrectly() throws Exception {
98, 83, 57, 112, 99, 49, 57, 121, 98, 50, 57, 48, 73, 106, 112, 48,
99, 110, 86, 108, 102, 81};
- String actual = subject.run(signInput);
+ byte[] actual = subject.run(signInput);
assertThat(actual, is(notNullValue()));
- assertThat(actual, is(expected));
+ assertThat(actual, is(expected.getBytes()));
}
/**
@@ -74,11 +75,11 @@ public void signTokenWithRS256ShouldSignCorrectly() throws InvalidAlgorithmExcep
RSAKeyPair jwk = Factory.makeRSAKeyPair();
Signer subject = appFactory.signerFactory().makeSigner(Algorithm.RS256, jwk);
- JsonWebToken jwt = Factory.makeToken(Algorithm.RS256, Optional.empty());
+ JsonWebToken jwt = Factory.makeToken(Algorithm.RS256, Optional.empty());
- String actual = subject.run(jwt);
+ byte[] actual = subject.run(jwt);
assertThat(actual, is(notNullValue()));
- assertThat(actual, is(expected));
+ assertThat(actual, is(expected.getBytes()));
}
}
\ No newline at end of file
diff --git a/src/test/java/org/rootservices/jwt/signature/signer/factory/MacFactoryTest.java b/src/test/java/org/rootservices/jwt/jws/signer/factory/MacFactoryTest.java
similarity index 72%
rename from src/test/java/org/rootservices/jwt/signature/signer/factory/MacFactoryTest.java
rename to src/test/java/org/rootservices/jwt/jws/signer/factory/MacFactoryTest.java
index a9b4628..4fcab9a 100644
--- a/src/test/java/org/rootservices/jwt/signature/signer/factory/MacFactoryTest.java
+++ b/src/test/java/org/rootservices/jwt/jws/signer/factory/MacFactoryTest.java
@@ -1,15 +1,15 @@
-package org.rootservices.jwt.signature.signer.factory;
+package org.rootservices.jwt.jws.signer.factory;
import helper.entity.Factory;
import org.junit.Before;
import org.junit.Test;
-import org.rootservices.jwt.config.AppFactory;
+import org.rootservices.jwt.config.JwtAppFactory;
import org.rootservices.jwt.entity.jwk.SymmetricKey;
-import org.rootservices.jwt.signature.signer.SignAlgorithm;
-import org.rootservices.jwt.signature.signer.factory.exception.InvalidAlgorithmException;
-import org.rootservices.jwt.signature.signer.factory.hmac.MacFactory;
-import org.rootservices.jwt.signature.signer.factory.hmac.exception.SecurityKeyException;
+import org.rootservices.jwt.jws.signer.SignAlgorithm;
+import org.rootservices.jwt.jws.signer.factory.exception.InvalidAlgorithmException;
+import org.rootservices.jwt.jws.signer.factory.hmac.MacFactory;
+import org.rootservices.jwt.jws.signer.factory.hmac.exception.SecurityKeyException;
import javax.crypto.Mac;
import java.util.Base64;
@@ -24,7 +24,7 @@ public class MacFactoryTest {
@Before
public void setUp() {
- AppFactory appFactory = new AppFactory();
+ JwtAppFactory appFactory = new JwtAppFactory();
subject = appFactory.macFactory();
}
diff --git a/src/test/java/org/rootservices/jwt/signature/signer/factory/PrivateKeySignatureFactoryTest.java b/src/test/java/org/rootservices/jwt/jws/signer/factory/PrivateKeySignatureFactoryTest.java
similarity index 85%
rename from src/test/java/org/rootservices/jwt/signature/signer/factory/PrivateKeySignatureFactoryTest.java
rename to src/test/java/org/rootservices/jwt/jws/signer/factory/PrivateKeySignatureFactoryTest.java
index 2e74f02..9654ef4 100644
--- a/src/test/java/org/rootservices/jwt/signature/signer/factory/PrivateKeySignatureFactoryTest.java
+++ b/src/test/java/org/rootservices/jwt/jws/signer/factory/PrivateKeySignatureFactoryTest.java
@@ -1,15 +1,14 @@
-package org.rootservices.jwt.signature.signer.factory;
+package org.rootservices.jwt.jws.signer.factory;
import helper.entity.Factory;
import org.junit.Before;
import org.junit.Test;
-import org.rootservices.jwt.config.AppFactory;
+import org.rootservices.jwt.config.JwtAppFactory;
import org.rootservices.jwt.entity.jwk.RSAKeyPair;
-import org.rootservices.jwt.signature.signer.SignAlgorithm;
-import org.rootservices.jwt.signature.signer.factory.exception.InvalidAlgorithmException;
-import org.rootservices.jwt.signature.signer.factory.rsa.PrivateKeySignatureFactory;
-import org.rootservices.jwt.signature.signer.factory.rsa.exception.PrivateKeyException;
-import org.rootservices.jwt.signature.signer.factory.rsa.exception.RSAPrivateKeyException;
+import org.rootservices.jwt.jws.signer.SignAlgorithm;
+import org.rootservices.jwt.jws.signer.factory.rsa.PrivateKeySignatureFactory;
+import org.rootservices.jwt.jws.signer.factory.rsa.exception.PrivateKeyException;
+
import java.math.BigInteger;
import java.security.*;
@@ -28,7 +27,7 @@ public class PrivateKeySignatureFactoryTest {
@Before
public void setUp() {
- AppFactory appFactory = new AppFactory();
+ JwtAppFactory appFactory = new JwtAppFactory();
this.subject = appFactory.privateKeySignatureFactory();
}
@@ -59,16 +58,23 @@ public void makePrivateKeyShouldMakeRSAPrivateCrtKey() throws Exception {
assertThat(privateKey.getCrtCoefficient(), is(crtCoefficient));
}
- @Test(expected = PrivateKeyException.class)
+ @Test
public void makePrivateKeyWhenKeyIsNot512ShouldThrowPrivateKeyException() throws Exception {
RSAKeyPair rsaKeyPair = Factory.makeRSAKeyPair();
- rsaKeyPair.setN(new BigInteger("12"));
+ rsaKeyPair.setN(new BigInteger("1"));
+
+ PrivateKeyException actual = null;
+ try {
+ subject.makePrivateKey(rsaKeyPair);
+ } catch (PrivateKeyException e) {
+ actual = e;
+ }
- subject.makePrivateKey(rsaKeyPair);
+ assertThat(actual, is(notNullValue()));
}
@Test
- public void testMakeSignatureShouldBeRS256() throws InvalidAlgorithmException, PrivateKeyException, RSAPrivateKeyException {
+ public void testMakeSignatureShouldBeRS256() throws Exception {
RSAKeyPair jwk = Factory.makeRSAKeyPair();
Signature signature = subject.makeSignature(SignAlgorithm.RS256, jwk);
diff --git a/src/test/java/org/rootservices/jwt/signature/signer/factory/PublicKeySignatureFactoryTest.java b/src/test/java/org/rootservices/jwt/jws/signer/factory/PublicKeySignatureFactoryTest.java
similarity index 68%
rename from src/test/java/org/rootservices/jwt/signature/signer/factory/PublicKeySignatureFactoryTest.java
rename to src/test/java/org/rootservices/jwt/jws/signer/factory/PublicKeySignatureFactoryTest.java
index 946afd7..0fea11a 100644
--- a/src/test/java/org/rootservices/jwt/signature/signer/factory/PublicKeySignatureFactoryTest.java
+++ b/src/test/java/org/rootservices/jwt/jws/signer/factory/PublicKeySignatureFactoryTest.java
@@ -1,15 +1,16 @@
-package org.rootservices.jwt.signature.signer.factory;
+package org.rootservices.jwt.jws.signer.factory;
import helper.entity.Factory;
import org.junit.Before;
+import org.junit.Ignore;
import org.junit.Test;
-import org.rootservices.jwt.config.AppFactory;
+import org.rootservices.jwt.config.JwtAppFactory;
import org.rootservices.jwt.entity.jwk.RSAPublicKey;
-import org.rootservices.jwt.signature.signer.SignAlgorithm;
-import org.rootservices.jwt.signature.signer.factory.exception.InvalidAlgorithmException;
-import org.rootservices.jwt.signature.signer.factory.rsa.PublicKeySignatureFactory;
-import org.rootservices.jwt.signature.signer.factory.rsa.exception.PublicKeyException;
-import org.rootservices.jwt.signature.signer.factory.rsa.exception.RSAPublicKeyException;
+import org.rootservices.jwt.jws.signer.SignAlgorithm;
+import org.rootservices.jwt.jws.signer.factory.exception.InvalidAlgorithmException;
+import org.rootservices.jwt.jws.signer.factory.rsa.PublicKeySignatureFactory;
+import org.rootservices.jwt.jws.signer.factory.rsa.exception.PublicKeyException;
+import org.rootservices.jwt.jws.signer.factory.rsa.exception.RSAPublicKeyException;
import java.math.BigInteger;
import java.security.Signature;
@@ -22,17 +23,17 @@
* Created by tommackenzie on 11/14/15.
*/
public class PublicKeySignatureFactoryTest {
- private AppFactory appFactory;
+ private JwtAppFactory appFactory;
private PublicKeySignatureFactory subject;
@Before
public void setUp() {
- this.appFactory = new AppFactory();
+ this.appFactory = new JwtAppFactory();
this.subject = appFactory.publicKeySignatureFactory();
}
@Test
- public void makePublicKeyShouldBeRsaPublicKey() throws PublicKeyException {
+ public void makePublicKeyShouldBeRsaPublicKey() throws Exception {
RSAPublicKey publicKey = Factory.makeRSAPublicKey();
@@ -49,16 +50,22 @@ public void makePublicKeyShouldBeRsaPublicKey() throws PublicKeyException {
}
- @Test(expected = PublicKeyException.class)
- public void makePublicKeyWhenKeyIsNot512ShouldThrowPublicKeyException() throws PublicKeyException {
+ @Test
+ public void makePublicKeyWhenKeyIsNot512ShouldThrowPublicKeyException() throws Exception {
RSAPublicKey publicKey = Factory.makeRSAPublicKey();
publicKey.setN(new BigInteger("1"));
- subject.makePublicKey(publicKey);
+ PublicKeyException actual = null;
+ try {
+ subject.makePublicKey(publicKey);
+ } catch (PublicKeyException e) {
+ actual = e;
+ }
+ assertThat(actual, is(notNullValue()));
}
- @Test
- public void testMakeSignatureShouldBeRS256() throws InvalidAlgorithmException, PublicKeyException, RSAPublicKeyException {
+ @Test
+ public void testMakeSignatureShouldBeRS256() throws Exception {
RSAPublicKey publicKey = Factory.makeRSAPublicKey();
Signature signature = subject.makeSignature(SignAlgorithm.RS256, publicKey);
diff --git a/src/test/java/org/rootservices/jwt/signature/signer/factory/SignerFactoryImplTest.java b/src/test/java/org/rootservices/jwt/jws/signer/factory/SignerFactoryImplTest.java
similarity index 69%
rename from src/test/java/org/rootservices/jwt/signature/signer/factory/SignerFactoryImplTest.java
rename to src/test/java/org/rootservices/jwt/jws/signer/factory/SignerFactoryImplTest.java
index 46ea893..b8018ef 100644
--- a/src/test/java/org/rootservices/jwt/signature/signer/factory/SignerFactoryImplTest.java
+++ b/src/test/java/org/rootservices/jwt/jws/signer/factory/SignerFactoryImplTest.java
@@ -1,17 +1,17 @@
-package org.rootservices.jwt.signature.signer.factory;
+package org.rootservices.jwt.jws.signer.factory;
import helper.entity.Factory;
import org.junit.Before;
import org.junit.Test;
-import org.rootservices.jwt.config.AppFactory;
+import org.rootservices.jwt.config.JwtAppFactory;
import org.rootservices.jwt.entity.jwk.RSAKeyPair;
import org.rootservices.jwt.entity.jwk.SymmetricKey;
import org.rootservices.jwt.entity.jwt.header.Algorithm;
-import org.rootservices.jwt.signature.signer.MacSigner;
-import org.rootservices.jwt.signature.signer.RSASigner;
-import org.rootservices.jwt.signature.signer.Signer;
-import org.rootservices.jwt.signature.signer.factory.exception.InvalidAlgorithmException;
-import org.rootservices.jwt.signature.signer.factory.exception.InvalidJsonWebKeyException;
+import org.rootservices.jwt.jws.signer.MacSigner;
+import org.rootservices.jwt.jws.signer.RSASigner;
+import org.rootservices.jwt.jws.signer.Signer;
+import org.rootservices.jwt.jws.signer.factory.exception.InvalidAlgorithmException;
+import org.rootservices.jwt.jws.signer.factory.exception.InvalidJsonWebKeyException;
import static org.hamcrest.core.IsInstanceOf.instanceOf;
import static org.junit.Assert.*;
@@ -24,7 +24,7 @@ public class SignerFactoryImplTest {
@Before
public void setUp() throws Exception {
- AppFactory appFactory = new AppFactory();
+ JwtAppFactory appFactory = new JwtAppFactory();
subject = appFactory.signerFactory();
}
diff --git a/src/test/java/org/rootservices/jwt/signature/verifier/VerifyMacSignatureTest.java b/src/test/java/org/rootservices/jwt/jws/verifier/VerifyMacSignatureTest.java
similarity index 61%
rename from src/test/java/org/rootservices/jwt/signature/verifier/VerifyMacSignatureTest.java
rename to src/test/java/org/rootservices/jwt/jws/verifier/VerifyMacSignatureTest.java
index d1d1a59..b0c1cbc 100644
--- a/src/test/java/org/rootservices/jwt/signature/verifier/VerifyMacSignatureTest.java
+++ b/src/test/java/org/rootservices/jwt/jws/verifier/VerifyMacSignatureTest.java
@@ -1,37 +1,33 @@
-package org.rootservices.jwt.signature.verifier;
+package org.rootservices.jwt.jws.verifier;
import helper.entity.Claim;
import helper.entity.Factory;
import org.junit.Before;
import org.junit.Test;
-import org.rootservices.jwt.config.AppFactory;
+import org.rootservices.jwt.config.JwtAppFactory;
import org.rootservices.jwt.entity.jwk.SymmetricKey;
import org.rootservices.jwt.entity.jwt.JsonWebToken;
import org.rootservices.jwt.entity.jwt.header.Algorithm;
-import org.rootservices.jwt.serializer.JWTSerializer;
-import org.rootservices.jwt.serializer.exception.JsonToJwtException;
-import org.rootservices.jwt.signature.signer.factory.exception.InvalidAlgorithmException;
-import org.rootservices.jwt.signature.signer.factory.exception.InvalidJsonWebKeyException;
+import org.rootservices.jwt.serialization.JwtSerde;
+import org.rootservices.jwt.serialization.exception.JsonToJwtException;
import static org.junit.Assert.assertTrue;
-/**
- * Created by tommackenzie on 8/30/15.
- */
+
public class VerifyMacSignatureTest {
- private AppFactory appFactory;
- private JWTSerializer jwtSerializer;
+ private JwtAppFactory appFactory;
+ private JwtSerde jwtSerde;
@Before
public void setUp() {
- appFactory = new AppFactory();
- jwtSerializer = appFactory.jwtSerializer();
+ appFactory = new JwtAppFactory();
+ jwtSerde = appFactory.jwtSerde();
}
@Test
- public void verifySecureJwtWithJwtShouldBeTrue() throws InvalidAlgorithmException, InvalidJsonWebKeyException {
+ public void verifySecureJwtWithJwtShouldBeTrue() throws Exception {
String jwtAsText = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9." +
"eyJpc3MiOiJqb2UiLCJleHAiOjEzMDA4MTkzODAsImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ." +
@@ -39,7 +35,7 @@ public void verifySecureJwtWithJwtShouldBeTrue() throws InvalidAlgorithmExceptio
JsonWebToken jwt = null;
try {
- jwt = jwtSerializer.stringToJwt(jwtAsText, Claim.class);
+ jwt = jwtSerde.stringToJwt(jwtAsText, Claim.class);
} catch (JsonToJwtException e) {
e.printStackTrace();
}
@@ -53,14 +49,14 @@ public void verifySecureJwtWithJwtShouldBeTrue() throws InvalidAlgorithmExceptio
}
@Test
- public void verifyUnsecureJwtWithJwtShouldBeTrue() throws InvalidAlgorithmException, InvalidJsonWebKeyException {
+ public void verifyUnsecureJwtWithJwtShouldBeTrue() throws Exception {
String jwtAsText = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9." +
"eyJpc3MiOiJqb2UiLCJleHAiOjEzMDA4MTkzODAsImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ.";
JsonWebToken jwt = null;
try {
- jwt = jwtSerializer.stringToJwt(jwtAsText, Claim.class);
+ jwt = jwtSerde.stringToJwt(jwtAsText, Claim.class);
} catch (JsonToJwtException e) {
e.printStackTrace();
}
diff --git a/src/test/java/org/rootservices/jwt/signature/verifier/VerifyRsaSignatureTest.java b/src/test/java/org/rootservices/jwt/jws/verifier/VerifyRsaSignatureTest.java
similarity index 82%
rename from src/test/java/org/rootservices/jwt/signature/verifier/VerifyRsaSignatureTest.java
rename to src/test/java/org/rootservices/jwt/jws/verifier/VerifyRsaSignatureTest.java
index a2877ec..77ed0e4 100644
--- a/src/test/java/org/rootservices/jwt/signature/verifier/VerifyRsaSignatureTest.java
+++ b/src/test/java/org/rootservices/jwt/jws/verifier/VerifyRsaSignatureTest.java
@@ -1,14 +1,14 @@
-package org.rootservices.jwt.signature.verifier;
+package org.rootservices.jwt.jws.verifier;
import helper.entity.Claim;
import helper.entity.Factory;
import org.junit.Before;
import org.junit.Test;
-import org.rootservices.jwt.config.AppFactory;
+import org.rootservices.jwt.config.JwtAppFactory;
import org.rootservices.jwt.entity.jwk.RSAPublicKey;
import org.rootservices.jwt.entity.jwt.JsonWebToken;
import org.rootservices.jwt.entity.jwt.header.Algorithm;
-import org.rootservices.jwt.serializer.JWTSerializer;
+import org.rootservices.jwt.serialization.JwtSerde;
import static org.hamcrest.core.Is.is;
import static org.junit.Assert.*;
@@ -17,17 +17,17 @@
* Created by tommackenzie on 11/14/15.
*/
public class VerifyRsaSignatureTest {
- private AppFactory appFactory;
+ private JwtAppFactory appFactory;
@Before
public void setUp() {
- this.appFactory = new AppFactory();
+ this.appFactory = new JwtAppFactory();
}
@Test
public void testRunShouldBeTrue() throws Exception {
String jwtAsText = "eyJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ.cC4hiUPoj9Eetdgtv3hF80EGrhuB__dzERat0XF9g2VtQgr9PJbu3XOiZj5RZmh7AAuHIm4Bh-0Qc_lF5YKt_O8W2Fp5jujGbds9uJdbF9CUAr7t1dnZcAcQjbKBYNX4BAynRFdiuB--f_nZLgrnbyTyWzO75vRK5h6xBArLIARNPvkSjtQBMHlb1L07Qe7K0GarZRmB_eSN9383LcOLn6_dO--xi12jzDwusC-eOkHWEsqtFZESc6BfI7noOPqvhJ1phCnvWh6IeYI2w9QOYEUipUTI8np6LbgGY9Fs98rqVt5AXLIhWkWywlVmtVrBp0igcN_IoypGlUPQGe77Rw";
- JWTSerializer serializer = appFactory.jwtSerializer();
+ JwtSerde serializer = appFactory.jwtSerde();
JsonWebToken jwt = serializer.stringToJwt(jwtAsText, Claim.class);
RSAPublicKey publicKey = Factory.makeRSAPublicKey();
diff --git a/src/test/java/org/rootservices/jwt/signature/verifier/factory/VerifySignatureFactoryImplTest.java b/src/test/java/org/rootservices/jwt/jws/verifier/factory/VerifySignatureFactoryImplTest.java
similarity index 77%
rename from src/test/java/org/rootservices/jwt/signature/verifier/factory/VerifySignatureFactoryImplTest.java
rename to src/test/java/org/rootservices/jwt/jws/verifier/factory/VerifySignatureFactoryImplTest.java
index 2253eb2..ffba961 100644
--- a/src/test/java/org/rootservices/jwt/signature/verifier/factory/VerifySignatureFactoryImplTest.java
+++ b/src/test/java/org/rootservices/jwt/jws/verifier/factory/VerifySignatureFactoryImplTest.java
@@ -1,15 +1,15 @@
-package org.rootservices.jwt.signature.verifier.factory;
+package org.rootservices.jwt.jws.verifier.factory;
import helper.entity.Factory;
import org.junit.Before;
import org.junit.Test;
-import org.rootservices.jwt.config.AppFactory;
+import org.rootservices.jwt.config.JwtAppFactory;
import org.rootservices.jwt.entity.jwk.RSAPublicKey;
import org.rootservices.jwt.entity.jwk.SymmetricKey;
import org.rootservices.jwt.entity.jwt.header.Algorithm;
-import org.rootservices.jwt.signature.verifier.VerifyMacSignature;
-import org.rootservices.jwt.signature.verifier.VerifyRsaSignature;
-import org.rootservices.jwt.signature.verifier.VerifySignature;
+import org.rootservices.jwt.jws.verifier.VerifyMacSignature;
+import org.rootservices.jwt.jws.verifier.VerifyRsaSignature;
+import org.rootservices.jwt.jws.verifier.VerifySignature;
import static org.hamcrest.CoreMatchers.instanceOf;
import static org.hamcrest.core.Is.is;
@@ -19,11 +19,11 @@
* Created by tommackenzie on 11/15/15.
*/
public class VerifySignatureFactoryImplTest {
- private AppFactory appFactory;
+ private JwtAppFactory appFactory;
@Before
public void setUp() {
- this.appFactory = new AppFactory();
+ this.appFactory = new JwtAppFactory();
}
@Test
diff --git a/src/test/java/org/rootservices/jwt/serialization/HeaderDeserializerTest.java b/src/test/java/org/rootservices/jwt/serialization/HeaderDeserializerTest.java
new file mode 100644
index 0000000..5105c6f
--- /dev/null
+++ b/src/test/java/org/rootservices/jwt/serialization/HeaderDeserializerTest.java
@@ -0,0 +1,40 @@
+package org.rootservices.jwt.serialization;
+
+import helper.entity.Factory;
+import org.junit.Before;
+import org.junit.Test;
+import org.rootservices.jwt.config.JwtAppFactory;
+import org.rootservices.jwt.entity.jwe.EncryptionAlgorithm;
+import org.rootservices.jwt.entity.jwt.header.Algorithm;
+import org.rootservices.jwt.entity.jwt.header.AlgorithmFor;
+import org.rootservices.jwt.entity.jwt.header.Header;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.notNullValue;
+import static org.junit.Assert.*;
+
+public class HeaderDeserializerTest {
+ private HeaderDeserializer subject;
+
+ @Before
+ public void setUp() {
+ JwtAppFactory jwtAppFactory = new JwtAppFactory();
+ subject = jwtAppFactory.headerDeserializer();
+ }
+
+ @Test
+ public void toHeader() throws Exception {
+ // https://tools.ietf.org/html/rfc7516#section-3.3
+ String compactJWE = Factory.compactJWE();
+ Header actual = subject.toHeader(compactJWE);
+
+ assertThat(actual, is(notNullValue()));
+
+ assertThat(actual.getKeyId().isPresent(), is(false));
+ assertThat(actual.getType().isPresent(), is(false));
+ assertThat(actual.getAlgorithm(), is(Algorithm.RSAES_OAEP));
+ assertThat(actual.getAlgorithm().getAlgorithmFor(), is(AlgorithmFor.JWE));
+ assertThat(actual.getEncryptionAlgorithm().isPresent(), is(true));
+ assertThat(actual.getEncryptionAlgorithm().get(), is(EncryptionAlgorithm.AES_GCM_256));
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/org/rootservices/jwt/serializer/JWTSerializerTest.java b/src/test/java/org/rootservices/jwt/serialization/JwtSerdeTest.java
similarity index 79%
rename from src/test/java/org/rootservices/jwt/serializer/JWTSerializerTest.java
rename to src/test/java/org/rootservices/jwt/serialization/JwtSerdeTest.java
index c89849c..d57ea63 100644
--- a/src/test/java/org/rootservices/jwt/serializer/JWTSerializerTest.java
+++ b/src/test/java/org/rootservices/jwt/serialization/JwtSerdeTest.java
@@ -1,21 +1,17 @@
-package org.rootservices.jwt.serializer;
+package org.rootservices.jwt.serialization;
import helper.entity.Claim;
import helper.entity.Factory;
-import org.junit.Before;
import org.junit.Test;
import org.rootservices.jwt.factory.SecureJwtFactory;
import org.rootservices.jwt.factory.UnSecureJwtFactory;
-import org.rootservices.jwt.config.AppFactory;
+import org.rootservices.jwt.config.JwtAppFactory;
import org.rootservices.jwt.entity.jwk.SymmetricKey;
import org.rootservices.jwt.entity.jwt.JsonWebToken;
import org.rootservices.jwt.entity.jwt.header.Algorithm;
import org.rootservices.jwt.entity.jwt.header.TokenType;
-import org.rootservices.jwt.serializer.exception.JsonToJwtException;
-import org.rootservices.jwt.serializer.exception.JwtToJsonException;
-import org.rootservices.jwt.signature.signer.factory.exception.InvalidAlgorithmException;
-import org.rootservices.jwt.signature.signer.factory.exception.InvalidJsonWebKeyException;
+import java.io.ByteArrayOutputStream;
import java.util.Optional;
import static org.hamcrest.CoreMatchers.instanceOf;
@@ -25,39 +21,32 @@
import static org.junit.Assert.assertThat;
-/**
- * Created by tommackenzie on 8/13/15.
- */
-public class JWTSerializerTest {
- private AppFactory appFactory;
+public class JwtSerdeTest {
- @Before
- public void setUp() throws InvalidAlgorithmException, InvalidJsonWebKeyException {
- appFactory = new AppFactory();
- }
+ private static JwtAppFactory appFactory = new JwtAppFactory();
@Test
- public void UnsecuredJwtToStringShouldBeValidJWT() throws JwtToJsonException {
+ public void UnsecuredJwtToStringShouldBeValidJWT() throws Exception {
UnSecureJwtFactory unsecureTokenBuilder = appFactory.unsecureJwtFactory();
- JWTSerializer subject = appFactory.jwtSerializer();
+ JwtSerde subject = appFactory.jwtSerde();
String expectedJwt = "eyJhbGciOiJub25lIn0.eyJpc3MiOiJqb2UiLCJleHAiOjEzMDA4MTkzODAsImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ.";
Claim claim = Factory.makeClaim();
JsonWebToken tokenToMarshal = unsecureTokenBuilder.makeJwt(claim);
- String actual = subject.jwtToString(tokenToMarshal);
- assertThat(actual, is(expectedJwt));
+ ByteArrayOutputStream actual = subject.compactJwt(tokenToMarshal);
+ assertThat(actual.toString(), is(expectedJwt));
}
@Test
- public void SecuredJwtToStringShouldBeValid() throws JwtToJsonException, InvalidAlgorithmException, InvalidJsonWebKeyException {
+ public void SecuredJwtToStringShouldBeValid() throws Exception {
SymmetricKey key = Factory.makeSymmetricKey();
SecureJwtFactory secureJwtFactory = appFactory.secureJwtFactory(Algorithm.HS256, key);
- JWTSerializer subject = appFactory.jwtSerializer();
+ JwtSerde subject = appFactory.jwtSerde();
String signature = "lliDzOlRAdGUCfCHCPx_uisb6ZfZ1LRQa0OJLeYTTpY";
@@ -68,18 +57,18 @@ public void SecuredJwtToStringShouldBeValid() throws JwtToJsonException, Invalid
Claim claim = Factory.makeClaim();
JsonWebToken tokenToMarshal = secureJwtFactory.makeJwt(claim);
- String actual = subject.jwtToString(tokenToMarshal);
+ ByteArrayOutputStream actual = subject.compactJwt(tokenToMarshal);
- assertThat(actual, is(expectedJwt));
+ assertThat(actual.toString(), is(expectedJwt));
}
@Test
- public void SecuredJwtWithKeyIdToStringShouldBeValid() throws JwtToJsonException, InvalidAlgorithmException, InvalidJsonWebKeyException {
+ public void SecuredJwtWithKeyIdToStringShouldBeValid() throws Exception {
SymmetricKey key = Factory.makeSymmetricKey();
key.setKeyId(Optional.of("test-key-id"));
SecureJwtFactory secureJwtFactory = appFactory.secureJwtFactory(Algorithm.HS256, key);
- JWTSerializer subject = appFactory.jwtSerializer();
+ JwtSerde subject = appFactory.jwtSerde();
String signature = "YiFm03WWrDAbFn7omROmU2GHACkaGI30xdbWFzyoCNQ";
@@ -90,15 +79,15 @@ public void SecuredJwtWithKeyIdToStringShouldBeValid() throws JwtToJsonException
Claim claim = Factory.makeClaim();
JsonWebToken tokenToMarshal = secureJwtFactory.makeJwt(claim);
- String actual = subject.jwtToString(tokenToMarshal);
+ ByteArrayOutputStream actual = subject.compactJwt(tokenToMarshal);
- assertThat(actual, is(expectedJwt));
+ assertThat(actual.toString(), is(expectedJwt));
}
@Test
- public void stringToJwtShouldBeUnsecuredJwt() throws JsonToJwtException {
+ public void stringToJwtShouldBeUnsecuredJwt() throws Exception {
- JWTSerializer subject = appFactory.jwtSerializer();
+ JwtSerde subject = appFactory.jwtSerde();
String jwtAsText = "eyJhbGciOiJub25lIn0=." +
"eyJpc3MiOiJqb2UiLCJleHAiOjEzMDA4MTkzODAsImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ==.";
@@ -129,9 +118,9 @@ public void stringToJwtShouldBeUnsecuredJwt() throws JsonToJwtException {
}
@Test
- public void stringToJwtShouldBeSecuredJwt() throws JsonToJwtException {
+ public void stringToJwtShouldBeSecuredJwt() throws Exception {
- JWTSerializer subject = appFactory.jwtSerializer();
+ JwtSerde subject = appFactory.jwtSerde();
String signature = "lliDzOlRAdGUCfCHCPx_uisb6ZfZ1LRQa0OJLeYTTpY";
@@ -164,16 +153,16 @@ public void stringToJwtShouldBeSecuredJwt() throws JsonToJwtException {
assertThat(actual.getClaims().getJwtId().isPresent(), is(false));
assertThat(actual.getSignature().isPresent(), is(true));
- assertThat(actual.getSignature().get(), is(signature));
+ assertThat(actual.getSignature().get(), is(signature.getBytes()));
assertThat(actual.getJwt().isPresent(), is(true));
assertThat(actual.getJwt().get(), is(jwtAsText));
}
@Test
- public void stringToJwtShouldBeSecuredJwtWithKeyId() throws JsonToJwtException {
+ public void stringToJwtShouldBeSecuredJwtWithKeyId() throws Exception {
- JWTSerializer subject = appFactory.jwtSerializer();
+ JwtSerde subject = appFactory.jwtSerde();
String signature = "YiFm03WWrDAbFn7omROmU2GHACkaGI30xdbWFzyoCNQ";
@@ -207,7 +196,7 @@ public void stringToJwtShouldBeSecuredJwtWithKeyId() throws JsonToJwtException {
assertThat(actual.getClaims().getJwtId().isPresent(), is(false));
assertThat(actual.getSignature().isPresent(), is(true));
- assertThat(actual.getSignature().get(), is(signature));
+ assertThat(actual.getSignature().get(), is(signature.getBytes()));
assertThat(actual.getJwt().isPresent(), is(true));
assertThat(actual.getJwt().get(), is(jwtAsText));
diff --git a/src/test/java/org/rootservices/jwt/serializer/SerializerImplTest.java b/src/test/java/org/rootservices/jwt/serialization/SerdesTest.java
similarity index 71%
rename from src/test/java/org/rootservices/jwt/serializer/SerializerImplTest.java
rename to src/test/java/org/rootservices/jwt/serialization/SerdesTest.java
index 4ea56a4..e31f5c2 100644
--- a/src/test/java/org/rootservices/jwt/serializer/SerializerImplTest.java
+++ b/src/test/java/org/rootservices/jwt/serialization/SerdesTest.java
@@ -1,14 +1,15 @@
-package org.rootservices.jwt.serializer;
+package org.rootservices.jwt.serialization;
import helper.entity.Claim;
import org.junit.Before;
import org.junit.Test;
-import org.rootservices.jwt.config.AppFactory;
+import org.rootservices.jwt.config.JwtAppFactory;
import org.rootservices.jwt.entity.jwt.header.Header;
import org.rootservices.jwt.entity.jwt.header.Algorithm;
-import org.rootservices.jwt.serializer.exception.JsonException;
+import org.rootservices.jwt.serialization.exception.JsonException;
+import java.nio.charset.StandardCharsets;
import java.util.Optional;
import static org.hamcrest.CoreMatchers.notNullValue;
@@ -17,30 +18,30 @@
import static org.junit.Assert.assertThat;
import static org.junit.Assert.fail;
-/**
- * Created by tommackenzie on 8/12/15.
- */
-public class SerializerImplTest {
- private AppFactory appFactory;
+public class SerdesTest {
+
+ private JwtAppFactory appFactory;
@Before
public void setUp() {
- appFactory = new AppFactory();
+ appFactory = new JwtAppFactory();
}
@Test
public void headerToJson() throws JsonException {
- Serializer subject = appFactory.serializer();
+ Serdes subject = appFactory.serdes();
Header header = new Header();
header.setAlgorithm(Algorithm.NONE);
- String json = subject.objectToJson(header);
- assertThat(json, is("{\"alg\":\"none\"}"));
+
+ byte[] actual = subject.objectToByte(header);
+ String actualAsString = new String(actual, StandardCharsets.UTF_8);
+ assertThat(actualAsString, is("{\"alg\":\"none\"}"));
}
@Test
public void claimToJsonExpectExcludesNullAndOptionalEmpty() throws JsonException {
- Serializer subject = appFactory.serializer();
+ Serdes subject = appFactory.serdes();
Claim claim = new Claim();
Optional issuer = Optional.of("joe");
@@ -50,13 +51,14 @@ public void claimToJsonExpectExcludesNullAndOptionalEmpty() throws JsonException
claim.setIssuer(issuer);
claim.setExpirationTime(expirationTime);
- String json = subject.objectToJson(claim);
- assertThat(json, is("{\"iss\":\"joe\",\"exp\":1300819380,\"http://example.com/is_root\":true}"));
+ byte[] actual = subject.objectToByte(claim);
+ String actualAsString = new String(actual, StandardCharsets.UTF_8);
+ assertThat(actualAsString, is("{\"iss\":\"joe\",\"exp\":1300819380,\"http://example.com/is_root\":true}"));
}
@Test
public void jsonToUnsecuredHeader() throws JsonException {
- Serializer subject = appFactory.serializer();
+ Serdes subject = appFactory.serdes();
byte[] json = "{\"alg\":\"none\"}".getBytes();
Header actual = (Header) subject.jsonBytesToObject(json, Header.class);
assertThat(actual.getAlgorithm(), is(Algorithm.NONE));
@@ -64,7 +66,7 @@ public void jsonToUnsecuredHeader() throws JsonException {
@Test
public void jsonToClaim() throws JsonException {
- Serializer subject = appFactory.serializer();
+ Serdes subject = appFactory.serdes();
byte[] json = "{\"iss\":\"joe\",\"exp\":1300819380,\"http://example.com/is_root\":true}".getBytes();
Claim actual = (Claim) subject.jsonBytesToObject(json, Claim.class);
@@ -83,7 +85,7 @@ public void jsonToClaim() throws JsonException {
@Test(expected=JsonException.class)
public void jsonBytesToObjectShouldThrowJsonException() throws JsonException {
- Serializer subject = appFactory.serializer();
+ Serdes subject = appFactory.serdes();
byte[] invalidJson = "{\"iss\":\"joe\"".getBytes();
subject.jsonBytesToObject(invalidJson, Claim.class);
diff --git a/src/test/java/org/rootservices/jwt/serialization/UnSecureJwtSerializerTest.java b/src/test/java/org/rootservices/jwt/serialization/UnSecureJwtSerializerTest.java
new file mode 100644
index 0000000..e48e536
--- /dev/null
+++ b/src/test/java/org/rootservices/jwt/serialization/UnSecureJwtSerializerTest.java
@@ -0,0 +1,45 @@
+package org.rootservices.jwt.serialization;
+
+import helper.entity.Factory;
+import org.junit.Before;
+import org.junit.Test;
+import org.rootservices.jwt.config.JwtAppFactory;
+import org.rootservices.jwt.entity.jwt.Claims;
+
+import java.io.ByteArrayOutputStream;
+
+import static org.hamcrest.core.Is.is;
+import static org.junit.Assert.*;
+
+
+public class UnSecureJwtSerializerTest {
+ private JwtAppFactory appFactory;
+
+ @Before
+ public void setUp() {
+ appFactory = new JwtAppFactory();
+ }
+
+ @Test
+ public void compactJwtShouldBeOk() {
+ UnSecureJwtSerializer subject = appFactory.unSecureJwtSerializer();
+
+ Claims claims = Factory.makeClaim();
+
+ ByteArrayOutputStream actual = subject.compactJwt(claims);
+
+ assertThat(actual.toString(), is("eyJhbGciOiJub25lIn0.eyJpc3MiOiJqb2UiLCJleHAiOjEzMDA4MTkzODAsImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ."));
+ }
+
+ @Test
+ public void compactJwtToStringShouldBeOk() {
+ UnSecureJwtSerializer subject = appFactory.unSecureJwtSerializer();
+
+ Claims claims = Factory.makeClaim();
+
+ String jwt = subject.compactJwtToString(claims);
+
+ assertThat(jwt, is("eyJhbGciOiJub25lIn0.eyJpc3MiOiJqb2UiLCJleHAiOjEzMDA4MTkzODAsImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ."));
+ }
+
+}
\ No newline at end of file
diff --git a/src/test/java/org/rootservices/jwt/translator/CSRToRSAPublicKeyTest.java b/src/test/java/org/rootservices/jwt/translator/CSRToRSAPublicKeyTest.java
deleted file mode 100644
index ce2e23b..0000000
--- a/src/test/java/org/rootservices/jwt/translator/CSRToRSAPublicKeyTest.java
+++ /dev/null
@@ -1,83 +0,0 @@
-package org.rootservices.jwt.translator;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.rootservices.jwt.config.AppFactory;
-import org.rootservices.jwt.entity.jwk.KeyType;
-import org.rootservices.jwt.entity.jwk.RSAPublicKey;
-import org.rootservices.jwt.entity.jwk.Use;
-import org.rootservices.jwt.translator.exception.InvalidKeyException;
-import org.rootservices.jwt.translator.exception.InvalidCsrException;
-
-import java.io.FileNotFoundException;
-import java.io.FileReader;
-import java.io.IOException;
-import java.math.BigInteger;
-import java.net.URL;
-import java.util.Optional;
-
-import static org.hamcrest.core.Is.is;
-import static org.hamcrest.core.IsNull.notNullValue;
-import static org.junit.Assert.*;
-
-/**
- * Created by tommackenzie on 12/1/15.
- */
-public class CSRToRSAPublicKeyTest {
- private AppFactory appFactory;
-
- @Before
- public void setUp() {
- appFactory = new AppFactory();
- }
-
- @Test
- public void shouldTranslateCSRToRSAPublicKey() throws FileNotFoundException, InvalidCsrException, InvalidKeyException {
- URL privateKeyURL = getClass().getResource("/certs/rsa-cert.csr");
- FileReader fr = new FileReader(privateKeyURL.getFile());
-
- CSRToRSAPublicKey subject = appFactory.csrToRSAPublicKey();
-
- RSAPublicKey actual = subject.translate(fr, Optional.of("test-key-id"), Use.SIGNATURE);
-
- assertThat(actual, is(notNullValue()));
- assertThat(actual.getKeyId().isPresent(), is(true));
- assertThat(actual.getKeyId().get(), is("test-key-id"));
- assertThat(actual.getUse(), is(Use.SIGNATURE));
- assertThat(actual.getKeyType(), is(KeyType.RSA));
- assertThat(actual.getN(), is(new BigInteger("31547363068675167897756930554362079780191578737192115507526898964667457901907675194501789280350861000129589859093278343756085398379306366123730728103421370791175356895018543806044325144818946471653951140470823139449286798248410821533402163473721370921654197140946196794921284894039254456107355893831146589487500059843522247062489436603543693162592270480345794243004091939582347569432019753837113712433864529566521319428801714421137033495634109852983552061952143849954383008111368867567356581104016991597045919263898215285259909976858081430303755638022211078978491982452596141052654560597952703737488015089139469137261")));
- assertThat(actual.getE(), is(new BigInteger("65537")));
- }
-
- @Test(expected = InvalidCsrException.class)
- public void closedFileReaderShouldThrowInvalidFileReader() throws IOException, InvalidCsrException, InvalidKeyException {
- URL privateKeyURL = getClass().getResource("/certs/rsa-cert-bad.csr");
- FileReader fr = new FileReader(privateKeyURL.getFile());
- fr.close();
-
- CSRToRSAPublicKey subject = appFactory.csrToRSAPublicKey();
-
- subject.translate(fr, Optional.of("test-key-id"), Use.SIGNATURE);
- }
-
- @Test(expected = InvalidCsrException.class)
- public void emptyFileShouldThrowInvalidFileReader() throws FileNotFoundException, InvalidCsrException, InvalidKeyException {
- URL privateKeyURL = getClass().getResource("/certs/rsa-cert-bad.csr");
- FileReader fr = new FileReader(privateKeyURL.getFile());
-
- CSRToRSAPublicKey subject = appFactory.csrToRSAPublicKey();
-
- subject.translate(fr, Optional.of("test-key-id"), Use.SIGNATURE);
- }
-
- @Test(expected = InvalidCsrException.class)
- public void pemFileShouldThrowInvalidFileReader() throws FileNotFoundException, InvalidCsrException, InvalidKeyException {
- URL privateKeyURL = getClass().getResource("/certs/rsa-private-key.pem");
- FileReader fr = new FileReader(privateKeyURL.getFile());
-
- CSRToRSAPublicKey subject = appFactory.csrToRSAPublicKey();
-
- subject.translate(fr, Optional.of("test-key-id"), Use.SIGNATURE);
- }
-
-}
\ No newline at end of file
diff --git a/src/test/java/org/rootservices/jwt/translator/PemToRSAKeyPairTest.java b/src/test/java/org/rootservices/jwt/translator/PemToRSAKeyPairTest.java
deleted file mode 100644
index b233191..0000000
--- a/src/test/java/org/rootservices/jwt/translator/PemToRSAKeyPairTest.java
+++ /dev/null
@@ -1,118 +0,0 @@
-package org.rootservices.jwt.translator;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.rootservices.jwt.config.AppFactory;
-import org.rootservices.jwt.entity.jwk.KeyType;
-import org.rootservices.jwt.entity.jwk.RSAKeyPair;
-import org.rootservices.jwt.entity.jwk.Use;
-import org.rootservices.jwt.translator.exception.InvalidKeyException;
-import org.rootservices.jwt.translator.exception.InvalidPemException;
-
-import java.io.FileNotFoundException;
-import java.io.FileReader;
-import java.io.IOException;
-import java.math.BigInteger;
-import java.net.URL;
-import java.util.Optional;
-
-import static org.hamcrest.CoreMatchers.notNullValue;
-import static org.hamcrest.core.Is.is;
-import static org.junit.Assert.*;
-
-/**
- * Created by tommackenzie on 11/30/15.
- */
-public class PemToRSAKeyPairTest {
-
- private AppFactory appFactory;
-
- @Before
- public void setUp() {
- this.appFactory = new AppFactory();
- }
-
- private FileReader makeFileReader(String filePath) {
-
- URL privateKeyURL = getClass().getResource(filePath);
-
- if (privateKeyURL == null) {
- fail("Could not find file the pem file");
- }
-
- FileReader pemFileReader = null;
- try {
- pemFileReader = new FileReader(privateKeyURL.getFile());
- } catch (FileNotFoundException e) {
- fail("Could not find file the pem file");
- }
-
- return pemFileReader;
- }
-
- @Test
- public void shouldMakeCorrectKeyPair() throws InvalidPemException, InvalidKeyException {
-
- PemToRSAKeyPair pemToRSAKeyPair = appFactory.pemToRSAKeyPair();
-
- FileReader pemFileReader = makeFileReader("/certs/rsa-private-key.pem");
-
- // expected
- BigInteger modulus = new BigInteger("31547363068675167897756930554362079780191578737192115507526898964667457901907675194501789280350861000129589859093278343756085398379306366123730728103421370791175356895018543806044325144818946471653951140470823139449286798248410821533402163473721370921654197140946196794921284894039254456107355893831146589487500059843522247062489436603543693162592270480345794243004091939582347569432019753837113712433864529566521319428801714421137033495634109852983552061952143849954383008111368867567356581104016991597045919263898215285259909976858081430303755638022211078978491982452596141052654560597952703737488015089139469137261");
- BigInteger publicExponent = new BigInteger("65537");
- BigInteger privateExponent = new BigInteger("17926596396547475894233270530768851383098319785033974298729103320920713485892606190677649794612912011624365716198373114421172411325567975049420267105597071419719570107380343773454639558084782421393484511379433366437751036110427199974448479025967889505063154488700692964884928677524388897872866332639054734563540603538126904942970545933364201807568104872067768314855737491966908061964979181796120872344579985695190632663663576855846805589958978811239981840087025695582715666984680745947985390068749640688608533968405297323218578662269674742653843895867705344639568613274268304462852744075002084615909877427512082671809");
- BigInteger primeP = new BigInteger("177896497866913720666018635152384129022597163894037528397616765963660310944144586061003646473127224648491803487187299104582675895481985461698392379397626497276548015737035578624405241545087536057660433797241365357543813340937549961569784412712933089949857152189846777292464517821447558299649089116062107231697");
- BigInteger primeQ = new BigInteger("177335492530471784736855608763756232554907628078583812409958753247718335607210292037747143084156694233415555712874052909486016311004636559265753924014644550889364310406206169714329162148665359467600692075303825823321048442016831954507581831805295679970247348504587073016601516999984331832595091571024265531613");
- BigInteger primeExponentP = new BigInteger("142329141845884828866167525452494154770142967966491657598007804851283469552241897333150208266657810049575342540048809699096510793959174599061499702783696961383623276273795314548912285200346672347641289435350317395630747649705044397591438056306970621762223017805551458268658689403692284844954763549012016579745");
- BigInteger primeExponentQ = new BigInteger("1279882935851704444520388527782118467407286083909396879166127382794006023196216917677867444021028066167288064027792346707766387156952455750685896608922087867474393378124349882888714675623216122620430098289801327714586507058210804804646019903930678191341181253988886972807002419106651036159993260495513642621");
- BigInteger crtCoefficient = new BigInteger("52655246168149931266593527226554483262446108013405644846090346118573657005660216425771053079024891453912366463810544032383603524938201963417881747736294434635848257983482194424189814343462587544169753320024624881614416412658658522200837842119558010863255094195173449128914773351492908487605687200685726121916");
-
- RSAKeyPair actual = pemToRSAKeyPair.translate(pemFileReader, Optional.of("test-key-id"), Use.SIGNATURE);
-
- assertThat(actual, is(notNullValue()));
-
- assertThat(actual, is(notNullValue()));
- assertThat(actual.getKeyId().isPresent(), is(true));
- assertThat(actual.getKeyId().get(), is("test-key-id"));
- assertThat(actual.getKeyType(), is(KeyType.RSA));
- assertThat(actual.getUse(), is(Use.SIGNATURE));
-
- assertThat(actual.getN(), is(modulus));
- assertThat(actual.getE(), is(publicExponent));
- assertThat(actual.getD(), is(privateExponent));
- assertThat(actual.getP(), is(primeP));
- assertThat(actual.getQ(), is(primeQ));
- assertThat(actual.getDp(), is(primeExponentP));
- assertThat(actual.getDq(), is(primeExponentQ));
- assertThat(actual.getQi(), is(crtCoefficient));
- }
-
- @Test(expected = InvalidPemException.class)
- public void closedFileReaderShouldThrowInvalidPemException() throws InvalidPemException, IOException, InvalidKeyException {
- PemToRSAKeyPair pemToRSAKeyPair = appFactory.pemToRSAKeyPair();
-
- FileReader pemFileReader = makeFileReader("/certs/rsa-private-key.pem");
- pemFileReader.close();
-
- pemToRSAKeyPair.translate(pemFileReader, Optional.of("test-key-id"), Use.SIGNATURE);
- }
-
- @Test(expected = InvalidPemException.class)
- public void emptyPemFileShouldThrowInvalidPemException() throws InvalidPemException, InvalidKeyException {
- PemToRSAKeyPair pemToRSAKeyPair = appFactory.pemToRSAKeyPair();
-
- FileReader pemFileReader = makeFileReader("/certs/rsa-private-key-bad.pem");
- pemToRSAKeyPair.translate(pemFileReader, Optional.of("test-key-id"), Use.SIGNATURE);
- }
-
- @Test(expected = InvalidPemException.class)
- public void csrFileShouldThrowInvalidPemException() throws InvalidPemException, InvalidKeyException {
- PemToRSAKeyPair pemToRSAKeyPair = appFactory.pemToRSAKeyPair();
-
- FileReader pemFileReader = makeFileReader("/certs/rsa-cert.csr");
- pemToRSAKeyPair.translate(pemFileReader, Optional.of("test-key-id"), Use.SIGNATURE);
- }
-
-
-
-}
\ No newline at end of file
diff --git a/src/test/resources/certs/rsa-cert-bad.csr b/src/test/resources/certs/rsa-cert-bad.csr
deleted file mode 100644
index e69de29..0000000
diff --git a/src/test/resources/certs/rsa-cert.csr b/src/test/resources/certs/rsa-cert.csr
deleted file mode 100644
index e8ad5a5..0000000
--- a/src/test/resources/certs/rsa-cert.csr
+++ /dev/null
@@ -1,17 +0,0 @@
------BEGIN CERTIFICATE REQUEST-----
-MIICnTCCAYUCAQAwWDELMAkGA1UEBhMCVVMxETAPBgNVBAgTCElsbGlub2lzMRAw
-DgYDVQQHEwdDaGljYWdvMRYwFAYDVQQKEw1Sb290IFNlcnZpY2VzMQwwCgYDVQQL
-EwNKV1QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQD55zuXRnN5CXDU
-WXGjqEhh5eG3BN3sPp8mR/dw2CuNOHLd08vHMyhpYAXvpvAxf9EedYtoSA5bR0Xl
-gwQJqe4vb8rGXCq9EdC63qIuvZmZNbRDNLXcjUmYOJZ2BczSamaKGscUpkd4/YKQ
-vHtihv82tcVKAnacylWLZqC0nHKwTM/00vOlus7fnYSTE3qvVfRHyDQif/iAlaDr
-KI4CL2caSaIpmC5MOhJ4eUh07p2gKCTIfXa4PvAYqVHB5Q2KmprZkOxSBmZVlQGy
-H33OTKl2MBU/3oVfIgsjOcjxxvoKSaWx59U6YWgHbmq+i8Ub2DtcDaEDaqyEeVLv
-xa4uRjVtAgMBAAGgADANBgkqhkiG9w0BAQUFAAOCAQEApxMtAwnS+hwNMdTghgMd
-oNArpWTC7VKCCKYGffUzYX0LjANxj3pBNpBCzPFm7v2xbSyZ09iXMGz/Si/9Gr3B
-Bhv5arQV35jOgv3WNDDEB+rwqmyfPvYjEYTaPiGQ7JWAGQZxxqsbUt2ZEt4aXyVK
-S/4thpKARsPy454PdhYbVKc+sJ3tiA2dRP78I7FQhyOqv2biJHsJIynWjWVHTYxL
-SK7KGMefKqOP0LjO+s1921yI6h39VhJ5NjqDCeRAdWkOvv1FGsgayNO4FD9grCYB
-Z/shg+IpHO3TSNm+8hnGqmJAALZc8HfvrqbDeKzU6jSqMfs0lZC/3fiIj3beUzh3
-0A==
------END CERTIFICATE REQUEST-----
diff --git a/src/test/resources/certs/rsa-private-key-bad.pem b/src/test/resources/certs/rsa-private-key-bad.pem
deleted file mode 100644
index e69de29..0000000
diff --git a/src/test/resources/certs/rsa-private-key.pem b/src/test/resources/certs/rsa-private-key.pem
deleted file mode 100644
index 4973d89..0000000
--- a/src/test/resources/certs/rsa-private-key.pem
+++ /dev/null
@@ -1,27 +0,0 @@
------BEGIN RSA PRIVATE KEY-----
-MIIEpAIBAAKCAQEA+ec7l0ZzeQlw1Flxo6hIYeXhtwTd7D6fJkf3cNgrjThy3dPL
-xzMoaWAF76bwMX/RHnWLaEgOW0dF5YMECanuL2/KxlwqvRHQut6iLr2ZmTW0QzS1
-3I1JmDiWdgXM0mpmihrHFKZHeP2CkLx7Yob/NrXFSgJ2nMpVi2agtJxysEzP9NLz
-pbrO352EkxN6r1X0R8g0In/4gJWg6yiOAi9nGkmiKZguTDoSeHlIdO6doCgkyH12
-uD7wGKlRweUNipqa2ZDsUgZmVZUBsh99zkypdjAVP96FXyILIznI8cb6CkmlsefV
-OmFoB25qvovFG9g7XA2hA2qshHlS78WuLkY1bQIDAQABAoIBAQCOAYkKUF1jxSqZ
-cG4z+nePMetObfSRv4/+V9zTAfPVnuMfDLB6dKadIpSc9zb8Wc6CSXc7fd6yndCp
-OAb+WtLfn94RU+RxZgM/fS2Z8+Gpfyv9GKHTP3I3jshpLqiSVSYJimfgYxCwPxaH
-mqNefKnf8/C1OqseM5fizCG8ID7H0O7RMQCxz3Ebga+so8gTVANxIeGfFIXME1KN
-bxpSAmladw8QNfjqYEPeMYtN9IiFd3spLSX2pChYyjg7SuH/KtUwjA9o+Gn2Zb7z
-Rex3a/9jJOPSUbLrlqMYtnlGVjU/nU8rIqOImNDggxSbVk6781kJYI8P/ik2pXfs
-tVL6S6jBAoGBAP1VQO6MlOceOe9mxB69ZmngcahoCZLfw4L7P2YS3tLITZFqlhO8
-IzyittX/D/pR9LbpB3nh6T0kmQjFZMT8Rh8B/z9pvfmffmxbL7uD/jk/zwGy0vb6
-gdbvGvn3ynGE6Xhsci7v0dZbqKNDvrCu7HNo8AFrYE/lQBQt7OPBEuXRAoGBAPyI
-vFhFEOfE/9Ssl5Z2wd7S81jDg8ZgryaWJMi032TjtrHeCbEjefq5skvb0jvSdZvw
-WvwsAaKdKCNjW675N53k2uRoszOBhg1Vo2HSsW8nH6J/Uh4fYPNBGEVyYj74CFcs
-TTDNuxfFAD/3gWpkSVocD5cbgASrKotXQTDFfNDdAoGBAMqu9P5mt5OaGVwy6mJ1
-woSfMBA+/LnoEXKwNe8i1efqnjTkBCLR+Zc/z+yy30O1YocdNgAMASIML+xWkeMQ
-u8F/RYqkvXwEYY+r/SqX1kRTivme6y7zCgK+1uR7nhro7iqNCWYINei8+NV3FBAk
-Q8Wqhat9D1ec4YHDpK4sAUShAoGAAdKW0WhGM/YHBqjsOyjGQ25wVS6sD8141iV1
-RIGRry+5jNUWatHfuoCGmeePP+FH+gUlEvbaWCscNA0uhzfDP/972PQsfu2rYwNA
-N5+Gqk+0+b5DgHYng/nvS+kEboHpxX9LW1PQyt4gH1YQ+AybPuw+7I9FQENf/jt1
-+/0g5n0CgYBK+8qOpRZnKbjHMfmvi73lywWoOFHWY3QciMjhnQ8F/EtHzaNgC6wr
-WhzFxxdrL0+8bEyLwoUOudfcZXyBG3otSmGQLqn7ru+xRNSff8z8Y9E0GSKj3e7a
-qPtzeBCa5irkAonpgowxfciO5SvLhM2wi8a3nTOqHmNkTVvDv9A/vA==
------END RSA PRIVATE KEY-----
diff --git a/src/test/resources/log4j2.properties b/src/test/resources/log4j2.properties
new file mode 100644
index 0000000..4a420b3
--- /dev/null
+++ b/src/test/resources/log4j2.properties
@@ -0,0 +1,7 @@
+appender.console.type = Console
+appender.console.name = STDOUT
+appender.console.layout.type = PatternLayout
+appender.console.layout.pattern = %d{ISO8601} %5p %t %c{2}:%L - %m%n
+
+rootLogger.level=INFO
+rootLogger.appenderRef.stdout.ref = STDOUT
\ No newline at end of file