ginuerzh/gost · error

unknown public key for %q

Error message

unknown public key for %q

What it means

Raised by the SSH server's public key authentication callback: the client presented a public key that is not in the server's authorized key set, so the callback returns 'unknown public key for "<user>"' and the handshake fails. The Extensions map ('pubkey-fp') shows that valid keys are recorded with a SHA256 fingerprint on success.

Source

Thrown at ssh.go:897

// PublicKeyCallbackFunc is a callback function used by SSH server.
// It offers a public key for authentication.
type PublicKeyCallbackFunc func(c ssh.ConnMetadata, pubKey ssh.PublicKey) (*ssh.Permissions, error)

func defaultSSHPublicKeyCallback(keys map[string]bool) PublicKeyCallbackFunc {
	if len(keys) == 0 {
		return nil
	}

	return func(c ssh.ConnMetadata, pubKey ssh.PublicKey) (*ssh.Permissions, error) {
		if keys[string(pubKey.Marshal())] {
			return &ssh.Permissions{
				// Record the public key used for authentication.
				Extensions: map[string]string{
					"pubkey-fp": ssh.FingerprintSHA256(pubKey),
				},
			}, nil
		}
		return nil, fmt.Errorf("unknown public key for %q", c.User())
	}
}

type sshNopConn struct {
	session *sshSession
}

func (c *sshNopConn) Read(b []byte) (n int, err error) {
	return 0, &net.OpError{Op: "read", Net: "ssh", Source: nil, Addr: nil, Err: errors.New("read not supported")}
}

func (c *sshNopConn) Write(b []byte) (n int, err error) {
	return 0, &net.OpError{Op: "write", Net: "ssh", Source: nil, Addr: nil, Err: errors.New("write not supported")}
}

func (c *sshNopConn) Close() error {
	return nil
}

View on GitHub (pinned to a33fdbf4c9)

Solutions

  1. Add the client's public key (check its SHA256 fingerprint against server logs/config) to the server's authorized key set
  2. Verify the authenticator is pointed at the intended authorized-keys source
  3. Regenerate or copy the correct client keypair and retry
  4. Confirm the client offers the expected key (ssh -v or client logs) rather than a different default key

Example fix

// before: server only knows old-key.pub
authorizedKeys := []ssh.PublicKey{oldKey}
// after: add the client's new key
authorizedKeys := append(authorizedKeys, newClientPubKey)
Defensive patterns

Strategy: validation

Validate before calling

// before connecting, confirm the client key is authorized
fp := fingerprintSHA256(pubKeyBytes) // compute locally
if !allowedFingerprints[fp] {
    return fmt.Errorf("key %s is not in server authorized keys", fp)
}

Try / catch

client, err := ssh.Dial("tcp", addr, &ssh.ClientConfig{
    Auth: []ssh.AuthMethod{ssh.PublicKeys(signer)},
})
if err != nil {
    if strings.Contains(err.Error(), "unknown public key") {
        return fmt.Errorf("install the client public key on the server: %w", err)
    }
    return err
}

Prevention

When it happens

Trigger: An SSH client authenticates with a public key whose fingerprint does not match any key configured in the server's authenticator (au), causing the final return of fmt.Errorf("unknown public key for %q", c.User()).

Common situations: Client using a new/rotated key not yet added to the server's authorized keys; pointing the server at the wrong authorized-keys file; key format mismatch; testing with a throwaway keypair.

Related errors


AI-assisted analysis of ginuerzh/gost@a33fdbf4c9 (2026-09-02). Data as JSON: /api/errors/bda2295cd29eba99. Report an issue: GitHub.