Fehlermeldung
ssh: this private key is passphrase protected
Auch ausgegeben als
- ssh: no key found
„ssh: no key found“ (als Alias aufgeführt) ist ein anderer Fehlerfall desselben Parsers: Die Bytes enthalten keinen PEM-Schlüsselblock – zum Beispiel bei einem öffentlichen Schlüssel, einer `.ppk`-Datei von PuTTY oder einer leeren Datei.
golang.org/x/crypto/ssh (Go) — *ssh.PassphraseMissingError from ssh.ParsePrivateKey
Was der Fehler bedeutet
`ssh.ParsePrivateKey` hat einen verschlüsselten privaten Schlüssel erkannt und abgebrochen, weil es keine Passphrase hat, um ihn zu entschlüsseln. Der zurückgegebene `*ssh.PassphraseMissingError` enthält sogar den öffentlichen Schlüssel, aber zum Signieren braucht es den entschlüsselten privaten Schlüssel: Rufe `ssh.ParsePrivateKeyWithPassphrase` auf oder lass einen SSH-Agenten signieren. Der verwandte Fehler „ssh: no key found“ bedeutet, dass die Eingabe überhaupt keinen erkennbaren Schlüssel enthält.
Warum der Fehler auftritt
Der Schlüssel wurde mit einer Passphrase erstellt
häufig`ssh-keygen` fragt nach einer Passphrase und verschlüsselt die Schlüsseldatei damit. Das interaktive OpenSSH fragt sie ab oder nutzt den Agenten; ein Go-Programm muss sie explizit übergeben.
Das Tool hat sich darauf verlassen, dass der Agent den Schlüssel entsperrt
gelegentlichAuf einem Arbeitsplatzrechner hält `ssh-add` den entschlüsselten Schlüssel bereit, und `ssh` liest die Datei nie. Go-Code, der die Datei direkt liest, profitiert nicht vom Agenten.
Ein persönlicher, verschlüsselter Schlüssel wurde in die CI kopiert
gelegentlichDeploy-Keys für Automatisierung sind meist unverschlüsselt und haben eng begrenzte Rechte; wer einen persönlichen verschlüsselten Schlüssel in der CI wiederverwendet, scheitert hier.
So behebst du den Fehler
- 1.
Fehler erkennen und Passphrase übergeben
`errors.As` erkennt die fehlende Passphrase; lies sie aus einem Secret Store, nie aus dem Quellcode.
go signer, err := ssh.ParsePrivateKey(keyBytes) var missing *ssh.PassphraseMissingError if errors.As(err, &missing) { passphrase := []byte(os.Getenv("SSH_KEY_PASSPHRASE")) signer, err = ssh.ParsePrivateKeyWithPassphrase(keyBytes, passphrase) } if err != nil { return err } - 2.
Über den SSH-Agenten signieren
Mit `golang.org/x/crypto/ssh/agent` gelangt der private Schlüssel nie in deinen Prozess, und um die Passphrase kümmert sich der Agent.
go import "golang.org/x/crypto/ssh/agent" conn, err := net.Dial("unix", os.Getenv("SSH_AUTH_SOCK")) if err != nil { return err } agentClient := agent.NewClient(conn) auth := ssh.PublicKeysCallback(agentClient.Signers) // the agent holds the decrypted key