mirror of https://github.com/jwtk/jjwt.git
Ensured BouncyCastle was optional. Also ensured EllipticCurve algorithms 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 #372
This commit is contained in:
parent
b58e1b6dc5
commit
7f662627cc
|
@ -3,13 +3,16 @@
|
||||||
#sudo: required
|
#sudo: required
|
||||||
language: java
|
language: java
|
||||||
jdk:
|
jdk:
|
||||||
- openjdk7
|
- oraclejdk7
|
||||||
- oraclejdk8
|
- oraclejdk8
|
||||||
- oraclejdk9
|
- oraclejdk9
|
||||||
- oraclejdk10
|
- oraclejdk10
|
||||||
- openjdk10
|
- openjdk10
|
||||||
|
|
||||||
before_install:
|
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')"
|
- export BUILD_COVERAGE="$([ $TRAVIS_JDK_VERSION == 'oraclejdk8' ] && echo 'true')"
|
||||||
|
|
||||||
install: true
|
install: true
|
||||||
|
|
11
CHANGELOG.md
11
CHANGELOG.md
|
@ -1,5 +1,16 @@
|
||||||
## Release Notes
|
## 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
|
### 0.10.0
|
||||||
|
|
||||||
This is a fairly large feature enhancement release that enables the following:
|
This is a fairly large feature enhancement release that enables the following:
|
||||||
|
|
53
README.md
53
README.md
|
@ -84,17 +84,17 @@ enforcement.
|
||||||
* HS256: HMAC using SHA-256
|
* HS256: HMAC using SHA-256
|
||||||
* HS384: HMAC using SHA-384
|
* HS384: HMAC using SHA-384
|
||||||
* HS512: HMAC using SHA-512
|
* 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
|
* RS256: RSASSA-PKCS-v1_5 using SHA-256
|
||||||
* RS384: RSASSA-PKCS-v1_5 using SHA-384
|
* RS384: RSASSA-PKCS-v1_5 using SHA-384
|
||||||
* RS512: RSASSA-PKCS-v1_5 using SHA-512
|
* RS512: RSASSA-PKCS-v1_5 using SHA-512
|
||||||
* PS256: RSASSA-PSS using SHA-256 and MGF1 with SHA-256<sup>1</sup>
|
* 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>
|
* 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>
|
* 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
|
* Convenience enhancements beyond the specification such as
|
||||||
* Body compression for any large JWT, not just JWEs
|
* Body compression for any large JWT, not just JWEs
|
||||||
* Claims assertions (requiring specific values)
|
* Claims assertions (requiring specific values)
|
||||||
|
@ -179,22 +179,21 @@ If you're building a (non-Android) JDK project, you will want to define the foll
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>io.jsonwebtoken</groupId>
|
<groupId>io.jsonwebtoken</groupId>
|
||||||
<artifactId>jjwt-api</artifactId>
|
<artifactId>jjwt-api</artifactId>
|
||||||
<version>0.10.0</version>
|
<version>0.10.1</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>io.jsonwebtoken</groupId>
|
<groupId>io.jsonwebtoken</groupId>
|
||||||
<artifactId>jjwt-impl</artifactId>
|
<artifactId>jjwt-impl</artifactId>
|
||||||
<version>0.10.0</version>
|
<version>0.10.1</version>
|
||||||
<scope>runtime</scope>
|
<scope>runtime</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>io.jsonwebtoken</groupId>
|
<groupId>io.jsonwebtoken</groupId>
|
||||||
<artifactId>jjwt-jackson</artifactId>
|
<artifactId>jjwt-jackson</artifactId>
|
||||||
<version>0.10.0</version>
|
<version>0.10.1</version>
|
||||||
<scope>runtime</scope>
|
<scope>runtime</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<!-- Uncomment this next dependency if you want to use Elliptic Curve (ES256, ES384, ES512)
|
<!-- Uncomment this next dependency if you want to use RSASSA-PSS (PS256, PS384, PS512) algorithms:
|
||||||
or RSASSA-PSS (PS256, PS384, PS512) algorithms:
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.bouncycastle</groupId>
|
<groupId>org.bouncycastle</groupId>
|
||||||
<artifactId>bcprov-jdk15on</artifactId>
|
<artifactId>bcprov-jdk15on</artifactId>
|
||||||
|
@ -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>
|
<a name="install-jdk-gradle"></a>
|
||||||
#### Gradle
|
#### Gradle
|
||||||
|
|
||||||
```groovy
|
```groovy
|
||||||
dependencies {
|
dependencies {
|
||||||
compile 'io.jsonwebtoken:jjwt-api:0.10.0'
|
compile 'io.jsonwebtoken:jjwt-api:0.10.1'
|
||||||
runtime 'io.jsonwebtoken:jjwt-impl:0.10.0',
|
runtime 'io.jsonwebtoken:jjwt-impl:0.10.1',
|
||||||
// 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:
|
||||||
//'org.bouncycastle:bcprov-jdk15on:1.60',
|
//'org.bouncycastle:bcprov-jdk15on:1.60',
|
||||||
'io.jsonwebtoken:jjwt-jackson:0.10.0'
|
'io.jsonwebtoken:jjwt-jackson:0.10.1'
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -232,12 +229,12 @@ Add the dependencies to your project:
|
||||||
|
|
||||||
```groovy
|
```groovy
|
||||||
dependencies {
|
dependencies {
|
||||||
compile 'io.jsonwebtoken:jjwt-api:0.10.0'
|
compile 'io.jsonwebtoken:jjwt-api:0.10.1'
|
||||||
runtime 'io.jsonwebtoken:jjwt-impl:0.10.0'
|
runtime 'io.jsonwebtoken:jjwt-impl:0.10.1'
|
||||||
runtime('io.jsonwebtoken:jjwt-orgjson:0.10.0') {
|
runtime('io.jsonwebtoken:jjwt-orgjson:0.10.1') {
|
||||||
exclude group: 'org.json', module: 'json' //provided by Android natively
|
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'
|
//runtime 'org.bouncycastle:bcprov-jdk15on:1.60'
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
@ -433,15 +430,15 @@ key algorithms - identified by the following names:
|
||||||
* `HS256`: HMAC using SHA-256
|
* `HS256`: HMAC using SHA-256
|
||||||
* `HS384`: HMAC using SHA-384
|
* `HS384`: HMAC using SHA-384
|
||||||
* `HS512`: HMAC using SHA-512
|
* `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
|
* `RS256`: RSASSA-PKCS-v1_5 using SHA-256
|
||||||
* `RS384`: RSASSA-PKCS-v1_5 using SHA-384
|
* `RS384`: RSASSA-PKCS-v1_5 using SHA-384
|
||||||
* `RS512`: RSASSA-PKCS-v1_5 using SHA-512
|
* `RS512`: RSASSA-PKCS-v1_5 using SHA-512
|
||||||
* `PS256`: RSASSA-PSS using SHA-256 and MGF1 with SHA-256
|
* `PS256`: RSASSA-PSS using SHA-256 and MGF1 with SHA-256
|
||||||
* `PS384`: RSASSA-PSS using SHA-384 and MGF1 with SHA-384
|
* `PS384`: RSASSA-PSS using SHA-384 and MGF1 with SHA-384
|
||||||
* `PS512`: RSASSA-PSS using SHA-512 and MGF1 with SHA-512
|
* `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.
|
These are all represented in the `io.jsonwebtoken.SignatureAlgorithm` enum.
|
||||||
|
|
||||||
|
@ -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
|
You use the private key (`keyPair.getPrivate()`) to create a JWS and the public key (`keyPair.getPublic()`) to
|
||||||
parse/verify a JWS.
|
parse/verify a JWS.
|
||||||
|
|
||||||
**NOTE: The `PS256`, `PS384`, `PS512`, `ES256`, `ES384`, and `ES512` algorithms are not provided by the JDK by
|
**NOTE: The `PS256`, `PS384`, and `PS512` algorithms require JDK 11 or a compatible JCA Provider
|
||||||
default.** If you want to use them, you must enable a JCA provider in the JDK that supports those algorithms
|
(like BouncyCastle) in the runtime classpath.** If you are using JDK 10 or earlier and you want to use them, see
|
||||||
(such as BouncyCastle). See the [Installation](#Installation) section to see how to enable BouncyCastle if you want
|
the [Installation](#Installation) section to see how to enable BouncyCastle. All other algorithms are natively
|
||||||
to usse these algorithms.
|
supported by the JDK.
|
||||||
|
|
||||||
<a name="jws-create"></a>
|
<a name="jws-create"></a>
|
||||||
### Creating a JWS
|
### Creating a JWS
|
||||||
|
@ -1195,7 +1192,7 @@ scope which is the typical JJWT default). That is:
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>io.jsonwebtoken</groupId>
|
<groupId>io.jsonwebtoken</groupId>
|
||||||
<artifactId>jjwt-jackson</artifactId>
|
<artifactId>jjwt-jackson</artifactId>
|
||||||
<version>0.10.0</version>
|
<version>0.10.1</version>
|
||||||
<scope>compile</scope> <!-- Not runtime -->
|
<scope>compile</scope> <!-- Not runtime -->
|
||||||
</dependency>
|
</dependency>
|
||||||
```
|
```
|
||||||
|
@ -1204,7 +1201,7 @@ scope which is the typical JJWT default). That is:
|
||||||
|
|
||||||
```groovy
|
```groovy
|
||||||
dependencies {
|
dependencies {
|
||||||
compile 'io.jsonwebtoken:jjwt-jackson:0.10.0'
|
compile 'io.jsonwebtoken:jjwt-jackson:0.10.1'
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>io.jsonwebtoken</groupId>
|
<groupId>io.jsonwebtoken</groupId>
|
||||||
<artifactId>jjwt-root</artifactId>
|
<artifactId>jjwt-root</artifactId>
|
||||||
<version>0.11.0-SNAPSHOT</version>
|
<version>0.10.1-SNAPSHOT</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,6 @@
|
||||||
*/
|
*/
|
||||||
package io.jsonwebtoken;
|
package io.jsonwebtoken;
|
||||||
|
|
||||||
import io.jsonwebtoken.lang.RuntimeEnvironment;
|
|
||||||
import io.jsonwebtoken.security.InvalidKeyException;
|
import io.jsonwebtoken.security.InvalidKeyException;
|
||||||
import io.jsonwebtoken.security.Keys;
|
import io.jsonwebtoken.security.Keys;
|
||||||
import io.jsonwebtoken.security.SignatureException;
|
import io.jsonwebtoken.security.SignatureException;
|
||||||
|
@ -74,25 +73,19 @@ public enum SignatureAlgorithm {
|
||||||
RS512("RS512", "RSASSA-PKCS-v1_5 using SHA-512", "RSA", "SHA512withRSA", true, 512, 2048),
|
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
|
* JWA algorithm name for {@code ECDSA using P-256 and SHA-256}
|
||||||
* requires that a JCA provider like BouncyCastle be in the runtime classpath.</b> BouncyCastle will be used
|
|
||||||
* automatically if found in the runtime classpath.
|
|
||||||
*/
|
*/
|
||||||
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
|
* JWA algorithm name for {@code ECDSA using P-384 and SHA-384}
|
||||||
* requires that a JCA provider like BouncyCastle be in the runtime classpath.</b> BouncyCastle will be used
|
|
||||||
* automatically if found in the runtime classpath.
|
|
||||||
*/
|
*/
|
||||||
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
|
* JWA algorithm name for {@code ECDSA using P-521 and SHA-512}
|
||||||
* requires that a JCA provider like BouncyCastle be in the runtime classpath.</b> BouncyCastle will be used
|
|
||||||
* automatically if found in the runtime classpath.
|
|
||||||
*/
|
*/
|
||||||
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
|
* JWA algorithm name for {@code RSASSA-PSS using SHA-256 and MGF1 with SHA-256}. <b>This is not a JDK standard
|
||||||
|
@ -115,10 +108,6 @@ public enum SignatureAlgorithm {
|
||||||
*/
|
*/
|
||||||
PS512("PS512", "RSASSA-PSS using SHA-512 and MGF1 with SHA-512", "RSA", "SHA512withRSAandMGF1", false, 512, 2048);
|
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:
|
//purposefully ordered higher to lower:
|
||||||
private static final List<SignatureAlgorithm> PREFERRED_HMAC_ALGS = Collections.unmodifiableList(Arrays.asList(
|
private static final List<SignatureAlgorithm> PREFERRED_HMAC_ALGS = Collections.unmodifiableList(Arrays.asList(
|
||||||
SignatureAlgorithm.HS512, SignatureAlgorithm.HS384, SignatureAlgorithm.HS256));
|
SignatureAlgorithm.HS512, SignatureAlgorithm.HS384, SignatureAlgorithm.HS256));
|
||||||
|
|
|
@ -160,17 +160,8 @@ class JwtsTest {
|
||||||
|
|
||||||
mockStatic(Classes)
|
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)
|
def instance = createMock(JwtBuilder)
|
||||||
|
|
||||||
verify Classes
|
|
||||||
|
|
||||||
reset Classes
|
|
||||||
|
|
||||||
expect(Classes.newInstance(eq("io.jsonwebtoken.impl.DefaultJwtBuilder"))).andReturn(instance)
|
expect(Classes.newInstance(eq("io.jsonwebtoken.impl.DefaultJwtBuilder"))).andReturn(instance)
|
||||||
|
|
||||||
replay Classes, instance
|
replay Classes, instance
|
||||||
|
|
|
@ -121,7 +121,7 @@ class SignatureAlgorithmTest {
|
||||||
@Test
|
@Test
|
||||||
void testIsJdkStandard() {
|
void testIsJdkStandard() {
|
||||||
for (SignatureAlgorithm alg : SignatureAlgorithm.values()) {
|
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()
|
assertFalse alg.isJdkStandard()
|
||||||
} else {
|
} else {
|
||||||
assertTrue alg.isJdkStandard()
|
assertTrue alg.isJdkStandard()
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>io.jsonwebtoken</groupId>
|
<groupId>io.jsonwebtoken</groupId>
|
||||||
<artifactId>jjwt-root</artifactId>
|
<artifactId>jjwt-root</artifactId>
|
||||||
<version>0.11.0-SNAPSHOT</version>
|
<version>0.10.1-SNAPSHOT</version>
|
||||||
<relativePath>../../pom.xml</relativePath>
|
<relativePath>../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>io.jsonwebtoken</groupId>
|
<groupId>io.jsonwebtoken</groupId>
|
||||||
<artifactId>jjwt-root</artifactId>
|
<artifactId>jjwt-root</artifactId>
|
||||||
<version>0.11.0-SNAPSHOT</version>
|
<version>0.10.1-SNAPSHOT</version>
|
||||||
<relativePath>../../pom.xml</relativePath>
|
<relativePath>../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>io.jsonwebtoken</groupId>
|
<groupId>io.jsonwebtoken</groupId>
|
||||||
<artifactId>jjwt-root</artifactId>
|
<artifactId>jjwt-root</artifactId>
|
||||||
<version>0.11.0-SNAPSHOT</version>
|
<version>0.10.1-SNAPSHOT</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>io.jsonwebtoken</groupId>
|
<groupId>io.jsonwebtoken</groupId>
|
||||||
<artifactId>jjwt-root</artifactId>
|
<artifactId>jjwt-root</artifactId>
|
||||||
<version>0.11.0-SNAPSHOT</version>
|
<version>0.10.1-SNAPSHOT</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
@ -38,11 +38,12 @@
|
||||||
<groupId>io.jsonwebtoken</groupId>
|
<groupId>io.jsonwebtoken</groupId>
|
||||||
<artifactId>jjwt-api</artifactId>
|
<artifactId>jjwt-api</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.bouncycastle</groupId>
|
<groupId>org.bouncycastle</groupId>
|
||||||
<artifactId>bcprov-jdk15on</artifactId>
|
<artifactId>bcprov-jdk15on</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>io.jsonwebtoken</groupId>
|
<groupId>io.jsonwebtoken</groupId>
|
||||||
<artifactId>jjwt-jackson</artifactId>
|
<artifactId>jjwt-jackson</artifactId>
|
||||||
|
|
|
@ -18,11 +18,13 @@ package io.jsonwebtoken.impl.crypto;
|
||||||
import io.jsonwebtoken.JwtException;
|
import io.jsonwebtoken.JwtException;
|
||||||
import io.jsonwebtoken.SignatureAlgorithm;
|
import io.jsonwebtoken.SignatureAlgorithm;
|
||||||
import io.jsonwebtoken.lang.Assert;
|
import io.jsonwebtoken.lang.Assert;
|
||||||
|
import io.jsonwebtoken.lang.Strings;
|
||||||
|
|
||||||
import java.security.Key;
|
import java.security.Key;
|
||||||
import java.security.KeyPair;
|
import java.security.KeyPair;
|
||||||
import java.security.KeyPairGenerator;
|
import java.security.KeyPairGenerator;
|
||||||
import java.security.SecureRandom;
|
import java.security.SecureRandom;
|
||||||
|
import java.security.spec.ECGenParameterSpec;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
@ -85,10 +87,8 @@ public abstract class EllipticCurveProvider extends SignatureProvider {
|
||||||
* Generates a new secure-random key pair of sufficient strength for the specified Elliptic Curve {@link
|
* Generates a new secure-random key pair of sufficient strength for the specified Elliptic Curve {@link
|
||||||
* SignatureAlgorithm} (must be one of {@code ES256}, {@code ES384} or {@code ES512}) using the specified {@link
|
* SignatureAlgorithm} (must be one of {@code ES256}, {@code ES384} or {@code ES512}) using the specified {@link
|
||||||
* SecureRandom} random number generator. This is a convenience method that immediately delegates to {@link
|
* SecureRandom} random number generator. This is a convenience method that immediately delegates to {@link
|
||||||
* #generateKeyPair(String, String, SignatureAlgorithm, SecureRandom)} using {@code "ECDSA"} as the {@code
|
* #generateKeyPair(String, String, SignatureAlgorithm, SecureRandom)} using {@code "EC"} as the {@code
|
||||||
* jcaAlgorithmName} and {@code "BC"} as the {@code jcaProviderName} since EllipticCurve requires the use of an
|
* jcaAlgorithmName}.
|
||||||
* external JCA provider ({@code BC stands for BouncyCastle}. This will work as expected as long as the
|
|
||||||
* BouncyCastle dependency is in the runtime classpath.
|
|
||||||
*
|
*
|
||||||
* @param alg alg the algorithm indicating strength, must be one of {@code ES256}, {@code ES384} or {@code
|
* @param alg alg the algorithm indicating strength, must be one of {@code ES256}, {@code ES384} or {@code
|
||||||
* ES512}
|
* ES512}
|
||||||
|
@ -101,7 +101,7 @@ public abstract class EllipticCurveProvider extends SignatureProvider {
|
||||||
* @see #generateKeyPair(String, String, SignatureAlgorithm, SecureRandom)
|
* @see #generateKeyPair(String, String, SignatureAlgorithm, SecureRandom)
|
||||||
*/
|
*/
|
||||||
public static KeyPair generateKeyPair(SignatureAlgorithm alg, SecureRandom random) {
|
public static KeyPair generateKeyPair(SignatureAlgorithm alg, SecureRandom random) {
|
||||||
return generateKeyPair("ECDSA", "BC", alg, random);
|
return generateKeyPair("EC", null, alg, random);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -111,8 +111,8 @@ public abstract class EllipticCurveProvider extends SignatureProvider {
|
||||||
*
|
*
|
||||||
* @param jcaAlgorithmName the JCA name of the algorithm to use for key pair generation, for example, {@code
|
* @param jcaAlgorithmName the JCA name of the algorithm to use for key pair generation, for example, {@code
|
||||||
* ECDSA}.
|
* ECDSA}.
|
||||||
* @param jcaProviderName the JCA provider name of the algorithm implementation, for example {@code BC} for
|
* @param jcaProviderName the JCA provider name of the algorithm implementation (for example {@code "BC"} for
|
||||||
* BouncyCastle.
|
* BouncyCastle) or {@code null} if the default provider should be used.
|
||||||
* @param alg alg the algorithm indicating strength, must be one of {@code ES256}, {@code ES384} or
|
* @param alg alg the algorithm indicating strength, must be one of {@code ES256}, {@code ES384} or
|
||||||
* {@code ES512}
|
* {@code ES512}
|
||||||
* @param random the SecureRandom generator to use during key generation.
|
* @param random the SecureRandom generator to use during key generation.
|
||||||
|
@ -128,9 +128,17 @@ public abstract class EllipticCurveProvider extends SignatureProvider {
|
||||||
Assert.notNull(alg, "SignatureAlgorithm argument cannot be null.");
|
Assert.notNull(alg, "SignatureAlgorithm argument cannot be null.");
|
||||||
Assert.isTrue(alg.isEllipticCurve(), "SignatureAlgorithm argument must represent an Elliptic Curve algorithm.");
|
Assert.isTrue(alg.isEllipticCurve(), "SignatureAlgorithm argument must represent an Elliptic Curve algorithm.");
|
||||||
try {
|
try {
|
||||||
KeyPairGenerator g = KeyPairGenerator.getInstance(jcaAlgorithmName, jcaProviderName);
|
KeyPairGenerator g;
|
||||||
|
|
||||||
|
if (Strings.hasText(jcaProviderName)) {
|
||||||
|
g = KeyPairGenerator.getInstance(jcaAlgorithmName, jcaProviderName);
|
||||||
|
} else {
|
||||||
|
g = KeyPairGenerator.getInstance(jcaAlgorithmName);
|
||||||
|
}
|
||||||
|
|
||||||
String paramSpecCurveName = EC_CURVE_NAMES.get(alg);
|
String paramSpecCurveName = EC_CURVE_NAMES.get(alg);
|
||||||
g.initialize(org.bouncycastle.jce.ECNamedCurveTable.getParameterSpec(paramSpecCurveName), random);
|
ECGenParameterSpec spec = new ECGenParameterSpec(paramSpecCurveName);
|
||||||
|
g.initialize(spec, random);
|
||||||
return g.generateKeyPair();
|
return g.generateKeyPair();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new IllegalStateException("Unable to generate Elliptic Curve KeyPair: " + e.getMessage(), e);
|
throw new IllegalStateException("Unable to generate Elliptic Curve KeyPair: " + e.getMessage(), e);
|
||||||
|
@ -143,18 +151,19 @@ public abstract class EllipticCurveProvider extends SignatureProvider {
|
||||||
*
|
*
|
||||||
* @param alg The ECDSA algorithm. Must be supported and not
|
* @param alg The ECDSA algorithm. Must be supported and not
|
||||||
* {@code null}.
|
* {@code null}.
|
||||||
*
|
|
||||||
* @return The expected byte array length for the signature.
|
* @return The expected byte array length for the signature.
|
||||||
*
|
|
||||||
* @throws JwtException If the algorithm is not supported.
|
* @throws JwtException If the algorithm is not supported.
|
||||||
*/
|
*/
|
||||||
public static int getSignatureByteArrayLength(final SignatureAlgorithm alg)
|
public static int getSignatureByteArrayLength(final SignatureAlgorithm alg)
|
||||||
throws JwtException {
|
throws JwtException {
|
||||||
|
|
||||||
switch (alg) {
|
switch (alg) {
|
||||||
case ES256: return 64;
|
case ES256:
|
||||||
case ES384: return 96;
|
return 64;
|
||||||
case ES512: return 132;
|
case ES384:
|
||||||
|
return 96;
|
||||||
|
case ES512:
|
||||||
|
return 132;
|
||||||
default:
|
default:
|
||||||
throw new JwtException("Unsupported Algorithm: " + alg.name());
|
throw new JwtException("Unsupported Algorithm: " + alg.name());
|
||||||
}
|
}
|
||||||
|
@ -167,9 +176,7 @@ public abstract class EllipticCurveProvider extends SignatureProvider {
|
||||||
*
|
*
|
||||||
* @param derSignature The ASN1./DER-encoded. Must not be {@code null}.
|
* @param derSignature The ASN1./DER-encoded. Must not be {@code null}.
|
||||||
* @param outputLength The expected length of the ECDSA JWS signature.
|
* @param outputLength The expected length of the ECDSA JWS signature.
|
||||||
*
|
|
||||||
* @return The ECDSA JWS encoded signature.
|
* @return The ECDSA JWS encoded signature.
|
||||||
*
|
|
||||||
* @throws JwtException If the ASN.1/DER signature format is invalid.
|
* @throws JwtException If the ASN.1/DER signature format is invalid.
|
||||||
*/
|
*/
|
||||||
public static byte[] transcodeSignatureToConcat(final byte[] derSignature, int outputLength) throws JwtException {
|
public static byte[] transcodeSignatureToConcat(final byte[] derSignature, int outputLength) throws JwtException {
|
||||||
|
@ -205,9 +212,9 @@ public abstract class EllipticCurveProvider extends SignatureProvider {
|
||||||
rawLen = Math.max(rawLen, outputLength / 2);
|
rawLen = Math.max(rawLen, outputLength / 2);
|
||||||
|
|
||||||
if ((derSignature[offset - 1] & 0xff) != derSignature.length - offset
|
if ((derSignature[offset - 1] & 0xff) != derSignature.length - offset
|
||||||
|| (derSignature[offset - 1] & 0xff) != 2 + rLength + 2 + sLength
|
|| (derSignature[offset - 1] & 0xff) != 2 + rLength + 2 + sLength
|
||||||
|| derSignature[offset] != 2
|
|| derSignature[offset] != 2
|
||||||
|| derSignature[offset + 2 + rLength] != 2) {
|
|| derSignature[offset + 2 + rLength] != 2) {
|
||||||
throw new JwtException("Invalid ECDSA signature format");
|
throw new JwtException("Invalid ECDSA signature format");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -220,7 +227,6 @@ public abstract class EllipticCurveProvider extends SignatureProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Transcodes the ECDSA JWS signature into ASN.1/DER format for use by
|
* Transcodes the ECDSA JWS signature into ASN.1/DER format for use by
|
||||||
* the JCA verifier.
|
* the JCA verifier.
|
||||||
|
@ -228,9 +234,7 @@ public abstract class EllipticCurveProvider extends SignatureProvider {
|
||||||
* @param jwsSignature The JWS signature, consisting of the
|
* @param jwsSignature The JWS signature, consisting of the
|
||||||
* concatenated R and S values. Must not be
|
* concatenated R and S values. Must not be
|
||||||
* {@code null}.
|
* {@code null}.
|
||||||
*
|
|
||||||
* @return The ASN.1/DER encoded signature.
|
* @return The ASN.1/DER encoded signature.
|
||||||
*
|
|
||||||
* @throws JwtException If the ECDSA JWS signature format is invalid.
|
* @throws JwtException If the ECDSA JWS signature format is invalid.
|
||||||
*/
|
*/
|
||||||
public static byte[] transcodeSignatureToDER(byte[] jwsSignature) throws JwtException {
|
public static byte[] transcodeSignatureToDER(byte[] jwsSignature) throws JwtException {
|
||||||
|
@ -239,7 +243,7 @@ public abstract class EllipticCurveProvider extends SignatureProvider {
|
||||||
|
|
||||||
int i = rawLen;
|
int i = rawLen;
|
||||||
|
|
||||||
while((i > 0) && (jwsSignature[rawLen - i] == 0)) {
|
while ((i > 0) && (jwsSignature[rawLen - i] == 0)) {
|
||||||
i--;
|
i--;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@ package io.jsonwebtoken.impl.crypto;
|
||||||
|
|
||||||
import io.jsonwebtoken.SignatureAlgorithm;
|
import io.jsonwebtoken.SignatureAlgorithm;
|
||||||
import io.jsonwebtoken.lang.Assert;
|
import io.jsonwebtoken.lang.Assert;
|
||||||
|
import io.jsonwebtoken.lang.RuntimeEnvironment;
|
||||||
import io.jsonwebtoken.security.SignatureException;
|
import io.jsonwebtoken.security.SignatureException;
|
||||||
|
|
||||||
import java.security.InvalidAlgorithmParameterException;
|
import java.security.InvalidAlgorithmParameterException;
|
||||||
|
@ -54,6 +55,10 @@ public abstract class RsaProvider extends SignatureProvider {
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static {
|
||||||
|
RuntimeEnvironment.enableBouncyCastleIfPossible(); //PS256, PS384, PS512 on <= JDK 10 require BC
|
||||||
|
}
|
||||||
|
|
||||||
protected RsaProvider(SignatureAlgorithm alg, Key key) {
|
protected RsaProvider(SignatureAlgorithm alg, Key key) {
|
||||||
super(alg, key);
|
super(alg, key);
|
||||||
Assert.isTrue(alg.isRsa(), "SignatureAlgorithm must be an RSASSA or RSASSA-PSS algorithm.");
|
Assert.isTrue(alg.isRsa(), "SignatureAlgorithm must be an RSASSA or RSASSA-PSS algorithm.");
|
||||||
|
|
|
@ -38,7 +38,7 @@ class EllipticCurveProviderTest {
|
||||||
@Test
|
@Test
|
||||||
void testGenerateKeyPairWithInvalidProviderName() {
|
void testGenerateKeyPairWithInvalidProviderName() {
|
||||||
try {
|
try {
|
||||||
EllipticCurveProvider.generateKeyPair("ECDSA", "Foo", SignatureAlgorithm.ES256, null)
|
EllipticCurveProvider.generateKeyPair("EC", "Foo", SignatureAlgorithm.ES256, null)
|
||||||
fail()
|
fail()
|
||||||
} catch (IllegalStateException ise) {
|
} catch (IllegalStateException ise) {
|
||||||
assertEquals ise.message, "Unable to generate Elliptic Curve KeyPair: no such provider: Foo"
|
assertEquals ise.message, "Unable to generate Elliptic Curve KeyPair: no such provider: Foo"
|
||||||
|
@ -49,7 +49,7 @@ class EllipticCurveProviderTest {
|
||||||
@Test
|
@Test
|
||||||
void testGenerateKeyPairWithNullAlgorithm() {
|
void testGenerateKeyPairWithNullAlgorithm() {
|
||||||
try {
|
try {
|
||||||
EllipticCurveProvider.generateKeyPair("ECDSA", "Foo", null, null)
|
EllipticCurveProvider.generateKeyPair("EC", "Foo", null, null)
|
||||||
fail()
|
fail()
|
||||||
} catch (IllegalArgumentException ise) {
|
} catch (IllegalArgumentException ise) {
|
||||||
assertEquals ise.message, "SignatureAlgorithm argument cannot be null."
|
assertEquals ise.message, "SignatureAlgorithm argument cannot be null."
|
||||||
|
@ -59,7 +59,7 @@ class EllipticCurveProviderTest {
|
||||||
@Test
|
@Test
|
||||||
void testGenerateKeyPairWithNonEllipticCurveAlgorithm() {
|
void testGenerateKeyPairWithNonEllipticCurveAlgorithm() {
|
||||||
try {
|
try {
|
||||||
EllipticCurveProvider.generateKeyPair("ECDSA", "Foo", SignatureAlgorithm.HS256, null)
|
EllipticCurveProvider.generateKeyPair("EC", "Foo", SignatureAlgorithm.HS256, null)
|
||||||
fail()
|
fail()
|
||||||
} catch (IllegalArgumentException ise) {
|
} catch (IllegalArgumentException ise) {
|
||||||
assertEquals ise.message, "SignatureAlgorithm argument must represent an Elliptic Curve algorithm."
|
assertEquals ise.message, "SignatureAlgorithm argument must represent an Elliptic Curve algorithm."
|
||||||
|
|
|
@ -19,7 +19,6 @@ import io.jsonwebtoken.JwtException
|
||||||
import io.jsonwebtoken.SignatureAlgorithm
|
import io.jsonwebtoken.SignatureAlgorithm
|
||||||
import io.jsonwebtoken.io.Decoders
|
import io.jsonwebtoken.io.Decoders
|
||||||
import io.jsonwebtoken.security.SignatureException
|
import io.jsonwebtoken.security.SignatureException
|
||||||
import org.bouncycastle.jce.provider.BouncyCastleProvider
|
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
|
|
||||||
import java.security.*
|
import java.security.*
|
||||||
|
@ -29,10 +28,6 @@ import static org.junit.Assert.*
|
||||||
|
|
||||||
class EllipticCurveSignatureValidatorTest {
|
class EllipticCurveSignatureValidatorTest {
|
||||||
|
|
||||||
static {
|
|
||||||
Security.addProvider(new BouncyCastleProvider())
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testDoVerifyWithInvalidKeyException() {
|
void testDoVerifyWithInvalidKeyException() {
|
||||||
|
|
||||||
|
@ -62,7 +57,7 @@ class EllipticCurveSignatureValidatorTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void ecdsaSignatureComplianceTest() {
|
void ecdsaSignatureComplianceTest() {
|
||||||
def fact = KeyFactory.getInstance("ECDSA", "BC");
|
def fact = KeyFactory.getInstance("EC");
|
||||||
def publicKey = "MIGbMBAGByqGSM49AgEGBSuBBAAjA4GGAAQASisgweVL1tAtIvfmpoqvdXF8sPKTV9YTKNxBwkdkm+/auh4pR8TbaIfsEzcsGUVv61DFNFXb0ozJfurQ59G2XcgAn3vROlSSnpbIvuhKrzL5jwWDTaYa5tVF1Zjwia/5HUhKBkcPuWGXg05nMjWhZfCuEetzMLoGcHmtvabugFrqsAg="
|
def publicKey = "MIGbMBAGByqGSM49AgEGBSuBBAAjA4GGAAQASisgweVL1tAtIvfmpoqvdXF8sPKTV9YTKNxBwkdkm+/auh4pR8TbaIfsEzcsGUVv61DFNFXb0ozJfurQ59G2XcgAn3vROlSSnpbIvuhKrzL5jwWDTaYa5tVF1Zjwia/5HUhKBkcPuWGXg05nMjWhZfCuEetzMLoGcHmtvabugFrqsAg="
|
||||||
def pub = fact.generatePublic(new X509EncodedKeySpec(Decoders.BASE64.decode(publicKey)))
|
def pub = fact.generatePublic(new X509EncodedKeySpec(Decoders.BASE64.decode(publicKey)))
|
||||||
def v = new EllipticCurveSignatureValidator(SignatureAlgorithm.ES512, pub)
|
def v = new EllipticCurveSignatureValidator(SignatureAlgorithm.ES512, pub)
|
||||||
|
@ -82,7 +77,7 @@ class EllipticCurveSignatureValidatorTest {
|
||||||
void legacySignatureCompatTest() {
|
void legacySignatureCompatTest() {
|
||||||
def withoutSignature = "eyJhbGciOiJFUzUxMiIsInR5cCI6IkpXVCJ9.eyJ0ZXN0IjoidGVzdCIsImlhdCI6MTQ2NzA2NTgyN30"
|
def withoutSignature = "eyJhbGciOiJFUzUxMiIsInR5cCI6IkpXVCJ9.eyJ0ZXN0IjoidGVzdCIsImlhdCI6MTQ2NzA2NTgyN30"
|
||||||
def keypair = EllipticCurveProvider.generateKeyPair()
|
def keypair = EllipticCurveProvider.generateKeyPair()
|
||||||
def signature = Signature.getInstance(SignatureAlgorithm.ES512.jcaName, "BC")
|
def signature = Signature.getInstance(SignatureAlgorithm.ES512.jcaName)
|
||||||
def data = withoutSignature.getBytes("US-ASCII")
|
def data = withoutSignature.getBytes("US-ASCII")
|
||||||
signature.initSign(keypair.private)
|
signature.initSign(keypair.private)
|
||||||
signature.update(data)
|
signature.update(data)
|
||||||
|
|
|
@ -47,7 +47,7 @@ class SignatureProviderTest {
|
||||||
@Test
|
@Test
|
||||||
void testCreateSignatureInstanceNoSuchAlgorithmNonStandardAlgorithm() {
|
void testCreateSignatureInstanceNoSuchAlgorithmNonStandardAlgorithm() {
|
||||||
|
|
||||||
def p = new SignatureProvider(SignatureAlgorithm.ES512, EllipticCurveProvider.generateKeyPair().getPublic()) {
|
def p = new SignatureProvider(SignatureAlgorithm.PS256, RsaProvider.generateKeyPair().getPrivate()) {
|
||||||
@Override
|
@Override
|
||||||
protected Signature getSignatureInstance() throws NoSuchAlgorithmException {
|
protected Signature getSignatureInstance() throws NoSuchAlgorithmException {
|
||||||
throw new NoSuchAlgorithmException('foo')
|
throw new NoSuchAlgorithmException('foo')
|
||||||
|
@ -65,7 +65,7 @@ class SignatureProviderTest {
|
||||||
@Test
|
@Test
|
||||||
void testCreateSignatureInstanceNoSuchAlgorithmNonStandardAlgorithmWithoutBouncyCastle() {
|
void testCreateSignatureInstanceNoSuchAlgorithmNonStandardAlgorithmWithoutBouncyCastle() {
|
||||||
|
|
||||||
def p = new SignatureProvider(SignatureAlgorithm.ES512, EllipticCurveProvider.generateKeyPair().getPublic()) {
|
def p = new SignatureProvider(SignatureAlgorithm.PS256, RsaProvider.generateKeyPair().getPrivate()) {
|
||||||
@Override
|
@Override
|
||||||
protected Signature getSignatureInstance() throws NoSuchAlgorithmException {
|
protected Signature getSignatureInstance() throws NoSuchAlgorithmException {
|
||||||
throw new NoSuchAlgorithmException('foo')
|
throw new NoSuchAlgorithmException('foo')
|
||||||
|
@ -81,7 +81,7 @@ class SignatureProviderTest {
|
||||||
p.createSignatureInstance()
|
p.createSignatureInstance()
|
||||||
fail()
|
fail()
|
||||||
} catch (SignatureException se) {
|
} catch (SignatureException se) {
|
||||||
assertTrue se.message.contains('Try including BouncyCastle in the runtime classpath')
|
assertTrue se.message.contains('This is not a standard JDK algorithm. Try including BouncyCastle in the runtime classpath.')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -71,18 +71,21 @@ class KeysImplTest {
|
||||||
KeyPair pair = Keys.keyPairFor(alg);
|
KeyPair pair = Keys.keyPairFor(alg);
|
||||||
assertNotNull pair
|
assertNotNull pair
|
||||||
|
|
||||||
String asn1oid = "secp${alg.minKeyLength}r1"
|
int len = alg.minKeyLength
|
||||||
|
String asn1oid = "secp${len}r1"
|
||||||
|
String suffix = len == 256 ? ", X9.62 prime${len}v1" : '' //the JDK only adds this extra suffix to the secp256r1 curve name and not secp384r1 or secp521r1 curve names
|
||||||
|
String jdkParamName = "$asn1oid [NIST P-${len}${suffix}]" as String
|
||||||
|
|
||||||
PublicKey pub = pair.getPublic()
|
PublicKey pub = pair.getPublic()
|
||||||
assert pub instanceof ECPublicKey
|
assert pub instanceof ECPublicKey
|
||||||
assertEquals "ECDSA", pub.algorithm
|
assertEquals "EC", pub.algorithm
|
||||||
assertEquals asn1oid, pub.params.name
|
assertEquals jdkParamName, pub.params.name
|
||||||
assertEquals alg.minKeyLength, pub.params.order.bitLength()
|
assertEquals alg.minKeyLength, pub.params.order.bitLength()
|
||||||
|
|
||||||
PrivateKey priv = pair.getPrivate()
|
PrivateKey priv = pair.getPrivate()
|
||||||
assert priv instanceof ECPrivateKey
|
assert priv instanceof ECPrivateKey
|
||||||
assertEquals "ECDSA", priv.algorithm
|
assertEquals "EC", priv.algorithm
|
||||||
assertEquals asn1oid, priv.params.name
|
assertEquals jdkParamName, priv.params.name
|
||||||
assertEquals alg.minKeyLength, priv.params.order.bitLength()
|
assertEquals alg.minKeyLength, priv.params.order.bitLength()
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
13
pom.xml
13
pom.xml
|
@ -25,7 +25,7 @@
|
||||||
|
|
||||||
<groupId>io.jsonwebtoken</groupId>
|
<groupId>io.jsonwebtoken</groupId>
|
||||||
<artifactId>jjwt-root</artifactId>
|
<artifactId>jjwt-root</artifactId>
|
||||||
<version>0.11.0-SNAPSHOT</version>
|
<version>0.10.1-SNAPSHOT</version>
|
||||||
<name>JJWT</name>
|
<name>JJWT</name>
|
||||||
<description>JSON Web Token support for the JVM and Android</description>
|
<description>JSON Web Token support for the JVM and Android</description>
|
||||||
<packaging>pom</packaging>
|
<packaging>pom</packaging>
|
||||||
|
@ -121,12 +121,6 @@
|
||||||
<artifactId>jjwt-api</artifactId>
|
<artifactId>jjwt-api</artifactId>
|
||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>io.jsonwebtoken</groupId>
|
|
||||||
<artifactId>jjwt-impl</artifactId>
|
|
||||||
<version>${project.version}</version>
|
|
||||||
<scope>runtime</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>io.jsonwebtoken</groupId>
|
<groupId>io.jsonwebtoken</groupId>
|
||||||
<artifactId>jjwt-jackson</artifactId>
|
<artifactId>jjwt-jackson</artifactId>
|
||||||
|
@ -147,12 +141,13 @@
|
||||||
<artifactId>json</artifactId>
|
<artifactId>json</artifactId>
|
||||||
<version>${orgjson.version}</version>
|
<version>${orgjson.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!-- Used only during testing for PS256, PS384 and PS512 since JDK <= 10 doesn't support them: -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.bouncycastle</groupId>
|
<groupId>org.bouncycastle</groupId>
|
||||||
<artifactId>bcprov-jdk15on</artifactId>
|
<artifactId>bcprov-jdk15on</artifactId>
|
||||||
<version>${bouncycastle.version}</version>
|
<version>${bouncycastle.version}</version>
|
||||||
<scope>compile</scope>
|
<scope>test</scope>
|
||||||
<optional>true</optional>
|
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</dependencyManagement>
|
</dependencyManagement>
|
||||||
|
|
Loading…
Reference in New Issue