Skip to content

JWK: support the registered secp256k1 curve name for EC keys #786

Open

Description

@anakinj

Problem

RFC 8812, section 3.1 registers the JWK crv value for the secp256k1 curve as "secp256k1". JWT::JWK::EC only recognises "P-256K", a name from earlier drafts, in lib/jwt/jwk/ec.rb:

  • to_openssl_curve maps 'P-256K' to 'secp256k1' and raises JWT::JWKError, 'Invalid curve provided' for anything else.
  • keypair_components exports secp256k1 keys with crv: 'P-256K'.

As a result, ES256K tokens can't be verified against a JWKS that uses the registered name, and keys exported by ruby-jwt aren't readable by implementations that only accept "secp256k1".

Reproduction (jwt 3.3.0)

key = OpenSSL::PKey::EC.generate("secp256k1")
jwk = JWT::JWK.new(key)
jwk.export[:crv] # => "P-256K"

token = JWT.encode({ sub: "1" }, key, "ES256K", kid: jwk.kid)
standard = jwk.export.merge(crv: "secp256k1")

JWT.decode(token, nil, true, algorithms: ["ES256K"], jwks: { keys: [standard] })
# => JWT::JWKError: Invalid curve provided

JWT.decode(token, nil, true, algorithms: ["ES256K"], jwks: { keys: [jwk.export] })
# => works with "P-256K"

This also shows up with real JWKS. The Connect2id demo JWKS publishes an EC key with crv: "secp256k1". Importing it works because the key is built lazily, but verify_key, private? and export raise, so JWT::JWK::Set#export fails for the whole set. Looking up other keys by kid isn't affected.

Suggested fix

  1. Accept both "secp256k1" and "P-256K" in to_openssl_curve. This is backwards compatible and could go into a patch release.
  2. Export secp256k1 keys with crv: "secp256k1". This changes exported JWKs and their thumbprints for existing secp256k1 keys, so it might fit better in a minor or major release, with a CHANGELOG note.

Posted by Claude on behalf of @anakinj.

Activity

  1. anakinj commented on Nov 4, 2026

    @anakinj
    MemberAuthor

    The import half is fixed by #787, which will ship in 3.3.1. JWT::JWK::EC now accepts both "secp256k1" (RFC 8812) and "P-256K". Imported JWKs keep the curve name they were given, so standard secp256k1 JWKs, such as the one in the Connect2id demo JWKS, can be used to verify ES256K tokens and exported again.

    I'm leaving this open for the export side. Keys created from an OpenSSL::PKey::EC are still exported with crv: "P-256K". Switching to "secp256k1" would change exported JWKs and their RFC 7638 thumbprints, so it's planned for the next minor release, with a CHANGELOG note.

    Posted by Claude on behalf of @anakinj.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions