如何通过环境变量传递 ssh 密钥密码

How to pass an ssh key passphrase via environment variable

我在我的应用程序中使用 运行 shell 脚本和 ssh 命令。使用的私钥是通过密码加密的,问题是 - 当 ssh-agent 中未添加 asked.Key 时,我无法交互传递它。我无法执行 ssh-add my_key 因为密码短语应该以交互方式传递。对终端通信有好处,但不适合在应用程序内部使用。

man page 说:

DISPLAY and SSH_ASKPASS

If ssh-add needs a passphrase, it will read the passphrase from the current terminal if it was run from a terminal. If ssh-add does not have a terminal associated with it but DISPLAY and SSH_ASKPASS are set, it will execute the program specified by SSH_ASKPASS and open an X11 window to read the passphrase. This is particularly useful when calling ssh-add from a .xsession or related script. (Note that on some machines it may be necessary to redirect the input from /dev/null to make this work.)

当我执行 SSH_ASKPASS=file_with_passphrase ssh-add my_key 时,我仍然要求输入密码,看起来在这种情况下 env var 被忽略了。我尝试执行 ssh -o BatchMode=yes 并且服务器拒绝了编码密钥,因为没有人能够对其进行解码。

我绝对可以在 ssh-agent 中使用它之前手动解码 ssh 密钥,但看起来我即将从 SSH_ASKPASS 变量中获得我需要的东西,但我不知道如何让它起作用。很高兴获得社区帮助。

所以实际上有一些事情对您尝试做的事情很重要:

  1. 必须设置显示
  2. 它不能有关联的终端
  3. 在某些机器上,可能需要重定向来自 /dev/null 的输入(我的就是其中之一)。
  4. SSH_ASKPASS 必须包含在 stdout.
  5. 上输出密码的可执行文件

举个让它工作的例子(对我来说,我猜也应该在其他 linux 上工作):

创建虚拟密钥:

ssh-keygen -t rsa -C se-so-38354773 -f /tmp/se-so-38354773.key -N 'se-so-38354773-pp'

创建 askpass 脚本以回显密码文件:

cat > /tmp/se-so-38354773-askpass <<EOF
#!/usr/bin/env bash
echo "[=11=]:${@} : this is for debugging to see if the echo script runs" 1>&2
echo "se-so-38354773-pp"
EOF
chmod +x /tmp/se-so-38354773-askpass

我将此文件放在 /tmp/ 中 - 但这对安全性不利,除非您在写入文件之前也更改文件的权限以确保其他人无法读取它(或设置 umask)。

然后你可以按如下方式进行 ssh-add:

DISPLAY=":0.0" SSH_ASKPASS="/tmp/se-so-38354773-askpass" setsid ssh-add /tmp/se-so-38354773.key </dev/null

如果有终端,setsid 会将它与您的终端分离 - 虽然我的计算机不需要 - 但是是的 - 我认为在其他一些情况下可能需要它。

完成测试后进行清理:

ssh-add -d /tmp/se-so-38354773.key
rm /tmp/se-so-38354773*

我电脑上的示例输出:

iwana@iwana-nb.concurrent.co.za:~/projects/gitlab.com/aucampia/stackexchange/Whosebug/38354773
$ ssh-keygen -t rsa -C se-so-38354773 -f /tmp/se-so-38354773.key -N 'se-so-38354773-pp'
Generating public/private rsa key pair.
Your identification has been saved in /tmp/se-so-38354773.key.
Your public key has been saved in /tmp/se-so-38354773.key.pub.
The key fingerprint is:
SHA256:s+jVUPEyb2DzRM5y+Hm3XDzVRREKn5yU2d0hk61hIQ0 se-so-38354773
The key's randomart image is:
+---[RSA 2048]----+
|          .E+=B=O|
|           B*B*o=|
|          X B*o o|
|         o % o ..|
|        S   * ..+|
|       . = . ...+|
|      . o .    o |
|     . .         |
|      .          |
+----[SHA256]-----+
iwana@iwana-nb.concurrent.co.za:~/projects/gitlab.com/aucampia/stackexchange/Whosebug/38354773
$ 
iwana@iwana-nb.concurrent.co.za:~/projects/gitlab.com/aucampia/stackexchange/Whosebug/38354773
$ cat > /tmp/se-so-38354773-askpass <<EOF
> #!/usr/bin/env bash
> echo "[=14=]:${@} : this is for debugging to see if the echo script runs" 1>&2
> echo "se-so-38354773-pp"
> EOF
iwana@iwana-nb.concurrent.co.za:~/projects/gitlab.com/aucampia/stackexchange/Whosebug/38354773
$ chmod +x /tmp/se-so-38354773-askpass
iwana@iwana-nb.concurrent.co.za:~/projects/gitlab.com/aucampia/stackexchange/Whosebug/38354773
$ 
iwana@iwana-nb.concurrent.co.za:~/projects/gitlab.com/aucampia/stackexchange/Whosebug/38354773
$ DISPLAY=":0.0" SSH_ASKPASS="/tmp/se-so-38354773-askpass" setsid ssh-add /tmp/se-so-38354773.key </dev/null
iwana@iwana-nb.concurrent.co.za:~/projects/gitlab.com/aucampia/stackexchange/Whosebug/38354773
$ 
bash: : this is for debugging to see if the echo script runs
Identity added: /tmp/se-so-38354773.key (/tmp/se-so-38354773.key)
iwana@iwana-nb.concurrent.co.za:~/projects/gitlab.com/aucampia/stackexchange/Whosebug/38354773
$ ssh-add -d /tmp/se-so-38354773.key
Identity removed: /tmp/se-so-38354773.key (se-so-38354773)
iwana@iwana-nb.concurrent.co.za:~/projects/gitlab.com/aucampia/stackexchange/Whosebug/38354773
$ rm /tmp/se-so-38354773*

编辑:我正在为这个答案添加更多细节。如果您有带密码的 PEM 编码私钥,您可以先使用 openssl 解密密钥,因为 openssl 将接受标准输入上的密码。

要生成适用于此的新密钥,请使用此命令:

ssh-keygen -t rsa -m pem -b 4096

它不能是 'OPENSSH' 键。看起来像这样的现有密钥的开头应该有效。

-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: AES-128-CBC,8032BCA01FB25FCCD89AFDED8DB52079

然后,您可以使用 openssl 解密密钥,然后再将其发送到 ssh-add。 Openssl 使用 -passin stdin 选项接受 stdin 上的密码短语,默认情况下将输出到 stdout,然后 ssh-add 可以通过添加 - 作为第一个参数来接受 stdin 上未加密的密钥。

echo "$MY_PASSPHRASE" | openssl rsa -in my_encrypted_key -passin stdin | ssh-add -