gravitational/teleport · error

invalid public key

Error message

invalid public key

What it means

validateCertificateOverride rejects the override's public_key when it does not match the expected PEM public key format (certificateOverridePublicKeyRE) or when an accompanying certificate is present whose public key hash differs from the supplied public_key. This guards subCA overrides against malformed or mismatched key material.

Source

Thrown at lib/subca/parsed.go:246

	// Certificate.
	var cert *x509.Certificate
	var wantPublicKey string
	if co.GetCertificate() != "" {
		var err error
		cert, err = ParseCertificateOverrideCertificate(co.GetCertificate())
		if err != nil {
			return nil, "certificate", err
		}
		if err := validateOverrideCertificate(clusterName, cert); err != nil {
			return nil, "certificate", err
		}
		wantPublicKey = HashCertificatePublicKey(cert)
	}

	// PublicKey.
	if co.GetPublicKey() != "" {
		if !certificateOverridePublicKeyRE.MatchString(co.GetPublicKey()) {
			return nil, "", errors.New("invalid public key")
		}
		if wantPublicKey != "" && NormalizePublicKey(co.GetPublicKey()) != wantPublicKey {
			return nil, "public_key", fmt.Errorf("certificate public key mismatch (want %q)", wantPublicKey)
		}
	}

	// Validate "required" fields now that we know both Certificate and PublicKey
	// are valid.
	switch {
	case co.GetDisabled() && co.GetPublicKey() == "" && co.GetCertificate() == "":
		return nil, "", errors.New("certificate or public key required")
	case co.GetDisabled():
		// OK, determined above to have either PublicKey or Certificate.
	case co.GetCertificate() == "":
		return nil, "", errors.New("certificate required")
	}

	// Chain.

View on GitHub (pinned to 1283425b60)

Solutions

  1. Provide the public key as a valid PEM-encoded PUBLIC KEY block
  2. If both certificate and public_key are set, ensure the public key matches the certificate's key (or omit public_key and let it be derived from the certificate)
  3. Regenerate/extract the key with openssl: openssl x509 -in cert.pem -pubkey -noout

Example fix

// before: mismatched public_key + certificate
override:
  certificate: <cert A>
  public_key: <key from cert B>
// after: derive from certificate
override:
  certificate: <cert A>
Defensive patterns

Strategy: validation

Validate before calling

pub, ok := normalizePublicKeyPEM(override.GetPublicKey())
if !ok { return trace.BadParameter("public_key must be PEM-encoded PUBLIC KEY") }
if override.GetCertificate() != "" {
    cert := parseCert(t, override.GetCertificate())
    if normalize(pub) != hashCertPub(cert) {
        return trace.BadParameter("public_key does not match certificate")
    }
}

Type guard

func publicKeyMatchesCert(certPEM, pubPEM string) bool {
    cert, err := subca.ParseCertificatePEM(certPEM); if err != nil { return false }
    return subca.NormalizePublicKey(pubPEM) == subca.HashCertificatePublicKey(cert)
}

Try / catch

_, field, err := ValidateAndParseCAOverride(clusterName, co)
if field == "public_key" {
    return trace.BadParameter("override public_key invalid or does not match certificate")
}

Prevention

When it happens

Trigger: Providing co.PublicKey that is not a valid PEM public key string, or providing both certificate and public_key where NormalizePublicKey(public_key) != HashCertificatePublicKey(cert).

Common situations: Copy-pasting a public key with wrong PEM headers/extra whitespace; supplying a public_key from a different certificate than the override's certificate; pasting a private key or certificate where a public key is expected.

Related errors


AI-assisted analysis of gravitational/teleport@1283425b60 (2026-09-02). Data as JSON: /api/errors/cc32d0671147ef92. Report an issue: GitHub.