kubernetes/kops · error

error parsing SSH public key: %v

Error message

error parsing SSH public key: %v

What it means

After decoding, the blob is handed to golang.org/x/crypto/ssh.ParsePublicKey; if the SSH wire-format structure is invalid (bad key type string, wrong field counts, malformed mpints, failed signature/geometry checks) the error is wrapped as 'error parsing SSH public key: %v'.

Source

Thrown at pkg/pki/sshkey.go:50

// parseSSHPublicKey parses the SSH public key string
func parseSSHPublicKey(publicKey string) (ssh.PublicKey, error) {
	tokens := strings.Fields(publicKey)
	if len(tokens) < 2 {
		return nil, fmt.Errorf("error parsing SSH public key: %q", publicKey)
	}

	sshPublicKeyBytes, err := base64.StdEncoding.DecodeString(tokens[1])
	if err != nil {
		return nil, fmt.Errorf("error decoding SSH public key: %q err: %s", publicKey, err)
	}
	if len(tokens) < 2 {
		return nil, fmt.Errorf("error decoding SSH public key: %q", publicKey)
	}

	sshPublicKey, err := ssh.ParsePublicKey(sshPublicKeyBytes)
	if err != nil {
		return nil, fmt.Errorf("error parsing SSH public key: %v", err)
	}
	return sshPublicKey, nil
}

// colonSeparatedHex formats the byte slice SSH-fingerprint style: hex bytes separated by colons
func colonSeparatedHex(data []byte) string {
	sshKeyFingerprint := fmt.Sprintf("%x", data)
	var colonSeparated bytes.Buffer
	for i := 0; i < len(sshKeyFingerprint); i++ {
		if (i%2) == 0 && i != 0 {
			colonSeparated.WriteByte(':')
		}
		colonSeparated.WriteByte(sshKeyFingerprint[i])
	}

	return colonSeparated.String()
}

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Regenerate or re-export the public key with `ssh-keygen` and verify `ssh-keygen -l -f id_rsa.pub` succeeds
  2. Ensure the full single line (type + blob + optional comment) is preserved without internal line breaks
  3. If using an SSH certificate, extract the underlying public key first
Defensive patterns

Strategy: validation

Validate before calling

func validateSSHPubKey(s string) error {
	f := strings.Fields(s)
	if len(f) < 2 {
		return fmt.Errorf("missing type/blob fields")
	}
	b, err := base64.StdEncoding.DecodeString(f[1])
	if err != nil {
		return fmt.Errorf("bad base64: %w", err)
	}
	if _, err := ssh.ParsePublicKey(b); err != nil {
		return fmt.Errorf("bad SSH wire format: %w", err)
	}
	return nil
}
if err := validateSSHPubKey(pubKey); err != nil {
	return err
}
fp, err := pki.ComputeOpenSSHKeyFingerprint(pubKey)

Type guard

func isPlainKeyNotCert(pubKey string) bool {
	return !strings.Contains(pubKey, "-cert-v01@openssh.com")
}

Try / catch

fp, err := pki.ComputeOpenSSHKeyFingerprint(pubKey)
var parseErr *ssh.PassphraseMissingError // example narrowing if using ssh lib directly
if err != nil {
	return fmt.Errorf("cannot fingerprint key: %w", err)
}

Prevention

When it happens

Trigger: The base64 blob decodes but is not a well-formed SSH public key: random base64 data, an SSH certificate where a plain key is required, a wire blob from a different key format, or a corrupted/truncated key file.

Common situations: Keys mangled by editors (line wrapping inserted into the blob), users generating keys with exotic formats, or passing an ssh-ed25519 certificate (ssh-ed25519-cert-v01@openssh.com) to fingerprinting code expecting a plain key.

Related errors


AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05). Data as JSON: /api/errors/f1e98b18f6d68ef7. Report an issue: GitHub.