Closed gauravk48 closed 1 year ago
Without seeing more, it looks like perhaps you might be hitting key length assertions introduced in 0.10.0?
If you you run just the following:
Keys.hmacShaKeyFor(Decoders.BASE64.decode(SECRET))
do you get a WeakKeyException
?
If you do, you should use a stronger key on the server since the one currently being used isn't strong enough for the desired algorithm. If you cannot change that key on the server, you cannot upgrade to JJWT 0.10.0 or later on the client because of the security assertions - at least until you upgrade the server key.
If you are not seeing a WeakKeyException
, please do this:
SECRET
currently) that is the exact same length (number of bytes) as your current SECRET value.Once we have both of those, we can try to recreate and diagnose the problem on 0.11.x. I'm suspecting it's a key length issue though. Let us know!
(Also, for future questions, please kindly do not use GitHub Issues to ask usage questions. Please read https://github.com/jwtk/jjwt#questions Thanks 😃 )
Any update on this?
I will check in some code to reproduce the issue.
Thanks
On Wed, Aug 5, 2020 at 9:44 AM Les Hazlewood notifications@github.com wrote:
Any update on this?
— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/jwtk/jjwt/issues/613#issuecomment-669303915, or unsubscribe https://github.com/notifications/unsubscribe-auth/AGXKZOXO5L3SQFGUFT2UIRTR7GD7HANCNFSM4PMMDJNA .
I have created two repositories with code to show that the token generated by one version is not compatible with the other.
Here is the jwt 0.9 repo: https://github.com/gauravk48/jwttest9 Here is the jwt 0.11 repo: https://github.com/gauravk48/jwttest11
You can compile using maven, and then generate the token from one version and try using it on the later version. It shows the following error:
Test jwt token, current time: Tue Aug 18 11:17:11 PDT 2020 Exception in thread "main" java.lang.reflect.InvocationTargetException at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at com.simontuffs.onejar.Boot.run(Boot.java:340) at com.simontuffs.onejar.Boot.main(Boot.java:166) Caused by: io.jsonwebtoken.SignatureException: JWT signature does not match locally computed signature. JWT validity cannot be asserted and should not be trusted. at io.jsonwebtoken.impl.DefaultJwtParser.parse(DefaultJwtParser.java:354) at io.jsonwebtoken.impl.DefaultJwtParser.parse(DefaultJwtParser.java:481) at io.jsonwebtoken.impl.DefaultJwtParser.parseClaimsJws(DefaultJwtParser.java:541) at gauravk48.JwtTest.validateTokenAndGetSubj(JwtTest.java:51) at gauravk48.JwtTest.main(JwtTest.java:24) ... 6 more
@lhazlewood Please take a look and suggest how to resolve this. The token is generated on one host but should be able to validate on any different host as long as the secret is shared between them.
@gauravk48 thanks so much for putting this together! I'll take a look as soon as I can - probably later today or tomorrow.
Any updates on this @lhazlewood Thanks for looking.
@gauravk48 sorry for the delay - I was deep in JWE code all week! I hope I can get to this soon.
Just checking if you got time to look into the issue> @lhazlewood
@gauravk48 not yet - I had other responsibilities that prevented me from digging in further. I should be able to get back to this soon - probably this or next week. Thanks for the reminder!
This issue has been automatically marked as stale due to inactivity for 60 or more days. It will be closed in 7 days if no further activity occurs.
@lhazlewood Any update on this?
We kinda had a similar issue.
It was between the server on 0.9, and the client with a different jwt library (njwt latest). To fix it we had to increase the secret above 265 bytes and base64 encode the secret on the client side.
@bdemers if you get a sec would you mind taking a look at this when you get a sec? I'm unable to pick up new work until the JWE stuff is done (I'm in the thick of it).
This issue has been automatically marked as stale due to inactivity for 60 or more days. It will be closed in 7 days if no further activity occurs.
Ping. I'd like to help out.
I encountered a WeakKeyException. I wanted to share how we are temporarily solving this. We are trying to figure out how to role this change out across many microservices. We may have microservices using JJWT 0.11, but our security microservice generating JWTs using 0.9.
Our secret was only 384 bits, leading to a WeakKeyException. So we are padding the existing secret to meet the 512 bit requirement.
byte[] paddedKey = shortKey.length() < 64 ? Arrays.copy(shortKey, 64); : shortKey;
This will allow a JWT generated using the shortKey
to be parsed by microservices using 0.11 by padding the shortKey
.
Closing this as represented by @sruffatti 's workaround, as well as a potential solution in the upcoming 0.12.0
: custom SignatureAlgorithm
implementations are now supported, and if you need validation that is different than the RFC requirements, you can implement your own SignatureAlgorithm
and plug that in via JwtParserBuilder.addSignatureAlgorithms
I have a Spring Boot 2.2 with JJWT 0.9.1 project that generates the JWT tokens of length 32 bits and this token is being used in another Spring Boot project in which I'm trying to upgrade to Spring Boot 3 and JJWT 0.12.6. I'm trying to follow @sruffatti's approach of padding the secret key but it is throwing this exception:
Request to parse JWT with invalid signature : failed : {}
io.jsonwebtoken.security.SignatureException: JWT signature does not match locally computed signature. JWT validity cannot be asserted and should not be trusted.
This is my Java code:
private final String SECRET_KEY = "MY_SECRET_KEY"; // 32 bits
private final byte[] paddedSecretKey = Arrays.copyOf(MY_SECRET_KEY.getBytes(StandardCharsets.UTF_8), 32); // 256 bits
private Claims extractAllClaims(String token) {
return Jwts.parser().setSigningKey(paddedSecretKey).build().parseClaimsJws(token).getBody();
}
Any help would be appreciated
@SushSpaceBasic .setSigningKey
has been deprecated as of 0.12.0
, use verifyWith
using a key object directly. You could obtain one using:
byte[] paddedSecretKeyBytes = shortKey.length() < 64 ? Arrays.copy(shortKey, 64); : shortKey;
SecretKey secretKey = new SecretKeySpec(paddedSecretKeyBytes);
Jwts.parser().verifyWith(secretKey)// ... etc ...
BUT NOTE:
@sruffatti's fix (using padding as shown above) only works if both signature creation and signature verification uses the same exact padding and resulting key bytes - you can't just add padding to the key byte array for verification only. The issuer (the entity that creates the JWT and its signature) must also pad the key byte array in the exact same way. Otherwise they would technically be separate cryptographic keys (not symmetric) and thus incompatible.
Finally, note that padding should only ever be thought of as a 'quick fix', and ideally, not even used. A safe uniformly-distributed (i.e. indistinguishably random) cryptographic key is the only safe way. Padding with zeros ensures that the padded part is distinctly non-random, which breaks the keys strength.
Thanks for the quick clarification @lhazlewood. Really appreciate it
We have a server which issues JWT token using HS256 algorithm and some secret using Jwtt version 0.9. The client has upgraded to version 0.11 and now even while using the same secret to validate, its not working. When we just change the version to 0.9, the code works.
Here is the 0.9 code:
Jws claims = Jwts.parser()
.requireIssuer(ISSUER)
.setSigningKey(SECRET)
.parseClaimsJws(jwt);
Here is the 0.11 code:
Jws claims = Jwts.parserBuilder()
.requireIssuer(ISSUER)
.setSigningKey(Keys.hmacShaKeyFor(Decoders.BASE64.decode(SECRET)))
.build()
.parseClaimsJws(token);