caddyserver/caddy · error

unsupported key type: %T

Error message

unsupported key type: %T

What it means

Returned by verifyKeysMatch (modules/caddypki/crypto.go:154) when the public key embedded in the certificate being loaded is not RSA, ECDSA, or Ed25519. Caddy's PKI only knows how to verify these three key families, so any other algorithm in the cert's SubjectPublicKeyInfo fails here at the default switch case.

Source

Thrown at modules/caddypki/crypto.go:154

		}
	case *ecdsa.PublicKey:
		pk, ok := signer.Public().(*ecdsa.PublicKey)
		if !ok {
			return fmt.Errorf("private key type %T does not match issuer public key type %T", signer.Public(), pub)
		}
		if !pub.Equal(pk) {
			return errors.New("private key does not match issuer public key")
		}
	case ed25519.PublicKey:
		pk, ok := signer.Public().(ed25519.PublicKey)
		if !ok {
			return fmt.Errorf("private key type %T does not match issuer public key type %T", signer.Public(), pub)
		}
		if !pub.Equal(pk) {
			return errors.New("private key does not match issuer public key")
		}
	default:
		return fmt.Errorf("unsupported key type: %T", pub)
	}

	return nil
}

View on GitHub (pinned to 50e54ee279)

Solutions

  1. Re-issue the CA certificate with a supported key algorithm: RSA (>=2048), ECDSA (P-256/P-384/P-521), or Ed25519
  2. Check the algorithm before importing: openssl x509 -in cert.pem -noout -text | grep 'Public Key Algorithm'
  3. If you must keep the external CA, terminate its certificates in the TLS app instead of loading it as a Caddy PKI root/intermediate

Example fix

# before: DSA root
openssl dsaparam -genkey 2048 > d.key && openssl req -x509 -new -key d.key ...

# after: ECDSA root
openssl ecparam -name prime256v1 -genkey -noout -out key.pem
openssl req -x509 -new -key key.pem -subj '/CN=My Root' -days 3650 -out root.crt
Defensive patterns

Strategy: validation

Validate before calling

// reject unsupported algorithms before handing certs to Caddy
func isSupportedCertAlgorithm(certFile string) (bool, error) {
	out, err := exec.Command("openssl", "x509", "-in", certFile, "-noout", "-text").Output()
	if err != nil {
		return false, err
	}
	txt := string(out)
	return strings.Contains(txt, "rsaEncryption") ||
		strings.Contains(txt, "id-ecPublicKey") ||
		strings.Contains(txt, "ED25519"), nil
}

Type guard

// Go-side guard using the parsed certificate
func certUsesSupportedKey(crt *x509.Certificate) bool {
	switch crt.PublicKey.(type) {
	case *rsa.PublicKey, *ecdsa.PublicKey, ed25519.PublicKey:
		return true
	}
	return false
}

Try / catch

if err := ca.Provision(ctx, caID, p.log); err != nil {
    if strings.Contains(err.Error(), "unsupported key type") {
        // algorithm-level problem: re-issue the CA cert with RSA/ECDSA/Ed25519
    }
    return err
}

Prevention

When it happens

Trigger: Supplying a CA root or intermediate certificate whose public key uses an unsupported algorithm (e.g. DSA, Ed448, or an ECDH-typed key) via the root/intermediate cert_file/key_file config. The error fires during provisioning when the chain is read and verifyKeysMatch is called with the loaded certificate and signer.

Common situations: Importing certificates from legacy or exotic CAs that still use DSA; keys generated by experimental tooling (Ed448, Dilithium/PQC pilots); OpenSSL-generated ECDH keys mistakenly used where an ECDSA signing key was required.

Related errors


AI-assisted analysis of caddyserver/caddy@50e54ee279 (2026-08-15). Data as JSON: /api/errors/6e1c7def5b666e44. Report an issue: GitHub.