ruby-jwt icon indicating copy to clipboard operation
ruby-jwt copied to clipboard

Use RFC 7638 JWK Thumbprints as kid

Open bellebaum opened this issue 3 years ago • 4 comments

The current method for calculating JWK kids is something like

      def generate_kid(ec_keypair)
        _crv, x_octets, y_octets = keypair_components(ec_keypair)
        sequence = OpenSSL::ASN1::Sequence([OpenSSL::ASN1::Integer.new(OpenSSL::BN.new(x_octets, BINARY)),
                                            OpenSSL::ASN1::Integer.new(OpenSSL::BN.new(y_octets, BINARY))])
        OpenSSL::Digest::SHA256.hexdigest(sequence.to_der)
      end

for EC and something similar for RSA. I am unsure if there is some standard that this behavior is based on.

RFC 7638 describes a canonical way to derive a Thumbprint for a JWK, the base64url encoding of which is advertised as a "good" kid is the following:

  1. Construct a JSON object [RFC7159] containing only the required members of a JWK representing the key and with no whitespace or line breaks before or after any syntactic elements and with the required members ordered lexicographically by the Unicode [UNICODE] code points of the member names. (This JSON object is itself a legal JWK representation of the key.)

  2. Hash the octets of the UTF-8 representation of this JSON object with a cryptographic hash function H. For example, SHA-256 [SHS] might be used as H. See Section 3.4 for a discussion on the choice of hash function.

In some (admittedly rare) cases algorithms seem to rely on this behavior, which is why many popular JWT libraries seem to implement it (including json-jwt). Should this be implemented here as well?

bellebaum avatar Mar 11 '22 13:03 bellebaum

I should mention that the above current method should result in the same kid for keys with the same coordinates in different curves. I am unsure whether or not that can be a security risk.

bellebaum avatar Mar 11 '22 14:03 bellebaum

You're right. The kid calculation is pretty random at the moment. Problem with it is that it's "out there" already, so changing it will be somewhat challenging without breaking things.

Think we could at least support calculating the thumbprints for the jwks as a first step.

Looked into the RFC a while ago and did some experimenting. https://github.com/anakinj/ruby-jwt/blob/jwk-okp-support/lib/jwt/jwk/thumbprint.rb.

anakinj avatar Mar 16 '22 06:03 anakinj

Just to pin this here, so any related issues can be pointed to this issue. Some upcoming specifications increasingly rely on this form of kids as entity identifiers:

  • https://datatracker.ietf.org/doc/draft-ietf-oauth-jwk-thumbprint-uri/ (should become an RFC soon)
  • https://openid.net/specs/openid-connect-self-issued-v2-1_0.html (Currently an Implementer's Draft)

bellebaum avatar Jun 14 '22 07:06 bellebaum

I just tried to use the functionality introduced by #481, taking it straight from the documentation on the repo homepage — unfortunately, that gave me an "uninitialized constant" error, because the functionality is in the current unreleased 2.5.0. Took me a second to realise why the example from the documentation didn't work.

#501 would probably cause similar issues, because options[:kid_not_found] will never be set by the current version.

liamdawson avatar Jul 15 '22 06:07 liamdawson