Skip to content

Commit

Permalink
JWE support. Resolves #113
Browse files Browse the repository at this point in the history
impl checkpoint: adjusted @SInCE version, added KeyManagementMode concept w/ supporting interfaces
KeyManagementMode interfaces and implementations are dummy implementations to enable compiling.  Design still needs to be vetted.
  • Loading branch information
lhazlewood committed Jul 13, 2019
1 parent f7386de commit c60d53e
Show file tree
Hide file tree
Showing 105 changed files with 4,070 additions and 176 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,6 @@ target/
.classpath
.project
.settings

.clover
.java-version
23 changes: 20 additions & 3 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,26 @@ jdk:
- openjdk10

before_install:
- if [ "${TRAVIS_JDK_VERSION}" == "openjdk7" ]; then export MAVEN_OPTS="-Dhttps.protocols=TLSv1.2 -Xmx512m -XX:MaxPermSize=128m"; fi
- if [ "${TRAVIS_JDK_VERSION}" == "openjdk7" ]; then export JAVA_HOME="/usr/lib/jvm/java-7-oracle"; export PATH="${JAVA_HOME}/bin:${PATH}"; fi
- if [ "${TRAVIS_JDK_VERSION}" == "openjdk7" ]; then test ! -d "${JAVA_HOME}" && (wget https://s3.amazonaws.com/d2fbee19-5fe2-425f-ae11-cd25b35dc99a/jdk-7u80-linux-x64.tar.gz -O /tmp/jdk-7u80-linux-x64.tar.gz; tar xvfz /tmp/jdk-7u80-linux-x64.tar.gz -C /tmp; sudo mv /tmp/jdk1.7.0_80 "${JAVA_HOME}"); fi
- |
if [[ "${TRAVIS_JDK_VERSION}" == "oraclejdk7" ]]; then
export MAVEN_OPTS="-Dhttps.protocols=TLSv1.2 -Xmx512m -XX:MaxPermSize=128m"
export JAVA_HOME="/usr/lib/jvm/java-7-oracle" # Set JAVA_HOME to where we want to install Oracle JDK 7
export PATH="${JAVA_HOME}/bin:${PATH}"
if [[ ! -d "${JAVA_HOME}" ]]; then
# Download and install Oracle JDK 7:
wget https://s3.amazonaws.com/d2fbee19-5fe2-425f-ae11-cd25b35dc99a/jdk-7u80-linux-x64.tar.gz -O /tmp/jdk-7u80-linux-x64.tar.gz
tar xvfz /tmp/jdk-7u80-linux-x64.tar.gz -C /tmp
sudo mv /tmp/jdk1.7.0_80 "${JAVA_HOME}"
fi
# Download and install JCE Unlimited Strength Crypto policies for Oracle JDK 7:
curl -q -L -C - https://238dj3282as03k369.s3-us-west-1.amazonaws.com/UnlimitedJCEPolicyJDK7.zip -o /tmp/UnlimitedJCEPolicyJDK7.zip
sudo unzip -oj -d "$JAVA_HOME/jre/lib/security" /tmp/UnlimitedJCEPolicyJDK7.zip \*/\*.jar
rm /tmp/UnlimitedJCEPolicyJDK7.zip
fi
# If on JDK 8, ensure build coverage assertions are run (we only need to run this on one JDK to reduce overall build times):
- export BUILD_COVERAGE="$([ $TRAVIS_JDK_VERSION == 'oraclejdk8' ] && echo 'true')"

install: true
Expand Down
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ enforcement.
* [Custom Clock](#jws-read-clock-custom)
* [Decompression](#jws-read-decompression)
<!-- * [Error Handling](#jws-read-errors) -->
* [Encrypted JWTs](#jwe)
* [Compression](#compression)
* [Custom Compression Codec](#compression-custom)
* [JSON Processor](#json)
Expand Down Expand Up @@ -1138,7 +1139,10 @@ how to resolve your `CompressionCodec` to decompress the JWT.

Please see the [Compression](#compression) section below to see how to decompress JWTs during parsing.

<!-- TODO: ## Encrypted JWTs -->
<a name="jwe"></a>
## Encrypted JWTs

TODO: NOTE: A128GCM, A192GCM, A256GCM algorithms require JDK 8 or BouncyCastle.

<a name="compression"></a>
## Compression
Expand Down
6 changes: 4 additions & 2 deletions api/src/main/java/io/jsonwebtoken/CompressionCodec.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,11 @@
public interface CompressionCodec {

/**
* The compression algorithm name to use as the JWT's {@code zip} header value.
* The algorithm name to use as the JWT's
* <a href="https://tools.ietf.org/html/rfc7516#section-4.1.3"><code>zip</code></a> header value.
*
* @return the compression algorithm name to use as the JWT's {@code zip} header value.
* @return the algorithm name to use as the JWT's
* <a href="https://tools.ietf.org/html/rfc7516#section-4.1.3"><code>zip</code></a> header value.
*/
String getAlgorithmName();

Expand Down
75 changes: 71 additions & 4 deletions api/src/main/java/io/jsonwebtoken/Header.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
* <h3>Creation</h3>
*
* <p>It is easiest to create a {@code Header} instance by calling one of the
* {@link Jwts#header() JWTs.header()} factory methods.</p>
* {@link Jwts#header() Jwts.header()} factory methods.</p>
*
* @since 0.1
*/
Expand All @@ -48,6 +48,14 @@ public interface Header<T extends Header<T>> extends Map<String,Object> {
/** JWT {@code Content Type} header parameter name: <code>"cty"</code> */
public static final String CONTENT_TYPE = "cty";

/**
* JWT {@code Algorithm} header parameter name: <code>"alg"</code>.
*
* @see <a href="https://tools.ietf.org/html/rfc7515#section-4.1.1">JWS Algorithm Header</a>
* @see <a href="https://tools.ietf.org/html/rfc7516#section-4.1.1">JWE Algorithm Header</a>
*/
public static final String ALGORITHM = "alg";

/** JWT {@code Compression Algorithm} header parameter name: <code>"zip"</code> */
public static final String COMPRESSION_ALGORITHM = "zip";

Expand Down Expand Up @@ -109,22 +117,81 @@ public interface Header<T extends Header<T>> extends Map<String,Object> {
T setContentType(String cty);

/**
* Returns the JWT <code>zip</code> (Compression Algorithm) header value or {@code null} if not present.
* Returns the JWT {@code alg} (Algorithm) header value or {@code null} if not present.
*
* <ul>
* <li>If the JWT is a Signed JWT (a JWS), the <a href="https://tools.ietf.org/html/rfc7515#section-4.1.1">
* <code>alg</code></a> (Algorithm) header parameter identifies the cryptographic algorithm used to secure the
* JWS. Consider using {@link io.jsonwebtoken.SignatureAlgorithm#forName(String) SignatureAlgorithm.forName} to
* convert this string value to a type-safe enum instance.</li>
* <li>If the JWT is an Encrypted JWT (a JWE), the
* <a href="https://tools.ietf.org/html/rfc7516#section-4.1.1"><code>alg</code></a> (Algorithm) header parameter
* identifies the cryptographic key management algorithm used to encrypt or determine the value of the Content
* Encryption Key (CEK). The encrypted content is not usable if the <code>alg</code> value does not represent a
* supported algorithm, or if the recipient does not have a key that can be used with that algorithm</li>
* </ul>
*
* @return the {@code alg} header value or {@code null} if not present. This will always be
* {@code non-null} on validly constructed JWT instances, but could be {@code null} during construction.
*/
String getAlgorithm();

/**
* Sets the JWT <code>alg</code></a> (Algorithm) header value. A {@code null} value will remove the property
* from the JSON map.
* <ul>
* <li>If the JWT is a Signed JWT (a JWS), the <a href="https://tools.ietf.org/html/rfc7515#section-4.1.1">
* <code>alg</code></a> (Algorithm) header parameter identifies the cryptographic algorithm used to secure the
* JWS. Consider using {@link io.jsonwebtoken.SignatureAlgorithm#forName(String) SignatureAlgorithm.forName} to
* convert this string value to a type-safe enum instance.</li>
* <li>If the JWT is an Encrypted JWT (a JWE), the
* <a href="https://tools.ietf.org/html/rfc7516#section-4.1.1"><code>alg</code></a> (Algorithm) header parameter
* identifies the cryptographic key management algorithm used to encrypt or determine the value of the Content
* Encryption Key (CEK). The encrypted content is not usable if the <code>alg</code> value does not represent a
* supported algorithm, or if the recipient does not have a key that can be used with that algorithm</li>
* </ul>
*
* @param alg the {@code alg} header value
* @return this header for method chaining
*/
T setAlgorithm(String alg);

/**
* Returns the JWT <a href="https://tools.ietf.org/html/rfc7516#section-4.1.3"><code>zip</code></a>
* (Compression Algorithm) header parameter value or {@code null} if not present.
*
* <h3>Compatiblity Note</h3>
*
* <p>While the JWT family of specifications only defines the <code>zip</code> header in the JWE
* (JSON Web Encryption) specification, JJWT will also support compression for JWS as well if you choose to use it.
* However, be aware that <b>if you use compression when creating a JWS token, other libraries may not be able to
* parse the JWS</b>. However, compression when creating JWE tokens should be universally accepted for any library
* that supports JWE.</p>
*
* @return the {@code zip} header parameter value or {@code null} if not present.
* @since 0.6.0
*/
String getCompressionAlgorithm();

/**
* Sets the JWT <code>zip</code> (Compression Algorithm) header parameter value. A {@code null} value will remove
* Sets the JWT <a href="https://tools.ietf.org/html/rfc7516#section-4.1.3"><code>zip</code></a>
* (Compression Algorithm) header parameter value. A {@code null} value will remove
* the property from the JSON map.
* <p>
* <p>The compression algorithm is NOT part of the <a href="https://tools.ietf.org/html/draft-ietf-oauth-json-web-token-25">JWT specification</a>
* and must be used carefully since, is not expected that other libraries (including previous versions of this one)
* be able to deserialize a compressed JTW body correctly. </p>
*
* @param zip the JWT compression algorithm {@code zip} value or {@code null} to remove the property from the JSON map.
* <h3>Compatiblity Note</h3>
*
* <p>While the JWT family of specifications only defines the <code>zip</code> header in the JWE
* (JSON Web Encryption) specification, JJWT will also support compression for JWS as well if you choose to use it.
* However, be aware that <b>if you use compression when creating a JWS token, other libraries may not be able to
* parse the JWS</b>. However, Compression when creating JWE tokens should be universally accepted for any library
* that supports JWE.</p>
*
* @param zip the JWT compression algorithm {@code zip} value or {@code null} to remove the property from the
* JSON map.
* @since 0.6.0
*/
T setCompressionAlgorithm(String zip);
Expand Down
12 changes: 12 additions & 0 deletions api/src/main/java/io/jsonwebtoken/Jwe.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package io.jsonwebtoken;

/**
* @param <B> payload type
* @since 0.11.0
*/
public interface Jwe<B> extends Jwt<JweHeader,B> {

byte[] getInitializationVector();

byte[] getAadTag();
}
88 changes: 88 additions & 0 deletions api/src/main/java/io/jsonwebtoken/JweHeader.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package io.jsonwebtoken;

/**
* A <a href="https://tools.ietf.org/html/rfc7516">JWE</a> header.
*
* @since 0.11.0
*/
public interface JweHeader extends Header<JweHeader> {

/**
* JWE <a href="https://tools.ietf.org/html/rfc7516#section-4.1.1">Algorithm Header</a> name: the string literal <b><code>alg</code></b>
*/
public static final String ALGORITHM = "alg";

/**
* JWE <a href="https://tools.ietf.org/html/rfc7516#section-4.1.2">Encryption Algorithm Header</a> name: the string literal <b><code>enc</code></b>
*/
public static final String ENCRYPTION_ALGORITHM = "enc";

/**
* JWE <a href="https://tools.ietf.org/html/rfc7516#section-4.1.3">Compression Algorithm Header</a> name: the string literal <b><code>zip</code></b>
*/
public static final String COMPRESSION_ALGORITHM = "zip";

/**
* JWE <a href="https://tools.ietf.org/html/rfc7516#section-4.1.4">JWK Set URL Header</a> name: the string literal <b><code>jku</code></b>
*/
public static final String JWK_SET_URL = "jku";

/**
* JWE <a href="https://tools.ietf.org/html/rfc7516#section-4.1.5">JSON Web Key Header</a> name: the string literal <b><code>jwk</code></b>
*/
public static final String JSON_WEB_KEY = "jwk";

/**
* JWE <a href="https://tools.ietf.org/html/rfc7516#section-4.1.6">Key ID Header</a> name: the string literal <b><code>kid</code></b>
*/
public static final String KEY_ID = "kid";

/**
* JWE <a href="https://tools.ietf.org/html/rfc7516#section-4.1.7">X.509 URL Header</a> name: the string literal <b><code>x5u</code></b>
*/
public static final String X509_URL = "x5u";

/**
* JWE <a href="https://tools.ietf.org/html/rfc7516#section-4.1.8">X.509 Certificate Chain Header</a> name: the string literal <b><code>x5c</code></b>
*/
public static final String X509_CERT_CHAIN = "x5c";

/**
* JWE <a href="https://tools.ietf.org/html/rfc7516#section-4.1.9">X.509 Certificate SHA-1 Thumbprint Header</a> name: the string literal <b><code>x5t</code></b>
*/
public static final String X509_CERT_SHA1_THUMBPRINT = "x5t";

/**
* JWE <a href="https://tools.ietf.org/html/rfc7516#section-4.1.10">X.509 Certificate SHA-256 Thumbprint Header</a> name: the string literal <b><code>x5t#S256</code></b>
*/
public static final String X509_CERT_SHA256_THUMBPRINT = "x5t#S256";

/**
* JWE <a href="https://tools.ietf.org/html/rfc7516#section-4.1.13">Critical Header</a> name: the string literal <b><code>crit</code></b>
*/
public static final String CRITICAL = "crit";

/**
* Returns the JWE <a href="https://tools.ietf.org/html/rfc7516#section-4.1.2"><code>enc</code></a> (Encryption
* Algorithm) header value or {@code null} if not present.
* <p>The JWE {@code enc} (encryption algorithm) Header Parameter identifies the content encryption algorithm
* used to perform authenticated encryption on the plaintext to produce the ciphertext and the JWE
* {@code Authentication Tag}.</p>
*
* @return the JWE {@code enc} (Encryption Algorithm) header value or {@code null} if not present. This will
* always be {@code non-null} on validly constructed JWE instances, but could be {@code null} during construction.
*/
String getEncryptionAlgorithm();

/**
* Sets the JWE <a href="https://tools.ietf.org/html/rfc7516#section-4.1.2"><code>enc</code></a> (Encryption
* Algorithm) header value. A {@code null} value will remove the property from the JSON map.
* <p>The JWE {@code enc} (encryption algorithm) Header Parameter identifies the content encryption algorithm
* used to perform authenticated encryption on the plaintext to produce the ciphertext and the JWE
* {@code Authentication Tag}.</p>
*
* @param enc the encryption algorithm identifier
* @return this header for method chaining
*/
JweHeader setEncryptionAlgorithm(String enc);
}
Loading

0 comments on commit c60d53e

Please sign in to comment.