Skip to content
ecdsa.com

PEM ⇄ JWK · Ruby

How to convert a PEM public key to a JWK and back in Ruby

In Ruby, the jwt gem's JWT::JWK converts OpenSSL keys to JWKs and back: JWT::JWK.new(OpenSSL::PKey.read(pem)).export gives the JWK, and JWT::JWK.import(hash).verify_key gives an OpenSSL key whose public_to_pem writes the PEM. The run checks the RFC 7515 round trip byte for byte.

Tested with jwt (ruby-jwt) 3.3.0 (Ruby 4.0.7, openssl gem 4.0.2).

convert.rb — PEM to JWK and JWK to PEM with the jwt gem
require "jwt" # gem install jwt -v 3.3.0
require "json"
require "openssl"
# PEM -> JWK: export without the generated kid, public members only
jwk = JWT::JWK.new(OpenSSL::PKey.read(File.read("pub.pem")))
public_jwk = jwk.export.except(:kid)
File.write("out.jwk.json", JSON.generate(public_jwk))
puts JSON.generate(public_jwk)
# JWK -> PEM: import the JWK, take the OpenSSL key, write SPKI PEM
key = JWT::JWK.import(JSON.parse(File.read("pub.jwk.json"))).verify_key
File.write("out.pem", key.public_to_pem)
print key.public_to_pem

How it works

  1. OpenSSL::PKey.read loads the PEM; JWT::JWK.new(key) wraps it as a JWK object for EC, RSA or HMAC keys.
  2. export returns a hash with symbol keys — :kty, :crv, :x, :y and a generated :kid — and never the private members unless asked.
  3. JWT::JWK.import(hash) reads a JWK; verify_key is the OpenSSL public key, built and checked by OpenSSL.
  4. public_to_pem writes the SPKI PEM, identical to the original file.

Gotchas

  • export adds a kid the gem computes itself (its key digest, not the RFC 7638 thumbprint); except(:kid) removes it, or set kid_generator_type = :rfc7638_thumbprint to get a standard one.
  • export(include_private: true) adds d; the default export is public only.
  • An off-curve point fails when the key is built: OpenSSL::PKey::EC::Point::Error: EC_POINT_bn2point: point is not on curve.
  • Ed25519 (OKP) JWKs are not supported by the gem (JWT::UnsupportedKeyType); for those, OpenSSL::PKey.new_raw_public_key("ED25519", raw) and raw_public_key do the conversion.

Related recipes