ory/hydra · error
unsupported private / public key pairs: %T, %T
Error message
unsupported private / public key pairs: %T, %T
What it means
jwt.DefaultSigner.Generate only supports known private key types: ECDSA (ECPrivateKey), RSA (RSAPrivateKey), ed25519 (Ed25519PrivateKey) and their *jose.JSONWebKey/e.JWK wrappers. Falling into the key-pair 'default' branch means the key pair type (the second %T) is not one of these, so no token can be signed.
Source
Thrown at fosite/token/jwt/jwt.go:75
return generateToken(claims, header, jose.ES256, t)
case jose.OpaqueSigner:
switch tt := t.Public().Key.(type) {
case *rsa.PrivateKey:
alg := jose.RS256
if len(t.Algs()) > 0 {
alg = t.Algs()[0]
}
return generateToken(claims, header, alg, t)
case *ecdsa.PrivateKey:
alg := jose.ES256
if len(t.Algs()) > 0 {
alg = t.Algs()[0]
}
return generateToken(claims, header, alg, t)
default:
return "", "", errors.Errorf("unsupported private / public key pairs: %T, %T", t, tt)
}
default:
return "", "", errors.Errorf("unsupported private key type: %T", t)
}
}
// Validate validates a token and returns its signature or an error if the token is not valid.
func (j *DefaultSigner) Validate(ctx context.Context, token string) (string, error) {
key, err := j.GetPrivateKey(ctx)
if err != nil {
return "", err
}
if t, ok := key.(*jose.JSONWebKey); ok {
key = t.Key
}
switch t := key.(type) {View on GitHub (pinned to 4174065ffb)
Solutions
- Provide a supported key type: *ecdsa.PrivateKey, *rsa.PrivateKey, ed25519.PrivateKey, or a *jose.JSONWebKey wrapping one of them
- Parse PEM/DER into the concrete Go key type before passing it to the signer (e.g. x509.ParseECPrivateKey / ParsePKCS8PrivateKey with type switch)
- If keys come from a KMS/HSM, wrap them in a type the signer understands or implement your own Signer interface
- Log the key's %T at startup to confirm which type is actually configured
Example fix
// before
signer := jwt.NewSignerRS256("key-id", pemBytes) // raw bytes, wrong type
// after
block, _ := pem.Decode(pemBytes)
key, err := x509.ParsePKCS8PrivateKey(block.Bytes)
rsaKey, ok := key.(*rsa.PrivateKey)
if !ok { return errors.New("expected RSA private key") }
signer := jwt.NewSignerRS256("key-id", rsaKey) Defensive patterns
Strategy: type-guard
Validate before calling
func assertSignableKey(k interface{}) error {
switch t := k.(type) {
case *rsa.PrivateKey, *ecdsa.PrivateKey, ed25519.PrivateKey, *jose.JSONWebKey, *jwt.ECDSAKeyPair, *jwt.RSAKeyPair, *jwt.Ed25519KeyPair:
return nil
default:
return fmt.Errorf("unsupported signing key type %T", k)
}
} Type guard
func isSupportedJWTKey(k interface{}) bool {
switch k.(type) {
case *rsa.PrivateKey, *ecdsa.PrivateKey, ed25519.PrivateKey, *jose.JSONWebKey,
*jwt.ECDSAKeyPair, *jwt.RSAKeyPair, *jwt.Ed25519KeyPair:
return true
}
return false
} Try / catch
token, sig, err := signer.Generate(ctx, claims, header)
if err != nil && strings.Contains(err.Error(), "unsupported private") {
log.Fatalf("signing key misconfigured: %v", err)
} Prevention
- Parse PEM/DER into concrete Go key types before configuring the signer
- Avoid opaque crypto.Signer or KMS handles unless wrapped in a supported type
- Log the key type at startup when loading signing material
- Keep signer key wiring and key storage in one module so types stay consistent
When it happens
Trigger: Calling Generate (public) with a key pair whose underlying key type is unsupported — e.g. a custom signer exposing a *jose.JSONWebKey whose embedded key is an unsupported algorithm/key type, or passing a pointer-wrapper/PEM string instead of a parsed private key.
Common situations: Loading keys with a parser that yields an unexpected type (e.g. PKCS#1 parsed into interface{}, opaque crypto.Signer wrappers, HSM keys); swapping key providers (KMS, vault) without adapting to jose JSONWebKey; typos when constructing the signer's key interface.
Related errors
- unsupported private key type: %T
- header, body and signature must all be set
- Token is expired
- Session must be of type JWTSessionContainer but got type: %T
- GetTokenClaims() must not be nil
AI-assisted analysis of ory/hydra@4174065ffb (2026-09-03).
Data as JSON: /api/errors/72ebca78c2d99707.
Report an issue: GitHub.