【问题标题】:Paramiko -- using encrypted private key file on OS XParamiko -- 在 OS X 上使用加密的私钥文件
【发布时间】:2013-03-12 19:51:45
【问题描述】:

我正在尝试使用 Paramiko 从 Python 连接到 SSH 服务器。这是我迄今为止尝试过的:

>>> import paramiko
>>> import os
>>> privatekeyfile = os.path.expanduser('~/.ssh/id_rsa')
>>> mykey = paramiko.RSAKey.from_private_key_file(privatekeyfile)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/paramiko/pkey.py", line 198, in from_private_key_file
    key = cls(filename=filename, password=password)
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/paramiko/rsakey.py", line 51, in __init__
    self._from_private_key_file(filename, password)
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/paramiko/rsakey.py", line 163, in _from_private_key_file
    data = self._read_private_key_file('RSA', filename, password)
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/paramiko/pkey.py", line 280, in _read_private_key_file
    data = self._read_private_key(tag, f, password)
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/paramiko/pkey.py", line 323, in _read_private_key
    raise PasswordRequiredException('Private key file is encrypted')
paramiko.PasswordRequiredException: Private key file is encrypted

如您所见,它失败了,因为我的私钥已加密。但是,密码存储在我的 OS X 登录钥匙串中,当我输入 ssh host 时,它不会询问它(相反,它只询问一次,然后记住它直到下次重新启动)。有没有办法让paramiko 使用密码/从钥匙串中获取密码,就像ssh 一样?

【问题讨论】:

    标签: ssh osx-mountain-lion paramiko private-key


    【解决方案1】:

    在 Paramiko 中使用加密的私钥是不可能的,因为ssh-agent doesn't give private key(没有内存转储)。

    解决方案是使用subprocess 并从中调用 ssh 命令(与任何常用命令一样)。我没有要求解密私钥(它使用 ssh 代理,您可以使用 ssh -vvv 找到它)。

    顺便说一句,我找不到使用 paramiko 的好处。 SSH 代理似乎更发达,更通用的工具。例如,它是 paramiko 中的not possible to forward SSH agent,为此必须求助于子进程。另请注意 2014 年的 this issue,“密钥处理非常糟糕”(开放):

    SSHClient._auth 使用多退出策略并结合存储单个异常以在进程结束时引发。这通常意味着在身份验证时引发的异常对于无法进行身份验证的真正原因是完全不正确的。

    此线程中链接了许多 paramiko 错误。它现在似乎正在积极开发,我希望paramiko 能够解决这个问题,但我的建议是:不要依赖一个单一的库,它可能无法满足您的需求。

    是的,可以为加密密钥提供密码,但这违背了这样做的目的。您要么自己输入密码(然后您不需要 ssh 的密钥),要么将密码存储在磁盘上(当然不在版本控制中),然后您不需要加密私钥(这个想法是如果有人拿到了你的硬盘,就不会得到你的纯文本私钥)。

    【讨论】:

      【解决方案2】:

      以下方法似乎工作正常(在 OS X 上,通常设置加密私钥,密码存储在钥匙串中,无需任何用户交互):

      import paramiko
      
      ssh = paramiko.SSHClient()
      ssh.load_system_host_keys()
      ssh.connect(HOST, username=USER, look_for_keys=False)
      ...
      ssh.close()
      

      看来look_for_keys=False 不是绝对必要的。但是,如果您使用它,您将在身份验证失败的情况下收到更好的错误消息(“AuthenticationException”而不是“PasswordRequiredException”)。


      如果您真的想直接使用私钥,您可以执行以下操作:

      import os
      import paramiko
      import keyring
      
      keyfile = os.path.expanduser('~/.ssh/id_rsa')
      password = keyring.get_password('SSH', keyfile)
      key = paramiko.RSAKey.from_private_key_file(keyfile, password=password)
      

      但是,根据我的测试,这不需要。上面直接使用ssh.connect的解决方案应该足够了。

      【讨论】:

      • 第一种方法出现此错误:没有可用的身份验证方法
      • keyring.get_password('SSH', keyfile) - 不幸的是,这对我在 Gnome 密钥环(Fedora 29)中不起作用。这似乎是不可能的。我列出了 gnome 密钥环标签,但没有 SSH,并且相应的标签不适用于 keyring
      • 顺便说一句,无法从 ssh-agent 获取私钥(没有内存转储)。 stackoverflow.com/a/2976729/952234.
      • 你如何处理key 对象?
      【解决方案3】:

      RSAKey.from_private_key_file() 继承自 PKey();此方法的可选参数是密码。引用:

      如果私钥被加密并且密码不是None,给定的 密码将用于解密密钥(否则 抛出 PasswordRequiredException)。

      由于您没有传递密码并且您的密钥已加密,因此将始终抛出此异常。解决这个问题只有一种方法,实际上是给方法一个密码。因此,您需要一种从 OSXKeychain 中获取密码的方法。

      您可以使用跨平台的Keyring 模块来执行此操作。

      【讨论】:

      • 我最终只是创建了一个没有密码的新密钥对并使用它,但接受了这个,因为这可能会起作用
      • 面对这种情况@houbysoft,这是我自己的解决方案......它只是没有回答问题:-)。
      • 那么,密码被用作密码短语解密了吗?因为我刚刚尝试过,但没有成功!
      • 无法从 ssh-agent 获取私钥(没有内存转储)。 stackoverflow.com/a/2976729/952234
      猜你喜欢
      • 1970-01-01
      • 2017-01-04
      • 2018-01-31
      • 2021-02-17
      • 2012-04-11
      • 2017-01-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多