{"record":{"id":"40e66fdef8928d08","repo":"hashicorp/terraform","slug":"failed-to-read-ssh-private-key-password-protected","errorCode":null,"errorMessage":"Failed to read ssh private key: password protected keys are\nnot supported. Please decrypt the key prior to use.","messagePattern":"Failed to read ssh private key: password protected keys are\nnot supported\\. Please decrypt the key prior to use\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/communicator/ssh/provisioner.go","lineNumber":429,"sourceCode":"\t}\n\n\tucertSigner, err := ssh.NewCertSigner(pcert.(*ssh.Certificate), usigner)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to create cert signer %q: %s\", usigner, err)\n\t}\n\n\treturn ssh.PublicKeys(ucertSigner), nil\n}\n\nfunc readPrivateKey(pk string) (ssh.AuthMethod, error) {\n\t// We parse the private key on our own first so that we can\n\t// show a nicer error if the private key has a password.\n\tblock, _ := pem.Decode([]byte(pk))\n\tif block == nil {\n\t\treturn nil, errors.New(\"Failed to read ssh private key: no key found\")\n\t}\n\tif block.Headers[\"Proc-Type\"] == \"4,ENCRYPTED\" {\n\t\treturn nil, errors.New(\n\t\t\t\"Failed to read ssh private key: password protected keys are\\n\" +\n\t\t\t\t\"not supported. Please decrypt the key prior to use.\")\n\t}\n\n\tsigner, err := ssh.ParsePrivateKey([]byte(pk))\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"Failed to parse ssh private key: %s\", err)\n\t}\n\n\treturn ssh.PublicKeys(signer), nil\n}\n\nfunc connectToAgent(connInfo *connectionInfo) (*sshAgent, error) {\n\tif !connInfo.Agent {\n\t\t// No agent configured\n\t\treturn nil, nil\n\t}\n","sourceCodeStart":411,"sourceCodeEnd":447,"githubUrl":"https://github.com/hashicorp/terraform/blob/d32a084675427f5ac3f7d2868578ef8b2c1dc525/internal/communicator/ssh/provisioner.go#L411-L447","documentation":"Returned by `readPrivateKey` when the PEM block carries the legacy `Proc-Type: 4,ENCRYPTED` header, indicating the private key is passphrase-protected. Terraform's SSH auth does not support decrypting password-protected keys, so it refuses up front with this guidance to decrypt the key first.","triggerScenarios":"`pem.Decode` succeeds but `block.Headers[\"Proc-Type\"] == \"4,ENCRYPTED\"` — the supplied key was generated with a passphrase (e.g. `ssh-keygen -N 'secret' ...` in older PEM format, or a converted OpenSSL key with `-aes256`).","commonSituations":"Reusing a personal passphrase-protected key for a provisioner; older RSA keys in traditional PEM format that carry DEK-Info/Proc-Type encryption headers.","solutions":["Generate a new key without a passphrase: `ssh-keygen -t ed25519 -N '' -f deploy_key`.","Decrypt the existing key: `ssh-keygen -p -f id_rsa` (enter old passphrase, leave new empty) or `openssl rsa -in encrypted.key -out plain.key`.","Store the unencrypted key securely (secret manager) and reference it; never commit it."],"exampleFix":"# decrypt an existing encrypted key before use\n# ssh-keygen -p -f ~/.ssh/id_rsa   # remove passphrase\n# then:\nconnection { type = \"ssh\" private_key = file(\"~/.ssh/id_rsa\") }","handlingStrategy":"validation","validationCode":"// Reject encrypted PEM keys before attempting to use them:\nblock, _ := pem.Decode([]byte(key))\nif block != nil && block.Headers[\"Proc-Type\"] == \"4,ENCRYPTED\" {\n    return errors.New(\"private_key is passphrase-protected; decrypt it first\")\n}","typeGuard":"// isEncryptedPEM reports whether a PEM private key is passphrase-protected.\nfunc isEncryptedPEM(key string) bool {\n    block, _ := pem.Decode([]byte(key))\n    return block != nil && block.Headers[\"Proc-Type\"] == \"4,ENCRYPTED\"\n}","tryCatchPattern":"if _, err := readPrivateKey(privateKey); err != nil {\n    if strings.Contains(err.Error(), \"password protected keys\") {\n        return errors.New(\"decrypt the ssh key (ssh-keygen -p) before use\")\n    }\n    return err\n}","preventionTips":["Generate deployment keys without a passphrase: `ssh-keygen -N ''`.","Store unencrypted keys in a secrets manager, never in source control.","Document that passphrase-protected keys are unsupported by the SSH provisioner."],"tags":["ssh","private-key","encrypted-key","passphrase","connection","provisioner"],"backgroundTag":null,"analyzedSha":"d32a084675427f5ac3f7d2868578ef8b2c1dc525","analyzedAt":"2026-08-11T18:43:52.779Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}