Skip to content

Commit

Permalink
Ensured BouncyCastle was optional. Also ensured EllipticCurve algorit…
Browse files Browse the repository at this point in the history
…hms could be used without BouncyCastle since the JDK supports EC by default. Moved RuntimeEnvironment.enableBouncyCastleIfPossible() call out of SignatureAlgorithm into RsaProvider since BC is only necessary for RSASSA-PSS algorithms (PS256, PS384, PS512) and nothing else in JJWT's codebase.

Resolves jwtk#372
  • Loading branch information
lhazlewood committed Aug 2, 2018
1 parent b58e1b6 commit 7f66262
Show file tree
Hide file tree
Showing 18 changed files with 107 additions and 113 deletions.
5 changes: 4 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,16 @@
#sudo: required
language: java
jdk:
- openjdk7
- oraclejdk7
- oraclejdk8
- oraclejdk9
- oraclejdk10
- openjdk10

before_install:
- if [ "${TRAVIS_JDK_VERSION}" == "oraclejdk7" ]; then export MAVEN_OPTS="-Dhttps.protocols=TLSv1.2 -Xmx512m -XX:MaxPermSize=128m"; fi
- if [ "${TRAVIS_JDK_VERSION}" == "oraclejdk7" ]; then export JAVA_HOME="/usr/lib/jvm/java-7-oracle"; export PATH="${JAVA_HOME}/bin:${PATH}"; fi
- if [ "${TRAVIS_JDK_VERSION}" == "oraclejdk7" ]; then test ! -d "${JAVA_HOME}" && (curl http://ftp.osuosl.org/pub/funtoo/distfiles/oracle-java/jdk-7u80-linux-x64.tar.gz | sudo tar xz -C /usr/lib/jvm; sudo mv /usr/lib/jvm/jdk1.7.0_80 "${JAVA_HOME}"); fi
- export BUILD_COVERAGE="$([ $TRAVIS_JDK_VERSION == 'oraclejdk8' ] && echo 'true')"

install: true
Expand Down
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
## Release Notes

### 0.10.1

This is a minor point release that ensures the BouncyCastle dependency is optional and not pulled in as a transitive
dependency into projects.

Internal implementation code (not impacting the JJWT API) and documentation was also updated to reflect that all
Elliptic Curve algorithms are standard on the JDK and do not require Bouncy Castle.

Bouncy Castle is only needed when using PS256, PS384, and PS512 signature algorithms on < JDK 11.
[JDK 11 and later](https://bugs.openjdk.java.net/browse/JDK-8146293) supports these algorithms natively.

### 0.10.0

This is a fairly large feature enhancement release that enables the following:
Expand Down
53 changes: 25 additions & 28 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,17 +84,17 @@ enforcement.
* HS256: HMAC using SHA-256
* HS384: HMAC using SHA-384
* HS512: HMAC using SHA-512
* ES256: ECDSA using P-256 and SHA-256
* ES384: ECDSA using P-384 and SHA-384
* ES512: ECDSA using P-521 and SHA-512
* RS256: RSASSA-PKCS-v1_5 using SHA-256
* RS384: RSASSA-PKCS-v1_5 using SHA-384
* RS512: RSASSA-PKCS-v1_5 using SHA-512
* PS256: RSASSA-PSS using SHA-256 and MGF1 with SHA-256<sup>1</sup>
* PS384: RSASSA-PSS using SHA-384 and MGF1 with SHA-384<sup>1</sup>
* PS512: RSASSA-PSS using SHA-512 and MGF1 with SHA-512<sup>1</sup>
* ES256: ECDSA using P-256 and SHA-256<sup>1</sup>
* ES384: ECDSA using P-384 and SHA-384<sup>1</sup>
* ES512: ECDSA using P-521 and SHA-512<sup>1</sup>

<sup>1. Requires a compatible JCA Provider (like BouncyCastle) in the runtime classpath.</sup>
<sup>1. Requires JDK 11 or a compatible JCA Provider (like BouncyCastle) in the runtime classpath.</sup>
* Convenience enhancements beyond the specification such as
* Body compression for any large JWT, not just JWEs
* Claims assertions (requiring specific values)
Expand Down Expand Up @@ -179,22 +179,21 @@ If you're building a (non-Android) JDK project, you will want to define the foll
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>0.10.0</version>
<version>0.10.1</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>0.10.0</version>
<version>0.10.1</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<version>0.10.0</version>
<version>0.10.1</version>
<scope>runtime</scope>
</dependency>
<!-- Uncomment this next dependency if you want to use Elliptic Curve (ES256, ES384, ES512)
or RSASSA-PSS (PS256, PS384, PS512) algorithms:
<!-- Uncomment this next dependency if you want to use RSASSA-PSS (PS256, PS384, PS512) algorithms:
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
Expand All @@ -205,18 +204,16 @@ If you're building a (non-Android) JDK project, you will want to define the foll

```

Note: The above `jjwt-jackson` dependency requires Jackson 2.x.

<a name="install-jdk-gradle"></a>
#### Gradle

```groovy
dependencies {
compile 'io.jsonwebtoken:jjwt-api:0.10.0'
runtime 'io.jsonwebtoken:jjwt-impl:0.10.0',
// Uncomment the next line if you want to use Elliptic Curve or RSASSA-PSS algorithms:
compile 'io.jsonwebtoken:jjwt-api:0.10.1'
runtime 'io.jsonwebtoken:jjwt-impl:0.10.1',
// Uncomment the next line if you want to use RSASSA-PSS (PS256, PS384, PS512) algorithms:
//'org.bouncycastle:bcprov-jdk15on:1.60',
'io.jsonwebtoken:jjwt-jackson:0.10.0'
'io.jsonwebtoken:jjwt-jackson:0.10.1'
}
```

Expand All @@ -232,12 +229,12 @@ Add the dependencies to your project:

```groovy
dependencies {
compile 'io.jsonwebtoken:jjwt-api:0.10.0'
runtime 'io.jsonwebtoken:jjwt-impl:0.10.0'
runtime('io.jsonwebtoken:jjwt-orgjson:0.10.0') {
compile 'io.jsonwebtoken:jjwt-api:0.10.1'
runtime 'io.jsonwebtoken:jjwt-impl:0.10.1'
runtime('io.jsonwebtoken:jjwt-orgjson:0.10.1') {
exclude group: 'org.json', module: 'json' //provided by Android natively
}
// Uncomment the next line if you want to use Elliptic Curve or RSASSA-PSS algorithms:
// Uncomment the next line if you want to use RSASSA-PSS (PS256, PS384, PS512) algorithms:
//runtime 'org.bouncycastle:bcprov-jdk15on:1.60'
}
```
Expand Down Expand Up @@ -433,15 +430,15 @@ key algorithms - identified by the following names:
* `HS256`: HMAC using SHA-256
* `HS384`: HMAC using SHA-384
* `HS512`: HMAC using SHA-512
* `ES256`: ECDSA using P-256 and SHA-256
* `ES384`: ECDSA using P-384 and SHA-384
* `ES512`: ECDSA using P-521 and SHA-512
* `RS256`: RSASSA-PKCS-v1_5 using SHA-256
* `RS384`: RSASSA-PKCS-v1_5 using SHA-384
* `RS512`: RSASSA-PKCS-v1_5 using SHA-512
* `PS256`: RSASSA-PSS using SHA-256 and MGF1 with SHA-256
* `PS384`: RSASSA-PSS using SHA-384 and MGF1 with SHA-384
* `PS512`: RSASSA-PSS using SHA-512 and MGF1 with SHA-512
* `ES256`: ECDSA using P-256 and SHA-256
* `ES384`: ECDSA using P-384 and SHA-384
* `ES512`: ECDSA using P-521 and SHA-512

These are all represented in the `io.jsonwebtoken.SignatureAlgorithm` enum.

Expand Down Expand Up @@ -549,10 +546,10 @@ KeyPair keyPair = Keys.keyPairFor(SignatureAlgorithm.RS256); //or RS384, RS512,
You use the private key (`keyPair.getPrivate()`) to create a JWS and the public key (`keyPair.getPublic()`) to
parse/verify a JWS.

**NOTE: The `PS256`, `PS384`, `PS512`, `ES256`, `ES384`, and `ES512` algorithms are not provided by the JDK by
default.** If you want to use them, you must enable a JCA provider in the JDK that supports those algorithms
(such as BouncyCastle). See the [Installation](#Installation) section to see how to enable BouncyCastle if you want
to usse these algorithms.
**NOTE: The `PS256`, `PS384`, and `PS512` algorithms require JDK 11 or a compatible JCA Provider
(like BouncyCastle) in the runtime classpath.** If you are using JDK 10 or earlier and you want to use them, see
the [Installation](#Installation) section to see how to enable BouncyCastle. All other algorithms are natively
supported by the JDK.

<a name="jws-create"></a>
### Creating a JWS
Expand Down Expand Up @@ -1195,7 +1192,7 @@ scope which is the typical JJWT default). That is:
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<version>0.10.0</version>
<version>0.10.1</version>
<scope>compile</scope> <!-- Not runtime -->
</dependency>
```
Expand All @@ -1204,7 +1201,7 @@ scope which is the typical JJWT default). That is:
```groovy
dependencies {
compile 'io.jsonwebtoken:jjwt-jackson:0.10.0'
compile 'io.jsonwebtoken:jjwt-jackson:0.10.1'
}
```
Expand Down
2 changes: 1 addition & 1 deletion api/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
<parent>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-root</artifactId>
<version>0.11.0-SNAPSHOT</version>
<version>0.10.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

Expand Down
23 changes: 6 additions & 17 deletions api/src/main/java/io/jsonwebtoken/SignatureAlgorithm.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
*/
package io.jsonwebtoken;

import io.jsonwebtoken.lang.RuntimeEnvironment;
import io.jsonwebtoken.security.InvalidKeyException;
import io.jsonwebtoken.security.Keys;
import io.jsonwebtoken.security.SignatureException;
Expand Down Expand Up @@ -74,25 +73,19 @@ public enum SignatureAlgorithm {
RS512("RS512", "RSASSA-PKCS-v1_5 using SHA-512", "RSA", "SHA512withRSA", true, 512, 2048),

/**
* JWA algorithm name for {@code ECDSA using P-256 and SHA-256}. <b>This is not a JDK standard algorithm and
* requires that a JCA provider like BouncyCastle be in the runtime classpath.</b> BouncyCastle will be used
* automatically if found in the runtime classpath.
* JWA algorithm name for {@code ECDSA using P-256 and SHA-256}
*/
ES256("ES256", "ECDSA using P-256 and SHA-256", "ECDSA", "SHA256withECDSA", false, 256, 256),
ES256("ES256", "ECDSA using P-256 and SHA-256", "ECDSA", "SHA256withECDSA", true, 256, 256),

/**
* JWA algorithm name for {@code ECDSA using P-384 and SHA-384}. <b>This is not a JDK standard algorithm and
* requires that a JCA provider like BouncyCastle be in the runtime classpath.</b> BouncyCastle will be used
* automatically if found in the runtime classpath.
* JWA algorithm name for {@code ECDSA using P-384 and SHA-384}
*/
ES384("ES384", "ECDSA using P-384 and SHA-384", "ECDSA", "SHA384withECDSA", false, 384, 384),
ES384("ES384", "ECDSA using P-384 and SHA-384", "ECDSA", "SHA384withECDSA", true, 384, 384),

/**
* JWA algorithm name for {@code ECDSA using P-521 and SHA-512}. <b>This is not a JDK standard algorithm and
* requires that a JCA provider like BouncyCastle be in the runtime classpath.</b> BouncyCastle will be used
* automatically if found in the runtime classpath.
* JWA algorithm name for {@code ECDSA using P-521 and SHA-512}
*/
ES512("ES512", "ECDSA using P-521 and SHA-512", "ECDSA", "SHA512withECDSA", false, 512, 521),
ES512("ES512", "ECDSA using P-521 and SHA-512", "ECDSA", "SHA512withECDSA", true, 512, 521),

/**
* JWA algorithm name for {@code RSASSA-PSS using SHA-256 and MGF1 with SHA-256}. <b>This is not a JDK standard
Expand All @@ -115,10 +108,6 @@ public enum SignatureAlgorithm {
*/
PS512("PS512", "RSASSA-PSS using SHA-512 and MGF1 with SHA-512", "RSA", "SHA512withRSAandMGF1", false, 512, 2048);

static {
RuntimeEnvironment.enableBouncyCastleIfPossible();
}

//purposefully ordered higher to lower:
private static final List<SignatureAlgorithm> PREFERRED_HMAC_ALGS = Collections.unmodifiableList(Arrays.asList(
SignatureAlgorithm.HS512, SignatureAlgorithm.HS384, SignatureAlgorithm.HS256));
Expand Down
9 changes: 0 additions & 9 deletions api/src/test/groovy/io/jsonwebtoken/JwtsTest.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -160,17 +160,8 @@ class JwtsTest {

mockStatic(Classes)

//JwtBuilder loads SignatureAlgorithm which in turn uses RuntimeEnvironment which in turn checks for BC:
expect(Classes.isAvailable(eq("org.bouncycastle.jce.provider.BouncyCastleProvider"))).andReturn(false)

replay Classes

def instance = createMock(JwtBuilder)

verify Classes

reset Classes

expect(Classes.newInstance(eq("io.jsonwebtoken.impl.DefaultJwtBuilder"))).andReturn(instance)

replay Classes, instance
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ class SignatureAlgorithmTest {
@Test
void testIsJdkStandard() {
for (SignatureAlgorithm alg : SignatureAlgorithm.values()) {
if (alg.name().startsWith("ES") || alg.name().startsWith("PS") || alg == SignatureAlgorithm.NONE) {
if (alg.name().startsWith("PS") || alg == SignatureAlgorithm.NONE) {
assertFalse alg.isJdkStandard()
} else {
assertTrue alg.isJdkStandard()
Expand Down
2 changes: 1 addition & 1 deletion extensions/jackson/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
<parent>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-root</artifactId>
<version>0.11.0-SNAPSHOT</version>
<version>0.10.1-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>

Expand Down
2 changes: 1 addition & 1 deletion extensions/orgjson/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
<parent>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-root</artifactId>
<version>0.11.0-SNAPSHOT</version>
<version>0.10.1-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>

Expand Down
2 changes: 1 addition & 1 deletion extensions/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
<parent>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-root</artifactId>
<version>0.11.0-SNAPSHOT</version>
<version>0.10.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

Expand Down
5 changes: 3 additions & 2 deletions impl/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
<parent>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-root</artifactId>
<version>0.11.0-SNAPSHOT</version>
<version>0.10.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

Expand All @@ -38,11 +38,12 @@
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
</dependency>

<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<scope>test</scope>
</dependency>

<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
Expand Down
Loading

0 comments on commit 7f66262

Please sign in to comment.