Mensaje de error
ssh: this private key is passphrase protected
También se muestra como
- ssh: no key found
El mensaje «ssh: no key found» (que figura como alias) es una situación distinta del mismo analizador: los bytes no contienen ningún bloque de clave PEM; por ejemplo, una clave pública, un archivo `.ppk` de PuTTY o un archivo vacío.
golang.org/x/crypto/ssh (Go) — *ssh.PassphraseMissingError from ssh.ParsePrivateKey
Qué significa
`ssh.ParsePrivateKey` reconoció una clave privada cifrada y se detuvo, porque no tiene ninguna frase de contraseña con la que descifrarla. El `*ssh.PassphraseMissingError` devuelto incluso lleva la clave pública, pero para firmar hace falta la clave privada descifrada: llama a `ssh.ParsePrivateKeyWithPassphrase` o deja que un agente SSH se encargue de la firma. Su error hermano «ssh: no key found» significa que la entrada no contiene ninguna clave reconocible.
Por qué ocurre
La clave se creó con una frase de contraseña
frecuente`ssh-keygen` pide una frase de contraseña y cifra con ella el archivo de la clave. OpenSSH en modo interactivo la pide o usa el agente; un programa de Go tiene que proporcionarla explícitamente.
La herramienta daba por hecho que el agente desbloquearía la clave
ocasionalEn una estación de trabajo, `ssh-add` guarda la clave descifrada y `ssh` nunca lee el archivo. El código Go que lee el archivo directamente no se beneficia del agente.
Una clave personal y cifrada copiada en la CI
ocasionalLas claves de despliegue para la automatización suelen ir sin cifrar y con un alcance muy limitado; reutilizar en la CI una clave personal cifrada falla aquí.
Cómo solucionarlo
- 1.
Detectar el error y proporcionar la frase de contraseña
`errors.As` identifica la falta de frase de contraseña; léela de un almacén de secretos, nunca del código fuente.
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.
Firmar a través del agente SSH
Con `golang.org/x/crypto/ssh/agent`, la clave privada nunca entra en tu proceso y el agente se encarga de la frase de contraseña.
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