diff --git a/.travis.yml b/.travis.yml index 6bf18e26..0ffe5742 100644 --- a/.travis.yml +++ b/.travis.yml @@ -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 diff --git a/CHANGELOG.md b/CHANGELOG.md index ac1867d3..57561b43 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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: diff --git a/README.md b/README.md index d2857a44..383674c1 100644 --- a/README.md +++ b/README.md @@ -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-2561 * PS384: RSASSA-PSS using SHA-384 and MGF1 with SHA-3841 * PS512: RSASSA-PSS using SHA-512 and MGF1 with SHA-5121 - * ES256: ECDSA using P-256 and SHA-2561 - * ES384: ECDSA using P-384 and SHA-3841 - * ES512: ECDSA using P-521 and SHA-5121 - 1. Requires a compatible JCA Provider (like BouncyCastle) in the runtime classpath. + 1. Requires JDK 11 or a compatible JCA Provider (like BouncyCastle) in the runtime classpath. * Convenience enhancements beyond the specification such as * Body compression for any large JWT, not just JWEs * 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 io.jsonwebtoken jjwt-api - 0.10.0 + 0.10.1 io.jsonwebtoken jjwt-impl - 0.10.0 + 0.10.1 runtime io.jsonwebtoken jjwt-jackson - 0.10.0 + 0.10.1 runtime - ``` @@ -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' } ``` diff --git a/api/pom.xml b/api/pom.xml index 00007e65..5cd0a7ad 100644 --- a/api/pom.xml +++ b/api/pom.xml @@ -21,7 +21,7 @@ io.jsonwebtoken jjwt-root - 0.11.0-SNAPSHOT + 0.10.1-SNAPSHOT ../pom.xml diff --git a/api/src/main/java/io/jsonwebtoken/SignatureAlgorithm.java b/api/src/main/java/io/jsonwebtoken/SignatureAlgorithm.java index 1d198e85..3789020a 100644 --- a/api/src/main/java/io/jsonwebtoken/SignatureAlgorithm.java +++ b/api/src/main/java/io/jsonwebtoken/SignatureAlgorithm.java @@ -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; @@ -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}. This is not a JDK standard algorithm and - * requires that a JCA provider like BouncyCastle be in the runtime classpath. 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}. This is not a JDK standard algorithm and - * requires that a JCA provider like BouncyCastle be in the runtime classpath. 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}. This is not a JDK standard algorithm and - * requires that a JCA provider like BouncyCastle be in the runtime classpath. 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}. 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); - static { - RuntimeEnvironment.enableBouncyCastleIfPossible(); - } - //purposefully ordered higher to lower: private static final List PREFERRED_HMAC_ALGS = Collections.unmodifiableList(Arrays.asList( SignatureAlgorithm.HS512, SignatureAlgorithm.HS384, SignatureAlgorithm.HS256)); diff --git a/api/src/test/groovy/io/jsonwebtoken/JwtsTest.groovy b/api/src/test/groovy/io/jsonwebtoken/JwtsTest.groovy index 9b901622..3c540db5 100644 --- a/api/src/test/groovy/io/jsonwebtoken/JwtsTest.groovy +++ b/api/src/test/groovy/io/jsonwebtoken/JwtsTest.groovy @@ -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 diff --git a/api/src/test/groovy/io/jsonwebtoken/SignatureAlgorithmTest.groovy b/api/src/test/groovy/io/jsonwebtoken/SignatureAlgorithmTest.groovy index 1c9d1c82..159c646d 100644 --- a/api/src/test/groovy/io/jsonwebtoken/SignatureAlgorithmTest.groovy +++ b/api/src/test/groovy/io/jsonwebtoken/SignatureAlgorithmTest.groovy @@ -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() diff --git a/extensions/jackson/pom.xml b/extensions/jackson/pom.xml index 6757654d..928bb4a5 100644 --- a/extensions/jackson/pom.xml +++ b/extensions/jackson/pom.xml @@ -21,7 +21,7 @@ io.jsonwebtoken jjwt-root - 0.11.0-SNAPSHOT + 0.10.1-SNAPSHOT ../../pom.xml diff --git a/extensions/orgjson/pom.xml b/extensions/orgjson/pom.xml index 72a20c14..f8f7e968 100644 --- a/extensions/orgjson/pom.xml +++ b/extensions/orgjson/pom.xml @@ -21,7 +21,7 @@ io.jsonwebtoken jjwt-root - 0.11.0-SNAPSHOT + 0.10.1-SNAPSHOT ../../pom.xml diff --git a/extensions/pom.xml b/extensions/pom.xml index e96f58f8..7aeb2586 100644 --- a/extensions/pom.xml +++ b/extensions/pom.xml @@ -21,7 +21,7 @@ io.jsonwebtoken jjwt-root - 0.11.0-SNAPSHOT + 0.10.1-SNAPSHOT ../pom.xml diff --git a/impl/pom.xml b/impl/pom.xml index ddf35aa8..71f798f8 100644 --- a/impl/pom.xml +++ b/impl/pom.xml @@ -21,7 +21,7 @@ io.jsonwebtoken jjwt-root - 0.11.0-SNAPSHOT + 0.10.1-SNAPSHOT ../pom.xml @@ -38,11 +38,12 @@ io.jsonwebtoken jjwt-api + org.bouncycastle bcprov-jdk15on + test - io.jsonwebtoken jjwt-jackson diff --git a/impl/src/main/java/io/jsonwebtoken/impl/crypto/EllipticCurveProvider.java b/impl/src/main/java/io/jsonwebtoken/impl/crypto/EllipticCurveProvider.java index 2c7b01cd..6296289f 100644 --- a/impl/src/main/java/io/jsonwebtoken/impl/crypto/EllipticCurveProvider.java +++ b/impl/src/main/java/io/jsonwebtoken/impl/crypto/EllipticCurveProvider.java @@ -18,11 +18,13 @@ package io.jsonwebtoken.impl.crypto; import io.jsonwebtoken.JwtException; import io.jsonwebtoken.SignatureAlgorithm; import io.jsonwebtoken.lang.Assert; +import io.jsonwebtoken.lang.Strings; import java.security.Key; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.SecureRandom; +import java.security.spec.ECGenParameterSpec; import java.util.HashMap; 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 * 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 - * #generateKeyPair(String, String, SignatureAlgorithm, SecureRandom)} using {@code "ECDSA"} as the {@code - * jcaAlgorithmName} and {@code "BC"} as the {@code jcaProviderName} since EllipticCurve requires the use of an - * external JCA provider ({@code BC stands for BouncyCastle}. This will work as expected as long as the - * BouncyCastle dependency is in the runtime classpath. + * #generateKeyPair(String, String, SignatureAlgorithm, SecureRandom)} using {@code "EC"} as the {@code + * jcaAlgorithmName}. * * @param alg alg the algorithm indicating strength, must be one of {@code ES256}, {@code ES384} or {@code * ES512} @@ -101,7 +101,7 @@ public abstract class EllipticCurveProvider extends SignatureProvider { * @see #generateKeyPair(String, String, SignatureAlgorithm, SecureRandom) */ 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 * ECDSA}. - * @param jcaProviderName the JCA provider name of the algorithm implementation, for example {@code BC} for - * BouncyCastle. + * @param jcaProviderName the JCA provider name of the algorithm implementation (for example {@code "BC"} for + * 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 * {@code ES512} * @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.isTrue(alg.isEllipticCurve(), "SignatureAlgorithm argument must represent an Elliptic Curve algorithm."); 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); - g.initialize(org.bouncycastle.jce.ECNamedCurveTable.getParameterSpec(paramSpecCurveName), random); + ECGenParameterSpec spec = new ECGenParameterSpec(paramSpecCurveName); + g.initialize(spec, random); return g.generateKeyPair(); } catch (Exception 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 * {@code null}. - * * @return The expected byte array length for the signature. - * * @throws JwtException If the algorithm is not supported. */ public static int getSignatureByteArrayLength(final SignatureAlgorithm alg) - throws JwtException { + throws JwtException { switch (alg) { - case ES256: return 64; - case ES384: return 96; - case ES512: return 132; + case ES256: + return 64; + case ES384: + return 96; + case ES512: + return 132; default: 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 outputLength The expected length of the ECDSA JWS signature. - * * @return The ECDSA JWS encoded signature. - * * @throws JwtException If the ASN.1/DER signature format is invalid. */ 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); if ((derSignature[offset - 1] & 0xff) != derSignature.length - offset - || (derSignature[offset - 1] & 0xff) != 2 + rLength + 2 + sLength - || derSignature[offset] != 2 - || derSignature[offset + 2 + rLength] != 2) { + || (derSignature[offset - 1] & 0xff) != 2 + rLength + 2 + sLength + || derSignature[offset] != 2 + || derSignature[offset + 2 + rLength] != 2) { 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 * the JCA verifier. @@ -228,9 +234,7 @@ public abstract class EllipticCurveProvider extends SignatureProvider { * @param jwsSignature The JWS signature, consisting of the * concatenated R and S values. Must not be * {@code null}. - * * @return The ASN.1/DER encoded signature. - * * @throws JwtException If the ECDSA JWS signature format is invalid. */ public static byte[] transcodeSignatureToDER(byte[] jwsSignature) throws JwtException { @@ -239,7 +243,7 @@ public abstract class EllipticCurveProvider extends SignatureProvider { int i = rawLen; - while((i > 0) && (jwsSignature[rawLen - i] == 0)) { + while ((i > 0) && (jwsSignature[rawLen - i] == 0)) { i--; } diff --git a/impl/src/main/java/io/jsonwebtoken/impl/crypto/RsaProvider.java b/impl/src/main/java/io/jsonwebtoken/impl/crypto/RsaProvider.java index 2d6991f4..bce2b1c7 100644 --- a/impl/src/main/java/io/jsonwebtoken/impl/crypto/RsaProvider.java +++ b/impl/src/main/java/io/jsonwebtoken/impl/crypto/RsaProvider.java @@ -17,6 +17,7 @@ package io.jsonwebtoken.impl.crypto; import io.jsonwebtoken.SignatureAlgorithm; import io.jsonwebtoken.lang.Assert; +import io.jsonwebtoken.lang.RuntimeEnvironment; import io.jsonwebtoken.security.SignatureException; import java.security.InvalidAlgorithmParameterException; @@ -54,6 +55,10 @@ public abstract class RsaProvider extends SignatureProvider { return m; } + static { + RuntimeEnvironment.enableBouncyCastleIfPossible(); //PS256, PS384, PS512 on <= JDK 10 require BC + } + protected RsaProvider(SignatureAlgorithm alg, Key key) { super(alg, key); Assert.isTrue(alg.isRsa(), "SignatureAlgorithm must be an RSASSA or RSASSA-PSS algorithm."); diff --git a/impl/src/test/groovy/io/jsonwebtoken/impl/crypto/EllipticCurveProviderTest.groovy b/impl/src/test/groovy/io/jsonwebtoken/impl/crypto/EllipticCurveProviderTest.groovy index a92003d4..7e61b8f9 100644 --- a/impl/src/test/groovy/io/jsonwebtoken/impl/crypto/EllipticCurveProviderTest.groovy +++ b/impl/src/test/groovy/io/jsonwebtoken/impl/crypto/EllipticCurveProviderTest.groovy @@ -38,7 +38,7 @@ class EllipticCurveProviderTest { @Test void testGenerateKeyPairWithInvalidProviderName() { try { - EllipticCurveProvider.generateKeyPair("ECDSA", "Foo", SignatureAlgorithm.ES256, null) + EllipticCurveProvider.generateKeyPair("EC", "Foo", SignatureAlgorithm.ES256, null) fail() } catch (IllegalStateException ise) { assertEquals ise.message, "Unable to generate Elliptic Curve KeyPair: no such provider: Foo" @@ -49,7 +49,7 @@ class EllipticCurveProviderTest { @Test void testGenerateKeyPairWithNullAlgorithm() { try { - EllipticCurveProvider.generateKeyPair("ECDSA", "Foo", null, null) + EllipticCurveProvider.generateKeyPair("EC", "Foo", null, null) fail() } catch (IllegalArgumentException ise) { assertEquals ise.message, "SignatureAlgorithm argument cannot be null." @@ -59,7 +59,7 @@ class EllipticCurveProviderTest { @Test void testGenerateKeyPairWithNonEllipticCurveAlgorithm() { try { - EllipticCurveProvider.generateKeyPair("ECDSA", "Foo", SignatureAlgorithm.HS256, null) + EllipticCurveProvider.generateKeyPair("EC", "Foo", SignatureAlgorithm.HS256, null) fail() } catch (IllegalArgumentException ise) { assertEquals ise.message, "SignatureAlgorithm argument must represent an Elliptic Curve algorithm." diff --git a/impl/src/test/groovy/io/jsonwebtoken/impl/crypto/EllipticCurveSignatureValidatorTest.groovy b/impl/src/test/groovy/io/jsonwebtoken/impl/crypto/EllipticCurveSignatureValidatorTest.groovy index cdb37951..a0acb029 100644 --- a/impl/src/test/groovy/io/jsonwebtoken/impl/crypto/EllipticCurveSignatureValidatorTest.groovy +++ b/impl/src/test/groovy/io/jsonwebtoken/impl/crypto/EllipticCurveSignatureValidatorTest.groovy @@ -19,7 +19,6 @@ import io.jsonwebtoken.JwtException import io.jsonwebtoken.SignatureAlgorithm import io.jsonwebtoken.io.Decoders import io.jsonwebtoken.security.SignatureException -import org.bouncycastle.jce.provider.BouncyCastleProvider import org.junit.Test import java.security.* @@ -29,10 +28,6 @@ import static org.junit.Assert.* class EllipticCurveSignatureValidatorTest { - static { - Security.addProvider(new BouncyCastleProvider()) - } - @Test void testDoVerifyWithInvalidKeyException() { @@ -62,7 +57,7 @@ class EllipticCurveSignatureValidatorTest { @Test void ecdsaSignatureComplianceTest() { - def fact = KeyFactory.getInstance("ECDSA", "BC"); + def fact = KeyFactory.getInstance("EC"); def publicKey = "MIGbMBAGByqGSM49AgEGBSuBBAAjA4GGAAQASisgweVL1tAtIvfmpoqvdXF8sPKTV9YTKNxBwkdkm+/auh4pR8TbaIfsEzcsGUVv61DFNFXb0ozJfurQ59G2XcgAn3vROlSSnpbIvuhKrzL5jwWDTaYa5tVF1Zjwia/5HUhKBkcPuWGXg05nMjWhZfCuEetzMLoGcHmtvabugFrqsAg=" def pub = fact.generatePublic(new X509EncodedKeySpec(Decoders.BASE64.decode(publicKey))) def v = new EllipticCurveSignatureValidator(SignatureAlgorithm.ES512, pub) @@ -82,7 +77,7 @@ class EllipticCurveSignatureValidatorTest { void legacySignatureCompatTest() { def withoutSignature = "eyJhbGciOiJFUzUxMiIsInR5cCI6IkpXVCJ9.eyJ0ZXN0IjoidGVzdCIsImlhdCI6MTQ2NzA2NTgyN30" 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") signature.initSign(keypair.private) signature.update(data) diff --git a/impl/src/test/groovy/io/jsonwebtoken/impl/crypto/SignatureProviderTest.groovy b/impl/src/test/groovy/io/jsonwebtoken/impl/crypto/SignatureProviderTest.groovy index 91158c0d..55fa2e9e 100644 --- a/impl/src/test/groovy/io/jsonwebtoken/impl/crypto/SignatureProviderTest.groovy +++ b/impl/src/test/groovy/io/jsonwebtoken/impl/crypto/SignatureProviderTest.groovy @@ -47,7 +47,7 @@ class SignatureProviderTest { @Test void testCreateSignatureInstanceNoSuchAlgorithmNonStandardAlgorithm() { - def p = new SignatureProvider(SignatureAlgorithm.ES512, EllipticCurveProvider.generateKeyPair().getPublic()) { + def p = new SignatureProvider(SignatureAlgorithm.PS256, RsaProvider.generateKeyPair().getPrivate()) { @Override protected Signature getSignatureInstance() throws NoSuchAlgorithmException { throw new NoSuchAlgorithmException('foo') @@ -65,7 +65,7 @@ class SignatureProviderTest { @Test void testCreateSignatureInstanceNoSuchAlgorithmNonStandardAlgorithmWithoutBouncyCastle() { - def p = new SignatureProvider(SignatureAlgorithm.ES512, EllipticCurveProvider.generateKeyPair().getPublic()) { + def p = new SignatureProvider(SignatureAlgorithm.PS256, RsaProvider.generateKeyPair().getPrivate()) { @Override protected Signature getSignatureInstance() throws NoSuchAlgorithmException { throw new NoSuchAlgorithmException('foo') @@ -81,7 +81,7 @@ class SignatureProviderTest { p.createSignatureInstance() fail() } 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.') } } } diff --git a/impl/src/test/groovy/io/jsonwebtoken/security/KeysImplTest.groovy b/impl/src/test/groovy/io/jsonwebtoken/security/KeysImplTest.groovy index 1ff2420c..3dfacbd8 100644 --- a/impl/src/test/groovy/io/jsonwebtoken/security/KeysImplTest.groovy +++ b/impl/src/test/groovy/io/jsonwebtoken/security/KeysImplTest.groovy @@ -71,18 +71,21 @@ class KeysImplTest { KeyPair pair = Keys.keyPairFor(alg); 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() assert pub instanceof ECPublicKey - assertEquals "ECDSA", pub.algorithm - assertEquals asn1oid, pub.params.name + assertEquals "EC", pub.algorithm + assertEquals jdkParamName, pub.params.name assertEquals alg.minKeyLength, pub.params.order.bitLength() PrivateKey priv = pair.getPrivate() assert priv instanceof ECPrivateKey - assertEquals "ECDSA", priv.algorithm - assertEquals asn1oid, priv.params.name + assertEquals "EC", priv.algorithm + assertEquals jdkParamName, priv.params.name assertEquals alg.minKeyLength, priv.params.order.bitLength() } else { diff --git a/pom.xml b/pom.xml index 9f2836ab..f60d7256 100644 --- a/pom.xml +++ b/pom.xml @@ -25,7 +25,7 @@ io.jsonwebtoken jjwt-root - 0.11.0-SNAPSHOT + 0.10.1-SNAPSHOT JJWT JSON Web Token support for the JVM and Android pom @@ -121,12 +121,6 @@ jjwt-api ${project.version} - - io.jsonwebtoken - jjwt-impl - ${project.version} - runtime - io.jsonwebtoken jjwt-jackson @@ -147,12 +141,13 @@ json ${orgjson.version} + + org.bouncycastle bcprov-jdk15on ${bouncycastle.version} - compile - true + test