Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support pkcs11 #704

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions api/src/main/java/io/jsonwebtoken/Jwts.java
Original file line number Diff line number Diff line change
Expand Up @@ -122,9 +122,9 @@ public static JwtParser parser() {
}

/**
* Returns a new {@link JwtParserBuilder} instance that can be configured to create an immutable/thread-safe {@link JwtParser).
* Returns a new {@link JwtParserBuilder} instance that can be configured to create an immutable/thread-safe {@link JwtParser}.
*
* @return a new {@link JwtParser} instance that can be configured create an immutable/thread-safe {@link JwtParser).
* @return a new {@link JwtParser} instance that can be configured create an immutable/thread-safe {@link JwtParser}.
*/
public static JwtParserBuilder parserBuilder() {
return Classes.newInstance("io.jsonwebtoken.impl.DefaultJwtParserBuilder");
Expand Down
99 changes: 56 additions & 43 deletions api/src/main/java/io/jsonwebtoken/SignatureAlgorithm.java
Original file line number Diff line number Diff line change
Expand Up @@ -394,50 +394,63 @@ private void assertValid(Key key, boolean signing) throws InvalidKeyException {
String msg = familyName + " signing keys must be PrivateKey instances.";
throw new InvalidKeyException(msg);
}
}

if (isEllipticCurve()) {

if (!(key instanceof ECKey)) {
String msg = familyName + " " + keyType(signing) + " keys must be ECKey instances.";
throw new InvalidKeyException(msg);
if (isEllipticCurve()) {
if (!(key instanceof ECKey || "EC".equals(key.getAlgorithm()) || "ECDSA".equals(key.getAlgorithm()))) {
String msg = "Elliptic Curve signatures must be computed using an EC PrivateKey. The specified key of " +
"type " + key.getClass().getName() + " is not an EC PrivateKey.";
throw new InvalidKeyException(msg);
}
} else { //RSA
if (!(key instanceof RSAKey || "RSA".equals(key.getAlgorithm()))) {
String msg = "RSA signatures must be computed using an RSA PrivateKey. The specified key of type " +
key.getClass().getName() + " is not an RSA PrivateKey.";
throw new InvalidKeyException(msg);
}
}

ECKey ecKey = (ECKey) key;
int size = ecKey.getParams().getOrder().bitLength();
if (size < this.minKeyLength) {
String msg = "The " + keyType(signing) + " key's size (ECParameterSpec order) is " + size +
" bits which is not secure enough for the " + name() + " algorithm. The JWT " +
"JWA Specification (RFC 7518, Section 3.4) states that keys used with " +
name() + " MUST have a size >= " + this.minKeyLength +
" bits. Consider using the " + Keys.class.getName() + " class's " +
"'keyPairFor(SignatureAlgorithm." + name() + ")' method to create a key pair guaranteed " +
"to be secure enough for " + name() + ". See " +
"https://tools.ietf.org/html/rfc7518#section-3.4 for more information.";
throw new WeakKeyException(msg);
}

} else { //RSA

if (!(key instanceof RSAKey)) {
String msg = familyName + " " + keyType(signing) + " keys must be RSAKey instances.";
throw new InvalidKeyException(msg);
}

RSAKey rsaKey = (RSAKey) key;
int size = rsaKey.getModulus().bitLength();
if (size < this.minKeyLength) {

String section = name().startsWith("P") ? "3.5" : "3.3";

String msg = "The " + keyType(signing) + " key's size is " + size + " bits which is not secure " +
"enough for the " + name() + " algorithm. The JWT JWA Specification (RFC 7518, Section " +
section + ") states that keys used with " + name() + " MUST have a size >= " +
this.minKeyLength + " bits. Consider using the " + Keys.class.getName() + " class's " +
"'keyPairFor(SignatureAlgorithm." + name() + ")' method to create a key pair guaranteed " +
"to be secure enough for " + name() + ". See " +
"https://tools.ietf.org/html/rfc7518#section-" + section + " for more information.";
throw new WeakKeyException(msg);
} else {
if (isEllipticCurve()) {

if (!(key instanceof ECKey)) {
String msg = familyName + " " + keyType(false) + " keys must be ECKey instances.";
throw new InvalidKeyException(msg);
}

ECKey ecKey = (ECKey) key;
int size = ecKey.getParams().getOrder().bitLength();
if (size < this.minKeyLength) {
String msg = "The " + keyType(false) + " key's size (ECParameterSpec order) is " + size +
" bits which is not secure enough for the " + name() + " algorithm. The JWT " +
"JWA Specification (RFC 7518, Section 3.4) states that keys used with " +
name() + " MUST have a size >= " + this.minKeyLength +
" bits. Consider using the " + Keys.class.getName() + " class's " +
"'keyPairFor(SignatureAlgorithm." + name() + ")' method to create a key pair guaranteed " +
"to be secure enough for " + name() + ". See " +
"https://tools.ietf.org/html/rfc7518#section-3.4 for more information.";
throw new WeakKeyException(msg);
}

} else { //RSA

if (!(key instanceof RSAKey)) {
String msg = familyName + " " + keyType(false) + " keys must be RSAKey instances.";
throw new InvalidKeyException(msg);
}

RSAKey rsaKey = (RSAKey) key;
int size = rsaKey.getModulus().bitLength();
if (size < this.minKeyLength) {

String section = name().startsWith("P") ? "3.5" : "3.3";

String msg = "The " + keyType(false) + " key's size is " + size + " bits which is not secure " +
"enough for the " + name() + " algorithm. The JWT JWA Specification (RFC 7518, Section " +
section + ") states that keys used with " + name() + " MUST have a size >= " +
this.minKeyLength + " bits. Consider using the " + Keys.class.getName() + " class's " +
"'keyPairFor(SignatureAlgorithm." + name() + ")' method to create a key pair guaranteed " +
"to be secure enough for " + name() + ". See " +
"https://tools.ietf.org/html/rfc7518#section-" + section + " for more information.";
throw new WeakKeyException(msg);
}
}
}
}
Expand Down
68 changes: 6 additions & 62 deletions api/src/test/groovy/io/jsonwebtoken/SignatureAlgorithmTest.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -514,43 +514,16 @@ class SignatureAlgorithmTest {
for (SignatureAlgorithm alg : SignatureAlgorithm.values().findAll { it.isEllipticCurve() }) {

PrivateKey key = createMock(PrivateKey)
expect(key.getAlgorithm()).andStubReturn("unknown")
replay key

try {
alg.assertValidSigningKey(key)
fail()
} catch (InvalidKeyException expected) {
assertEquals 'ECDSA signing keys must be ECKey instances.', expected.message
}
}
}

@Test
void testAssertValidECSigningKeyInsufficientKeyLength() {

for (SignatureAlgorithm alg : SignatureAlgorithm.values().findAll { it.isEllipticCurve() }) {

ECPrivateKey key = createMock(ECPrivateKey)
ECParameterSpec spec = createMock(ECParameterSpec)
BigInteger order = bigInteger(alg.minKeyLength - 8) //one less byte
expect(key.getParams()).andStubReturn(spec)
expect(spec.getOrder()).andStubReturn(order)

replay key, spec

try {
alg.assertValidSigningKey(key)
fail()
} catch (InvalidKeyException expected) {
assertEquals "The signing key's size (ECParameterSpec order) is ${order.bitLength()} bits " +
"which is not secure enough for the ${alg.name()} algorithm. The JWT JWA Specification " +
"(RFC 7518, Section 3.4) states that keys used with ${alg.name()} MUST have a size >= " +
"${alg.minKeyLength} bits. Consider using the ${Keys.class.getName()} class's " +
"'keyPairFor(SignatureAlgorithm.${alg.name()})' method to create a key pair guaranteed " +
"to be secure enough for ${alg.name()}. See " +
"https://tools.ietf.org/html/rfc7518#section-3.4 for more information." as String, expected.message
assertEquals "Elliptic Curve signatures must be computed using an EC PrivateKey. " +
"The specified key of type ${key.getClass().getName()} is not an EC PrivateKey." as String, expected.message
}

verify key, spec
}
}

Expand Down Expand Up @@ -602,41 +575,12 @@ class SignatureAlgorithmTest {
alg.assertValidSigningKey(key)
fail()
} catch (InvalidKeyException expected) {
assertEquals 'RSA signing keys must be RSAKey instances.', expected.message
assertEquals "RSA signatures must be computed using an RSA PrivateKey. " +
"The specified key of type ${key.getClass().getName()} is not an RSA PrivateKey." as String, expected.message
}
}
}

@Test
void testAssertValidRSASigningKeyInsufficientKeyLength() {

for (SignatureAlgorithm alg : SignatureAlgorithm.values().findAll { it.isRsa() }) {

String section = alg.name().startsWith("P") ? "3.5" : "3.3"

RSAPrivateKey key = createMock(RSAPrivateKey)
BigInteger modulus = bigInteger(alg.minKeyLength - 8) // 1 less byte
expect(key.getModulus()).andStubReturn(modulus)

replay key

try {
alg.assertValidSigningKey(key)
fail()
} catch (InvalidKeyException expected) {
assertEquals "The signing key's size is ${modulus.bitLength()} bits which is not secure " +
"enough for the ${alg.name()} algorithm. The JWT JWA Specification " +
"(RFC 7518, Section ${section}) states that keys used with ${alg.name()} MUST have a size >= " +
"${alg.minKeyLength} bits. Consider using the ${Keys.class.getName()} class's " +
"'keyPairFor(SignatureAlgorithm.${alg.name()})' method to create a key pair guaranteed " +
"to be secure enough for ${alg.name()}. See " +
"https://tools.ietf.org/html/rfc7518#section-${section} for more information." as String, expected.message
}

verify key
}
}

@Test
void testAssertValidVerificationKeyWithNoneAlgorithm() {
Key key = createMock(Key)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public class EllipticCurveSigner extends EllipticCurveProvider implements Signer

public EllipticCurveSigner(SignatureAlgorithm alg, Key key) {
super(alg, key);
if (!(key instanceof PrivateKey && key instanceof ECKey)) {
if (!(key instanceof PrivateKey && (key instanceof ECKey || "EC".equals(key.getAlgorithm()) || "ECDSA".equals(key.getAlgorithm())))) {
String msg = "Elliptic Curve signatures must be computed using an EC PrivateKey. The specified key of " +
"type " + key.getClass().getName() + " is not an EC PrivateKey.";
throw new IllegalArgumentException(msg);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public RsaSigner(SignatureAlgorithm alg, Key key) {
super(alg, key);
// https://github.com/jwtk/jjwt/issues/68
// Instead of checking for an instance of RSAPrivateKey, check for PrivateKey and RSAKey:
if (!(key instanceof PrivateKey && key instanceof RSAKey)) {
if (!(key instanceof PrivateKey && (key instanceof RSAKey || "RSA".equals(key.getAlgorithm())))) {
String msg = "RSA signatures must be computed using an RSA PrivateKey. The specified key of type " +
key.getClass().getName() + " is not an RSA PrivateKey.";
throw new IllegalArgumentException(msg);
Expand Down