kubernetes/kops · info

error decoding SSH public key: %q

Error message

error decoding SSH public key: %q

What it means

This branch is a redundant defensive check: after a successful base64 decode of tokens[1] it re-checks len(tokens) < 2 and reports a decode error. Since tokens[1] was just accessed, len(tokens) >= 2 already holds, so in practice this exact message is unreachable dead code; the reachable decode failure is reported by errorIndex 1582.

Source

Thrown at pkg/pki/sshkey.go:45

	"reflect"
	"strings"

	"golang.org/x/crypto/ssh"
)

// 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])

View on GitHub (pinned to 4c8573c808)

Solutions

  1. No runtime action needed; treat occurrences of this message as the base64-decode failure path (see 'error decoding SSH public key: %q err: %s')
  2. If maintaining the code, remove the redundant len(tokens) < 2 re-check

Example fix

// before
if len(tokens) < 2 {
	return nil, fmt.Errorf("error decoding SSH public key: %q", publicKey)
}
// after
// (remove the redundant check; tokens[1] was already accessed safely)
Defensive patterns

Strategy: try-catch

Try / catch

// Unreachable defensive branch; treat any decode-shaped error via the reachable path:
if _, err := pki.ComputeAWSKeyFingerprint(pubKey); err != nil {
	klog.V(2).Infof("SSH key rejected: %v", err) // covers decode + parse paths
}

Prevention

When it happens

Trigger: Not reachable at runtime: the preceding base64.DecodeString(tokens[1]) guarantees at least two tokens exist.

Common situations: Seen only while reading the source; it appears in audits of sshkey.go as an apparent copy-paste leftover of the earlier token-length check.

Related errors


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