-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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
SecretKey algorithm did not equal one of the three required JCA #381
Comments
I understand why you'd be frustrated after two hours, but we're here to help, please try not to be too confrontational. The entire codebase has 100% code coverage, so we try extremely hard to ensure that everything works perfectly, but even code coverage assertions have their faults. The internal JCA provider should have identical names on both creation and key.getAlgorithm() results. Could you please tell us if you're running standard JDK, Android or BouncyCastle? |
I just ran a test and this succeeds: @Test
void testSecretKeyFor() {
for (SignatureAlgorithm alg : SignatureAlgorithm.values()) {
String name = alg.name()
if (alg.isHmac()) {
SecretKey key = Keys.secretKeyFor(alg)
assertEquals alg.minKeyLength, key.getEncoded().length * 8 //convert byte count to bit count
assertEquals alg.jcaName, key.algorithm
alg.assertValidSigningKey(key)
alg.assertValidVerificationKey(key)
assertEquals alg, SignatureAlgorithm.forSigningKey(key)
} else {
try {
Keys.secretKeyFor(alg)
fail()
} catch (IllegalArgumentException expected) {
assertEquals "The $name algorithm does not support shared secret keys." as String, expected.message
}
}
}
} Notice the lines: alg.assertValidSigningKey(key)
alg.assertValidVerificationKey(key)
assertEquals alg, SignatureAlgorithm.forSigningKey(key) These assert that the key (created from The only thing I can think of: what version of the JDK are you using? |
…natureAlgorithm helper methods. Resolves #381
Even with the test the JCA name is less important than the key length, so I'll use this ticket to change the assertion from a name to a key length. We'll get a quick 0.10.3 release out asap to address this. Even so, what version of the JDK are you using? |
…natureAlgorithm helper methods. Resolves #381
…r methods for hmac key lengths. Resolves #381 Prepping for a 0.10.3 point release
Hi Les, Thanks for your prompt feedback. Our engineer directly in charge of this actually already left for today. We found this issue by actually stepping into the class Honestly, we also found very strange that a library so popular has such a stupid issue, but we can actually reproduce it at least on Android. TTY tomorrow. Thanks again! |
Anyway, I agree that directly string comparison (case-sensitive) is not the best solution. On Android we may have it in camelcase, as it seems to be the case. Are we the first ones to use it on Android? 🤔 |
Hi @rodmaz Thanks for letting me know. It's not a stupid issue in JJWT however - the release where you're seeing the issue is only a week or so old. I have had feedback from Android devs that are using JJWT 0.10.x in prod - they probably just haven't come across this particular edge case based on how they use JJWT. What is stupid IMO is that the Android JVM has an internal discrepancy on how it names JCA algorithms. This problem doesn't exist on any JDK that we test on (7, 8, 9 and 10). Our build system tests on all of these JDKs, but, to the best of my knowledge, there is no Travis CI ability to run both JDK and Android VMs in a single Travis CI project, otherwise we would have caught this (IMO bug) that is Android's fault. If anyone knows how to add Android VMs into our existing Travis setup, I'd love to know how. Otherwise, we try really hard to test things based on Android's public APIs and cursory testing from the Android community. I'd love some extra Android CI help here if possible. |
P.S. I'm cutting a 0.10.3 release tonight so you shouldn't see this issue (since the assertion will be on key lengths only). Your engineer should be able to try tomorrow with the new 0.10.3 release and have it work out. If not, don't worry - I'm happy to help and we'll get you guys up and running asap. :) |
@lhazlewood Thanks Les! We were about to fork it and do a pull-request tomorrow. We will analyse and let you know. |
We also saw some (in fact many) situations in which the JJWT actually freezes on Android when we called the |
@rodmaz any information on those freezes would be greatly appreciated. There are a ton of people using JJWT in Android, so if we can fill in any remaining gaps, all the better. |
…r methods for hmac key lengths. Resolves #381 Updated Android dependencies and ProGuard exclusion definitions Prepping for a 0.10.3 point release
Released with 0.10.3 - please allow 30 min or so to propagate to Maven Central. |
@lhazlewood This is what we see on Android 5.1 (old) and Android 8 (Samsung). Even when using Android emulator on macOS the problem exists with camelcase. We cannot understand how this could possibly have worked on Android before. |
@lhazlewood We just tested version 0.10.3 and it turns out the problem persists. The class |
Thanks for the follow up - I really appreciate it. In my haste to get you up and running, I only fixed what was reported. I'll do a full usage search of I'll fix this asap and get 0.10.4 out. Sorry for the trouble. |
P.S. Does anyone know how to test this in CI? We put in a great deal of work to put in 100% code coverage on every build specifically to catch these types of 'gotchas', but that's not guaranteed unless Android is part of the CI runs. As an example, I found this Android project on GH, and looked at its travis config: The If that's the case (using Oracle JDK 8), and all JJWT Oracle JDK 8 builds pass without exposing this problem, wouldn't this problem stay hidden and not be resolved with TravisCI? Or does |
@lhazlewood Thanks! P.S. We do not use TravisCI but you can also check out this post. |
@rodmaz I read the article but the examples there also show using |
This is pretty clear to me that this is an Android bug. The standard names are defined here: https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#KeyGenerator And those are the ones JJWT uses. That Android returns something different is a violation of the spec names. |
Wow - from that document, nestled in one little innocuous line:
Well, this is a good confirmation of the |
Released in 0.10.4. Please allow 30 minutes to propagate to Maven Central. |
@lhazlewood I've encountered a similar bug with loading the key in a PKCS 12 keystore. The algorithm name of the secret key algorithm gets for some reason (guess it's because it's mandated by the PKCS12 spec) converted to an OID (e.g. HmacSHA512 becomes 1.2.840.113549.2.11; see http://www.oid-info.com/cgi-bin/display?oid=1.2.840.113549.2.11&action=display). After loading the key, the algorithm identifier stays in the OID format and thus your check fails. I've solved this problem by switching to a different keystore format (JCEKS in my case). Couldn't make the PKCS12 one work. The sad thing is that PKCS12 is the default since some relatively recent Java release (9 I guess; my problem was on JDK11). |
@rpanak-generalbytes can you please help me understand how/where JJWT is involved in what you're seeing? JJWT doesn't load keys from keystores. Do you have any example code that demonstrates a problem? Thanks! |
Sure. You are right, JJWT is not involved with keystores. However, that is just an information about how to reproduce the problem (to be precise, how to unwillingly create a valid The problem itself is that you can have a valid Also, I have found that |
@lhazlewood This is closed now, but I too am experiencing issues with a HmacSha512 Key loaded from a PKCS 12. I'm unsure, whether this is an Issue with the JDK I'm using (OpenJDK in this case) or a problem with jjwt. The following example might illustrate the problem:
Edit: formatting and reducing example |
I think |
Created a Test Project with the given code example, which can be used to reproduce the issue. Could reproduce with OpenJDK11 as well. Looking at Java Security Standard Algorithm Names though, I can't find the String '1.2.840.113549.2.11' anywhere in the document. I would have expected the KeyStore to load the key with the Standard Algorithm name. I might be overlooking something though in the JCA Reference, which would indicate this behaviour. |
Meanwhile I found the following Workaround:
|
Since the corresponding bug report at OpenJDK seems to be accepted and we have a workaround, IMHO this issue can stay closed. |
The alternative is to remove these lines from the assertion check entirely: jjwt/api/src/main/java/io/jsonwebtoken/SignatureAlgorithm.java Lines 353 to 359 in c09deaa
But I'm a little hesitant to do that: removing those lines could still allow keys that fail when calling The safest implementation change would be to remove those lines and then actually perform a test mac calculation, e.g. private void assertValidHmac(Key key) {
try {
Mac mac = Mac.getInstance(this.jcaName);
mac.init(key);
mac.doFinal(dummyData);
catch (IllegalStateException ise) {
throw new InvalidKeyException("whatever", ise);
}
} The problem with this approach is that it could be a performance hit due to the extra non-essential calculation. We'd have to ensure that it is used in a calculated fashion and it might be more effort than it's worth, especially with the workaround that @fibsifan posted. Thoughts? |
@lhazlewood I think this is a no-brainer. The safest implementation is to accept the proper aliases (OIDs) as well as the current algorithm names (they're both just alternative names for the same thing). I don't see any downside (correct me if I'm wrong). Easy to implement as well, just add three more cases into the appropriate if statement. The OIDs can be Googled, or found here or the JDKs sources link I've already posted before. @fibsifan Open JDK bug is a long way from fixed :). In the meantime, we're left to deal with the present problem. |
Adding the OIDs to the check is easy enough - thanks for suggesting the solution! Reopening so we can address it in a future release. |
Actually, closing this (since it is tied to the 0.10.4 release) and opening a new issue to track that work. |
OIDs will be added to the validation check via #588 |
Hi there,
We have struggled for over 2 hours to get this library to work (for a such a simple task (JWT) as to generate a simple JWT). Not a good start!
We end up figuring out the final problem to be this exception:
SecretKey algorithm did not equal one of the three required JCA algorithm names of HmacSHA256, HmacSHA384, or HmacSHA512.
The collection
PREFERRED_HMAC_ALGS
hasjcaName
s internally asHmacSHA256
etc. using camelcase. However when we generate a key using the library:val key = Keys.secretKeyFor(SignatureAlgorithm.HS256)
The internal jcaName generated in the key is
HMACSHA256
, all uppercase. The methodSignatureAlgorithm()
throws an exception [here]jjwt/api/src/main/java/io/jsonwebtoken/SignatureAlgorithm.java
Line 560 in 1839ebf
Are we doing something wrong? It can't be this library has such a stupid string comparison bug and nobody else has notice it?!
We are using the version
0.9.0
frommaster
.The text was updated successfully, but these errors were encountered: