auth0 / java-jwt

Java implementation of JSON Web Token (JWT)

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

token signature verification fails for ECDSA and jwks starting with java 15

meraedit opened this issue · comments

The JWT token is not verified when using the key from jwks in the latest java version (or >=15.0.2), but it worked with older java versions (11, 13, 14).

Reproduction

Please run the attached java code jwt verification.zip
You need to serve the atached keys.json and update the url in the java sample.
When using an older java version (up to 14.0.2) it verifies the token using the key from the provided jwks.

When using java 17, it throws
Exception in thread "main" com.auth0.jwt.exceptions.SignatureVerificationException: The Token's Signature resulted invalid when verified using the Algorithm: SHA256withECDSA
at com.auth0.jwt.algorithms.ECDSAAlgorithm.verify(ECDSAAlgorithm.java:52)
at com.auth0.jwt.JWTVerifier.verify(JWTVerifier.java:299)
at com.auth0.jwt.JWTVerifier.verify(JWTVerifier.java:283)
at com.servoy.extensions.plugins.jwt.client.TestJWKS.verifyToken(TestJWKS.java:129)
at com.servoy.extensions.plugins.jwt.client.TestJWKS.main(TestJWKS.java:121)

Environment Windows 64-bit

  • Version of this library used: 3.18.1
  • Version of Java used: 17.0.1 (fails starting with java version 15.0.2)
  • Other modules/plugins/libraries that might be involved: jwks-rsa-java
  • Any other relevant information you think would be useful:
    Verifying the token is successful with any java version I tried (from java 11 to java 17) when providing the public key (not via jwks), as demonstrated in the attached sample.
    The public key obtained from jwks looks the same in any java version I tried, therefore I suspect that the issue is related to the token verification part and not to the public key.

Our company hit this as well with java 17

I did more investigations for this issue and everything that is provided to the method below is the same in both Java 14 and Java 17.
boolean verifySignatureFor(String algorithm, PublicKey publicKey, byte[] headerBytes, byte[] payloadBytes, byte[] signatureBytes) throws NoSuchAlgorithmException, InvalidKeyException, SignatureException {
final Signature s = Signature.getInstance(algorithm);
s.initVerify(publicKey);
s.update(headerBytes);
s.update(JWT_PART_SEPARATOR);
s.update(payloadBytes);
return s.verify(signatureBytes);
}
It looks like the problem is in Java itself. So I'm wondering what/if can we do to fix the issue in the lib...

Do we know what the underlying exception that the JDK is throwing here? Did one of the string constants for the algorithm get renamed?

The sample code you shared seems to reproduce the issue. But seeing the changelogs for Java 15, though they have disabled support for certain curves in the EC algorithm, the key used in the sample seems to be supported.

I generated a new key pair and the issue is not reproducing in that.

{
    "kty": "EC",
    "d": "R-Xl0RKnGydQkC5CYRv-IQCTHSU_fcH8smkHmtWuHoM",
    "use": "sig",
    "crv": "P-256",
    "kid": "jfUXSPjX9HJfLgYhzSpL68CxRilx6Xrmy9CSOK7lRPs",
    "x": "EzYel6UO99KDYJbEwUscNAn2DcFsLd0Se5KvoMcjviw",
    "y": "XLQ3GYS5DwEuuhQ2zanVWGixBZ-D3-576vZVXFNxvdQ",
    "alg": "ES256"
}

Can you tell us how you generated the keys so that we can try and debug further?

Hello, I just used this site https://mkjwk.org/ to generate the keys and the jwks .. since that was only for testing purposes.

This is the one that I used in the sample, if it helps:
{
"kty": "EC",
"d": "18HYhm2RcgS8OXbofnClTpFNnEQrSwpnKH6uBuL9pgA",
"use": "sig",
"crv": "P-256",
"kid": "3LNaPaJX93XTknKf0L_RGoZGM0BKaqtWdAzSQxP-FDg",
"x": "yb790G3aOB92lsoGfrhQratQBvA330pi8rMeorATe7c",
"y": "E1WCwNSDv2hp4Ttgu7HY0zbEPpcrHIMnP16XrtMQ69Q",
"alg": "ES256"
}
Public key: "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEyb790G3aOB92lsoGfrhQratQBvA3\n" +
"30pi8rMeorATe7cTVYLA1IO/aGnhO2C7sdjTNsQ+lyscgyc/Xpeu0xDr1A=="
Private key: "MEECAQAwEwYHKoZIzj0CAQYIKoZIzj0DAQcEJzAlAgEBBCDXwdiGbZFyBLw5duh+\n" +
"cKVOkU2cRCtLCmcofq4G4v2mAA=="

Thanks @meraedit I checked it out and looks like keys generated from the same site works for me in the same sample code. Can you try it again? Probably there was some issue while copying the code or you can check the configuration I have selected and verify whether it is the same you used.

Screenshot 2022-02-18 at 15 58 12

The difference is that I selected SHA-256 instead of "Specify" for the Key ID

That shouldn't be an issue, I tested it with SHA as well, it is just a selector and it worked. Is the issue still reproducing for you if you generate new keys from the same website?

I generated another one and it doesn't verify the token when using the jwk store.
key

Public and Private Keypair
{
"kty": "EC",
"d": "vpdg7gNZ4qF7RaAvPJ87b1QQEWzCzRrN_4L9QQeeaM8",
"use": "sig",
"crv": "P-256",
"kid": "123",
"x": "b25UZzwkKpPK5FlPjAtqhlii6MkOnhxqXo9pK3Mfa6A",
"y": "z2lSXy6byzVdSExkqlsYLd8Lrzqw1rYEiEzWWOQ8rNI",
"alg": "ES256"
}

Private Key (X.509 PEM Format)
-----BEGIN PRIVATE KEY-----
MEECAQAwEwYHKoZIzj0CAQYIKoZIzj0DAQcEJzAlAgEBBCC+l2DuA1nioXtFoC88
nztvVBARbMLNGs3/gv1BB55ozw==
-----END PRIVATE KEY-----

Public Key (X.509 PEM Format)

-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEb25UZzwkKpPK5FlPjAtqhlii6MkO
nhxqXo9pK3Mfa6DPaVJfLpvLNV1ITGSqWxgt3wuvOrDWtgSITNZY5Dys0g==
-----END PUBLIC KEY-----

-----BEGIN CERTIFICATE-----
MIIBDTCBtKADAgECAgYBfwxqNG0wCgYIKoZIzj0EAwIwDjEMMAoGA1UEAwwDMTIz
MB4XDTIyMDIxODEwMzkyMVoXDTIyMTIxNTEwMzkyMVowDjEMMAoGA1UEAwwDMTIz
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEb25UZzwkKpPK5FlPjAtqhlii6MkO
nhxqXo9pK3Mfa6DPaVJfLpvLNV1ITGSqWxgt3wuvOrDWtgSITNZY5Dys0jAKBggq
hkjOPQQDAgNIADBFAiEAjP7/STTMlzShep461Bh8Cv0rZ26xax+nKEDUTyVJb2QC
IA1e6w92PjqR2mxkefIQ59NMvH1MBO+Nurju3ZLSyQ9F
-----END CERTIFICATE-----

@meraedit I guess we figured the issue. You are choosing the option with a disabled curve type secp256k1. You can read it in this changelog for Java 15 - https://www.oracle.com/java/technologies/javase/15-relnote-issues.html#JDK-8237219

You can choose the option which doesn't mention the curve (1st option in the website) and it should work.

Since this is a change in JDK itself I guess we won't be able to support this now. I will close this issue for now but please feel free to reopen it if there is more doubts regarding this

Thanks @meraedit for bringing this to our notice. We have a PR to reflect the same in our README. Thanks again for your effort and quick responses. Much appreciated

Thank you for investigating the issue, it's good to know that some types of keys are not not supported by java anymore.

However, something is still unclear to me. I see there is a secp256k1 option for the curve on the site, but I selected P-256 as you can see in my screenshot.

I also see "crv": "P-256" for all the keys I pasted. Or is there something wrong with the site? Selecting P-256 and it actually generates something else?

I generate with
Curve - P-256
Key Use - Signature
Algorithm - ES256: ECDSA using P-256 and SHA-256

Which generates following values
JWK

{
    "kty": "EC",
    "d": "wUnTMCQ3g3l4gUrIP5ygaOBQPj5fPFeO7lf708sQAgU",
    "use": "sig",
    "crv": "P-256",
    "kid": "123",
    "x": "PQNy-oSvcVHzbyUC7lHUlrGf3AjRiWuFZwwkTjxCL14",
    "y": "FS8mxmVEZUx6J1QYGOwXcPj6_aeGkry_oSQCv4FKAzM",
    "alg": "ES256"
}

Private Key

-----BEGIN PRIVATE KEY-----
MEECAQAwEwYHKoZIzj0CAQYIKoZIzj0DAQcEJzAlAgEBBCDBSdMwJDeDeXiBSsg/
nKBo4FA+Pl88V47uV/vTyxACBQ==
-----END PRIVATE KEY-----

Public Key

-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEPQNy+oSvcVHzbyUC7lHUlrGf3AjR
iWuFZwwkTjxCL14VLybGZURlTHonVBgY7Bdw+Pr9p4aSvL+hJAK/gUoDMw==
-----END PUBLIC KEY-----

And for this, the sample code you shared seems to work. Can you try these values in your code?

I can confirm that the pair above works, thank you.
But I generated the one in the screenshot with the same Curve - P-256, Key Use - Signature, Algorithm - ES256: ECDSA using P-256 and SHA-256 and my sample fails. So I don't really know what is the difference then.

What is the JDK you are using? I am using Amazon Corretto v15.0.2

I am using JDK v15.0.2 and v.17.0.1 and it's the same behavior with openjdk v.17.0.1

@meraedit I guess the issue is with the website. Some keys generated doesn't seem to be working. Can you try with other algorithms or generate the keys using openssl in one of the supported curves?

Thank you, I will use openssl from now on.
RSA algo works, we only had problems with ECDSA and jwks. It is weird that ECDSA without jwks worked also.