hashicorp/nomad · error

invalid key type: %T

Error message

invalid key type: %T

What it means

keyID was given a public key whose concrete Go type is neither *ecdsa.PublicKey nor *rsa.PublicKey, so the switch falls through to the default and refuses to compute an RFC 5280 Subject Key Identifier. This is a programming error in the caller, not a data-corruption issue.

Solutions

  1. Pass the public key (e.g. signer.Public()) rather than the private key to keyID.
  2. Use an ECDSA (P-256) or RSA private key when generating CAs/certs with this helper.
  3. If you need Ed25519, extend keyID's switch to handle *ed25519.PublicKey.
  4. Verify any custom crypto.Signer implementation's Public() returns *ecdsa.PublicKey or *rsa.PublicKey.

Example fix

// before
signer := ed25519.GenerateKey(rand.Reader)
kid, err := keyID(signer)
// after
ecdsaKey, _ := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
kid, err := keyID(&ecdsaKey.PublicKey)
Defensive patterns

Strategy: type-guard

Validate before calling

func isSupportedSigner(s crypto.Signer) error {
	switch s.Public().(type) {
	case *ecdsa.PublicKey, *rsa.PublicKey:
		return nil
	default:
		return fmt.Errorf("unsupported key type %T; use ECDSA or RSA", s.Public())
	}
}

Type guard

func isSupportedPublicKey(pub interface{}) bool {
	switch pub.(type) {
	case *ecdsa.PublicKey, *rsa.PublicKey:
		return true
	}
	return false
}

Try / catch

if !isSupportedPublicKey(signer.Public()) {
	return fmt.Errorf("cannot compute key ID for %T", signer.Public())
}
kid, err := keyID(signer.Public())
if err != nil { return err }

Prevention

When it happens

Trigger: Calling keyID (directly, or indirectly via GenerateCA/GenerateCert with a custom signer) with an Ed25519 public key, ed25519.PrivateKey passed instead of its Public(), or any other crypto.Signer implementation.

Common situations: Forking or extending the CA code to use Ed25519 or a PKCS#11/HSM-backed signer; accidentally passing a private key rather than signer.Public(); refactoring so the wrong variable is handed to keyID.

Related errors


AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04). Data as JSON: /api/errors/413b905a6046c3f9. Report an issue: GitHub.

Appendix: source

Thrown at helper/tlsutil/generate.go:267

		return "", "", err
	}

	var buf bytes.Buffer
	err = pem.Encode(&buf, &pem.Block{Type: "CERTIFICATE", Bytes: bs})
	if err != nil {
		return "", "", fmt.Errorf("error encoding private key: %s", err)
	}

	return buf.String(), pk, nil
}

// KeyId returns a x509 KeyId from the given signing key.
func keyID(raw interface{}) ([]byte, error) {
	switch raw.(type) {
	case *ecdsa.PublicKey:
	case *rsa.PublicKey:
	default:
		return nil, fmt.Errorf("invalid key type: %T", raw)
	}

	// This is not standard; RFC allows any unique identifier as long as they
	// match in subject/authority chains but suggests specific hashing of DER
	// bytes of public key including DER tags.
	bs, err := x509.MarshalPKIXPublicKey(raw)
	if err != nil {
		return nil, err
	}

	// String formatted
	kID := sha256.Sum256(bs)
	return kID[:], nil
}

// ParseCert parses the x509 certificate from a PEM-encoded value.
func ParseCert(pemValue string) (*x509.Certificate, error) {
	// The _ result below is not an error but the remaining PEM bytes.

View on GitHub (pinned to 482b49bf1a)