ory/hydra · error

Could not convert key to RSA Public Key, got: %T

Error message

Could not convert key to RSA Public Key, got: %T

What it means

jwk.ToRSAPublic converts a *jose.JSONWebKey to *rsa.PublicKey; if the key's underlying Key is not an RSA public key the cast fails and this error is returned. It indicates the JWK being consumed is EC/OKP/symmetric rather than RSA.

Source

Thrown at jwk/cast.go:28

	jose "github.com/go-jose/go-jose/v3"
	"github.com/pkg/errors"
)

func MustRSAPublic(key *jose.JSONWebKey) *rsa.PublicKey {
	res, err := ToRSAPublic(key)
	if err != nil {
		panic(err.Error())
	}

	return res
}

func ToRSAPublic(key *jose.JSONWebKey) (*rsa.PublicKey, error) {
	pk := josex.ToPublicKey(key)
	res, ok := pk.Key.(*rsa.PublicKey)
	if !ok {
		return res, errors.Errorf("Could not convert key to RSA Public Key, got: %T", pk.Key)
	}

	return res, nil
}

func MustRSAPrivate(key *jose.JSONWebKey) *rsa.PrivateKey {
	res, err := ToRSAPrivate(key)
	if err != nil {
		panic(err.Error())
	}

	return res
}

func ToRSAPrivate(key *jose.JSONWebKey) (*rsa.PrivateKey, error) {
	res, ok := key.Key.(*rsa.PrivateKey)
	if !ok {
		return res, errors.New("Could not convert key to RSA Private Key.")

View on GitHub (pinned to 4174065ffb)

Solutions

  1. Select the RSA key from the JWKS (filter by kty == "RSA" or the alg/kid actually used to sign)
  2. Use a generic verifier that dispatches on key type (e.g. jose's verifier with the JSONWebKey directly) instead of forcing RSA conversion
  3. If the provider uses EC keys, switch your verification logic to ToECPublic / ECDSA verification
  4. Before calling, guard: if k, _ := josex.ToPublicKey(jwk); _, ok := k.Key.(*rsa.PublicKey); !ok { handle non-RSA path }

Example fix

// before
rsaKey, err := jwk.ToRSAPublic(jwks.Key(0)) // key 0 may be EC
// after
var rsaKey *rsa.PublicKey
for _, k := range jwks.Keys {
    if k.Kty == "RSA" {
        rsaKey, err = jwk.ToRSAPublic(&k)
        break
    }
}
Defensive patterns

Strategy: type-guard

Validate before calling

func isRSAJWK(j *jose.JSONWebKey) bool {
    pk, err := jwk.ToRSAPublic(j)
    return err == nil && pk != nil
}
// use before calling ToRSAPublic
if !isRSAJWK(candidate) { select another key from the JWKS }

Type guard

func asRSAPublic(j *jose.JSONWebKey) (*rsa.PublicKey, bool) {
    pk, err := jwk.ToRSAPublic(j)
    if err != nil || pk == nil { return nil, false }
    return pk, true
}

Try / catch

rsaKey, err := jwk.ToRSAPublic(key)
if err != nil && strings.Contains(err.Error(), "Could not convert key to RSA Public Key") {
    // fall back to EC verification or pick an RSA key from the JWKS
    return verifyWithJWKey(rawToken, key)
}

Prevention

When it happens

Trigger: Calling ToRSAPublic (public) on a JWK parsed from a JWKS or id_token header whose key type (kty) is not RSA — e.g. EC (P-256) or oct keys — typically via MustRSAPublic during token verification or client key handling.

Common situations: OIDC providers publishing ES256 signing keys while the consumer assumes RS256/RSA; fetching a JWKS where the selected kid points at an EC key; hardcoding RSA assumptions when migrating providers.

Related errors


AI-assisted analysis of ory/hydra@4174065ffb (2026-09-03). Data as JSON: /api/errors/f4fdca32276c8253. Report an issue: GitHub.