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
- Select the RSA key from the JWKS (filter by kty == "RSA" or the alg/kid actually used to sign)
- Use a generic verifier that dispatches on key type (e.g. jose's verifier with the JSONWebKey directly) instead of forcing RSA conversion
- If the provider uses EC keys, switch your verification logic to ToECPublic / ECDSA verification
- 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
- Filter JWKS keys by kty=="RSA" (and the signing alg/kid) before RSA conversion
- Support ECDSA verification for providers that publish ES256 keys
- Never assume key type from the provider; read kty/alg from the JWK
- Cache JWKS per kid and re-check key type on rotation
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
- invalid JWK key
- unknown algorithm %s for signing key
- unknown algorithm %s for encryption key
- square/go-jose: parse error, got '%s', '%s' and '%s'
- square/go-jose: parse error, got '%s', '%s', '%s' and '%s'
AI-assisted analysis of ory/hydra@4174065ffb (2026-09-03).
Data as JSON: /api/errors/f4fdca32276c8253.
Report an issue: GitHub.