From e22667e5824941fd6dae6968ce85692740050920 Mon Sep 17 00:00:00 2001 From: Miguel Landaeta Date: Mon, 10 Aug 2026 14:00:03 +0100 Subject: [PATCH] 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. --- lib/jwt/eddsa/jwk/okp.rb | 2 +- spec/jwt/jwk/okp_spec.rb | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/lib/jwt/eddsa/jwk/okp.rb b/lib/jwt/eddsa/jwk/okp.rb index ea17a84..35af1ae 100644 --- a/lib/jwt/eddsa/jwk/okp.rb +++ b/lib/jwt/eddsa/jwk/okp.rb @@ -7,7 +7,7 @@ module JWK class OKP < ::JWT::JWK::KeyBase KTY = "OKP" KTYS = [KTY, JWT::EdDSA::JWK::OKP, Ed25519::SigningKey, Ed25519::VerifyKey].freeze - OKP_PUBLIC_KEY_ELEMENTS = %i[kty n x].freeze + OKP_PUBLIC_KEY_ELEMENTS = %i[crv kty x].freeze OKP_PRIVATE_KEY_ELEMENTS = %i[d].freeze def initialize(key, params = nil, options = {}) diff --git a/spec/jwt/jwk/okp_spec.rb b/spec/jwt/jwk/okp_spec.rb index 0aa438b..be2adb7 100644 --- a/spec/jwt/jwk/okp_spec.rb +++ b/spec/jwt/jwk/okp_spec.rb @@ -73,6 +73,16 @@ end end + describe "#kid" do + # Test vector from RFC 8037 Appendix A.3 (JWK Thumbprint Canonicalization): + # https://www.rfc-editor.org/rfc/rfc8037#appendix-A.3 + let(:key) { { kty: "OKP", crv: "Ed25519", x: "11qYAYKxCrfVS_7TyWQHOg7hcvPapiMlrwIaaPcHURo" } } + + it "matches the RFC 7638 JWK thumbprint of the crv/kty/x members" do + expect(instance.kid).to eq("kPrK_qmxVWaYVA9wwBF6Iuo3vVzz7TxHCTwXBygrS4k") + end + end + describe "#export" do let(:options) { {} } subject { instance.export(options) }