Skip to content

Commit b4e84da

Browse files
committed
signature verification algorithm resolving moved to AlgorithmResolver
1 parent 5a46811 commit b4e84da

2 files changed

Lines changed: 58 additions & 86 deletions

File tree

src/main/java/org/oidc/msg/AbstractMessage.java

Lines changed: 10 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import com.auth0.jwt.exceptions.oicmsg_exceptions.JWKException;
2626
import com.auth0.jwt.exceptions.oicmsg_exceptions.SerializationNotPossible;
2727
import com.auth0.jwt.exceptions.oicmsg_exceptions.ValueError;
28+
import com.auth0.jwt.interfaces.DecodedJWT;
2829
import com.auth0.msg.Key;
2930
import com.auth0.msg.KeyJar;
3031
import com.auth0.msg.SYMKey;
@@ -294,11 +295,9 @@ public void fromJwt(String jwt, KeyJar keyJar, String keyOwner,
294295
throw new DeserializationException("Could not read the JWT contents", e);
295296
}
296297
verified = false;
297-
298298
if (keyJar == null) {
299299
return;
300300
}
301-
302301
if (header.get("alg") == null || !(header.get("alg") instanceof String)) {
303302
throw new JWTDecodeException("JWT does not have alg in header");
304303
}
@@ -313,6 +312,7 @@ public void fromJwt(String jwt, KeyJar keyJar, String keyOwner,
313312
verifier.verify(jwt);
314313
return;
315314
}
315+
//Now we expect to have keys
316316
List<Key> keys;
317317
try {
318318
keys = keyJar.getJWTVerifyKeys(jwt, keyOwner, noKidIssuers, allowMissingKid, trustJKU);
@@ -324,90 +324,15 @@ public void fromJwt(String jwt, KeyJar keyJar, String keyOwner,
324324
throw new JWTDecodeException("Not able to locate keys to verify JWT");
325325
}
326326
// We try each located key
327-
try {
328-
for (Key key : keys) {
329-
java.security.Key decKey = null;
330-
try {
331-
decKey = key.getKey(false);
332-
} catch (ValueError e) {
333-
throw new JWTDecodeException(String.format("Invalid key: '%s'", e.getMessage()));
334-
}
335-
switch (alg) {
336-
case "RS256":
337-
case "RS384":
338-
case "RS512":
339-
if (!(decKey instanceof RSAPublicKey)) {
340-
continue;
341-
}
342-
break;
343-
case "ES256":
344-
case "ES384":
345-
case "ES512":
346-
if (!(decKey instanceof ECPublicKey)) {
347-
continue;
348-
}
349-
break;
350-
case "HS256":
351-
case "HS384":
352-
case "HS512":
353-
if (!(decKey instanceof SYMKey)) {
354-
continue;
355-
}
356-
break;
357-
default:
358-
break;
359-
}
360-
if (decKey == null) {
361-
//key not suitable for the algorithm, move on
362-
continue;
363-
}
364-
Algorithm algorithm = null;
365-
switch (alg) {
366-
case "RS256":
367-
algorithm = Algorithm.RSA256((RSAPublicKey) decKey, null);
368-
break;
369-
case "RS384":
370-
algorithm = Algorithm.RSA384((RSAPublicKey) decKey, null);
371-
break;
372-
case "RS512":
373-
algorithm = Algorithm.RSA512((RSAPublicKey) decKey, null);
374-
break;
375-
case "ES256":
376-
algorithm = Algorithm.ECDSA256((ECPublicKey) decKey, null);
377-
break;
378-
case "ES384":
379-
algorithm = Algorithm.ECDSA384((ECPublicKey) decKey, null);
380-
break;
381-
case "ES512":
382-
algorithm = Algorithm.ECDSA512((ECPublicKey) decKey, null);
383-
break;
384-
case "HS256":
385-
algorithm = Algorithm.HMAC256((String) ((SYMKey) decKey).serialize(false).get("k"));
386-
break;
387-
case "HS384":
388-
algorithm = Algorithm.HMAC384((String) ((SYMKey) decKey).serialize(false).get("k"));
389-
break;
390-
case "HS512":
391-
algorithm = Algorithm.HMAC512((String) ((SYMKey) decKey).serialize(false).get("k"));
392-
break;
393-
default:
394-
break;
395-
}
396-
if (algorithm == null) {
397-
throw new JWTDecodeException("Not able to initialize algorithm to verify JWT");
398-
}
399-
JWTVerifier verifier = JWT.require(algorithm).build();
400-
try {
401-
verifier.verify(jwt);
402-
return;
403-
} catch (JWTVerificationException e) {
404-
// Move to next key
405-
continue;
406-
}
327+
for (Key key : keys) {
328+
try {
329+
JWT.require(AlgorithmResolver.resolveVerificationAlgorithm(key, alg)).build().verify(jwt);
330+
// Success
331+
return;
332+
} catch (JWTVerificationException | IllegalArgumentException | ValueError
333+
| UnsupportedEncodingException | SerializationNotPossible e) {
334+
// Move on to next key, this one is not suitable or just wrong
407335
}
408-
} catch (IllegalArgumentException | UnsupportedEncodingException | SerializationNotPossible e) {
409-
throw new JWTDecodeException(
410-
String.format("Key/Algorithmn handling exception '%s'", e.getMessage()));
411336
}
412337
throw new JWTDecodeException("Not able to verify JWT with any of the keys provided");
413338

src/main/java/org/oidc/msg/oidc/util/AlgorithmResolver.java

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,9 @@
2525
import com.auth0.msg.SYMKey;
2626
import java.io.UnsupportedEncodingException;
2727
import java.security.interfaces.ECPrivateKey;
28+
import java.security.interfaces.ECPublicKey;
2829
import java.security.interfaces.RSAPrivateKey;
30+
import java.security.interfaces.RSAPublicKey;
2931

3032
public class AlgorithmResolver {
3133

@@ -68,7 +70,7 @@ private static boolean verifyKeyType(Key key, String alg) {
6870
}
6971
return false;
7072
}
71-
73+
7274
/**
7375
* Resolves signing algorithm for key and algorithm identifier string.
7476
* @param key for signing.
@@ -113,4 +115,49 @@ public static Algorithm resolveSigningAlgorithm(Key key, String alg)
113115
}
114116
throw new ValueError(String.format("Algorithm '%s' not supported ", alg));
115117
}
118+
119+
/**
120+
* Resolves signature verification algorithm for key and algorithm identifier string.
121+
* @param key for signing.
122+
* @param alg algorithm name.
123+
* @return Algorithm instance
124+
* @throws ValueError if key or algorithm is of unexpected type
125+
* @throws UnsupportedEncodingException if symmetric key encoding fails
126+
* @throws SerializationNotPossible if symmetric key fails to serialize
127+
*/
128+
public static Algorithm resolveVerificationAlgorithm(Key key, String alg)
129+
throws ValueError, UnsupportedEncodingException, SerializationNotPossible {
130+
if (!verifyKeyType(key, alg)) {
131+
throw new ValueError(String.format("key does not match algorithm '%s' ", alg));
132+
}
133+
if (key != null && !key.isPublicKey()) {
134+
throw new ValueError(String.format("Verification key must be public"));
135+
}
136+
switch (alg) {
137+
case "none":
138+
return Algorithm.none();
139+
case "RS256":
140+
return Algorithm.RSA256((RSAPublicKey) key.getKey(false), null);
141+
case "RS384":
142+
return Algorithm.RSA384((RSAPublicKey) key.getKey(false), null);
143+
case "RS512":
144+
return Algorithm.RSA512((RSAPublicKey) key.getKey(false), null);
145+
case "ES256":
146+
return Algorithm.ECDSA256((ECPublicKey) key.getKey(false), null);
147+
case "ES384":
148+
return Algorithm.ECDSA384((ECPublicKey) key.getKey(false), null);
149+
case "ES512":
150+
return Algorithm.ECDSA512((ECPublicKey) key.getKey(false), null);
151+
case "HS256":
152+
return Algorithm.HMAC256((String) ((SYMKey) key).serialize(false).get("k"));
153+
case "HS384":
154+
return Algorithm.HMAC384((String) ((SYMKey) key).serialize(false).get("k"));
155+
case "HS512":
156+
return Algorithm.HMAC512((String) ((SYMKey) key).serialize(false).get("k"));
157+
default:
158+
break;
159+
}
160+
throw new ValueError(String.format("Algorithm '%s' not supported ", alg));
161+
}
162+
116163
}

0 commit comments

Comments
 (0)