google / jwt_verify_lib

Provide c++ library to verify JWT tokens
Apache License 2.0
42 stars 43 forks source link

JWKs parse issue when using non standard exponent (not 3 or 65537) #96

Open michaelpaliy opened 1 year ago

michaelpaliy commented 1 year ago

As raised in https://github.com/istio/istio/issues/41729

If a JWK has an exponent different from 65537 or 3, the parsing fails with the following error: "Jwks RSA [n] or [e] field is missing or has a parse error"

For example, parsing will fail for the following valid JWK:

{
 "keys": [
  {
      "n": "q9hO0xKd6KfjXRxzAzLYnV-o4wm7aRMSr27ajF2bDedVFMJ-G6Y01lRsSn0zTusBCbax10dEOMg1g_GEWWqG_hYYq2eQ0RAWHAEfUUZHacu1MrGUFFcmbRYlR_Q1lM-e-831yFFbDPZAIUpyN_8qZuVL1fN2cGRXNcAyVzrDqu2h1pdjQykyMGPKr9X3xxMZ-IHDhbnZjdeYBHJPvwic2G-_Wp1ZrHxBhUykZuAVS3RMFDH-pV6-_W0rOENv3tZmxBTTSGIGNHYGaMg_qrnVDZuNOv3XGv_McqlD0RFifqtCO5QQtCQAdwMXHxmv2SxC04LsFL3GgSh_G3otGhwItQ",
      "e": "Iw",
      "kty": "RSA",
      "alg": "RS256",
      "kid": "1u-zN2fkExpEMumSNIYBfV8XPjFPHalL8IM6mO285yE"
  }
 ]
}

I couldn't find any reference that the exponent must be 65537 or 3, even though 65537 is commonly used.

opened PR https://github.com/google/jwt_verify_lib/pull/95, which should fix the JWK validation. I'd appreciate if you could review it.

nareddyt commented 1 year ago

This is something I'm not familiar with. Let me try pulling in some crypto experts.

Based on https://crypto.stackexchange.com/a/3113

Only the Fermat primes 3,5,17,257,65537 have both properties, and all are common choices of 𝑒

Are you sure e can be any non-negative number?

sophieschmieg commented 1 year ago

In theory, e can be any non-negative number that is coprime to the Euler totient of n. In practice, the exponent should always be 65537, and even 3 should be discouraged, given Coppersmith attacks, and I don't think allowing different exponents is a good idea.

michaelpaliy commented 1 year ago

I agree that 65537 is the best practice. But this library is used for JWT validation, and I think it should accept all the valid exponent values (even if they are not the best practice/not secured enough). In my case, the Idp service (external provider) uses different values for the exponent, which prevents us from using istio authentication. As the exponent is not 65537 or 3, we get the following error: Jwks RSA [n] or [e] field is missing or has a parse error.

davidben commented 1 year ago

Supporting arbitrary values of e is also a DoS risk. BoringSSL won't accept any e over 33 bits for this reason. We're stuck being a bit more permissive than just 3 and 65537, but the constraints in this library are sound. I don't think it makes sense to change it.

Were RSA standardized correctly, we'd have just picked the one value of e as part of a parameter set and moved on with life.