Skip to content

Fix: Change OKP JWK thumbprint to use crv/kty/x, not RSA's kty/n/x - #26

Merged
anakinj merged 1 commit into
jwt:mainfrom
nomadium:fix-okp-jwk-thumbprint
Aug 13, 2026
Merged

Fix: Change OKP JWK thumbprint to use crv/kty/x, not RSA's kty/n/x#26
anakinj merged 1 commit into
jwt:mainfrom
nomadium:fix-okp-jwk-thumbprint

Conversation

@nomadium

Copy link
Copy Markdown
Contributor

Description

Fix OKP JWK thumbprint: use crv/kty/x, not RSA's kty/n/x

OKP_PUBLIC_KEY_ELEMENTS was copy-pasted from an RSA-shaped element list (kty, n, x). "n" is the RSA modulus and never applies to OKP (Ed25519) keys, so it always serialized as null; "crv" is required by RFC 8037 but was missing entirely.

This list feeds JWK::OKP#members, which JWT::JWK::Thumbprint (RFC 7638) uses directly to compute the SHA-256 thumbprint, and jwt's default kid_generator (:key_digest) uses that thumbprint as the auto-generated "kid" for every key this gem creates. As a result, every kid produced by this gem is computed over the wrong JSON ({"kty":"OKP","n":null,"x":"..."}) instead of the RFC 7638-correct {"crv":"Ed25519","kty":"OKP","x":"..."}, so it never matches the thumbprint a spec-compliant verifier computes for the same key.

Add a regression test pinned to the published RFC 8037 Appendix A.3 thumbprint test vector.

Checklist

Before the PR can be merged be sure the following are checked:

  • There are tests for the fix or feature added/changed

Notes

I stumbled upon this issue after investigating why JWK keys generated by Linzer gem (which depends on jwt-eddsa) and associated HTTP message signatures were failing verification at a CloudFlare debug utility website.

OKP_PUBLIC_KEY_ELEMENTS was copy-pasted from an RSA-shaped element
list (kty, n, x). "n" is the RSA modulus and never applies to OKP
(Ed25519) keys, so it always serialized as null; "crv" is required by
RFC 8037 but was missing entirely.

This list feeds JWK::OKP#members, which JWT::JWK::Thumbprint (RFC
7638) uses directly to compute the SHA-256 thumbprint, and jwt's
default kid_generator (:key_digest) uses that thumbprint as the
auto-generated "kid" for every key this gem creates. As a result,
every kid produced by this gem is computed over the wrong JSON
({"kty":"OKP","n":null,"x":"..."}) instead of the RFC 7638-correct
{"crv":"Ed25519","kty":"OKP","x":"..."}, so it never matches the
thumbprint a spec-compliant verifier computes for the same key.

Add a regression test pinned to the published RFC 8037 Appendix A.3
thumbprint test vector.
nomadium added a commit to nomadium/linzer that referenced this pull request Aug 10, 2026
…sa's kid

jwt-eddsa (<= 0.9.0) computes JWK::OKP's thumbprint over the wrong
members ({kty, n, x} instead of the RFC 8037-correct {crv, kty, x}),
so the Web Bot Auth `keyid` derived from it never matched what a
spec-compliant verifier expects.

Add Linzer::JWS::Key#jwk_thumbprint and use it instead, so Linzer
is correct independent of jwt/ruby-jwt-eddsa#26.
@anakinj anakinj changed the title Fix OKP JWK thumbprint: use crv/kty/x, not RSA's kty/n/x Fix: Change OKP JWK thumbprint to use crv/kty/x, not RSA's kty/n/x Aug 11, 2026
@anakinj

anakinj commented Aug 13, 2026

Copy link
Copy Markdown
Member

Thanks for the fix. Technically its a breaking change but in the other hand it was so broken from before.

Think i'll just cut a 1.0 release with this included.

@anakinj
anakinj merged commit 7760623 into jwt:main Aug 13, 2026
9 of 11 checks passed
@nomadium
nomadium deleted the fix-okp-jwk-thumbprint branch August 13, 2026 09:40
anakinj added a commit that referenced this pull request Aug 14, 2026
BREAKING CHANGE: Auto-generated `kid` values for OKP JWKs are now computed from the RFC 8037 required members (crv, kty, x) instead of the incorrect (kty, n, x). Previously generated kid values will no longer match; keys with an explicitly provided kid are unaffected.

Release-As: 1.0.0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants