我正在通过 SSH 密钥使用
paramiko.SSHClient
向远程服务器进行身份验证。为此,我有几个针对不同服务器的配置以及 SSH 密钥的路径。碰巧其中一些是 Ed25519,一些是 RSA。仅使用密码连接不是可接受的选择。
一开始我想用下面的代码连接:
keyfilename = build_configuration['sshPrivateKeypath']
keyfilename = os.path.expandvars(keyfilename)
key = paramiko.Ed25519Key.from_private_key_file(keyfilename)
ssh.connect(ssh_host, port=port, username=ssh_user, pkey=key)
但事实证明,有些密钥是 RSA(不是 Ed25519)。
有没有办法在不使用具体实现的情况下读取任何类型的 SSH 密钥?或者也许有某种方法可以确定类型? 或者唯一的方法是将所有键更改为已知类型?
无法从文档
中计算出来在测试真实配置之前,我尝试从 Jupyter 读取本地 PC 上的 SSH 密钥。 当读错这样的类型时:
keyfilename = "%USERPROFILE%/.ssh/id_rsa"
keyfilename = os.path.expandvars(keyfilename)
privateKey = paramiko.Ed25519Key.from_private_key_file(keyfilename)
它抛出:
---------------------------------------------------------------------------
SSHException Traceback (most recent call last)
Cell In[2], line 6
4 keyfilename = "%USERPROFILE%/.ssh/id_rsa"
5 keyfilename = os.path.expandvars(keyfilename)
----> 6 privateKey = paramiko.Ed25519Key.from_private_key_file(keyfilename)
7 display(key)
8 display(privateKey)
File ~\AppData\Local\Programs\Python\Python311\Lib\site-packages\paramiko\pkey.py:421, in PKey.from_private_key_file(cls, filename, password)
400 @classmethod
401 def from_private_key_file(cls, filename, password=None):
402 """
403 Create a key object by reading a private key file. If the private
404 key is encrypted and ``password`` is not ``None``, the given password
(...)
419 :raises: `.SSHException` -- if the key file is invalid
420 """
--> 421 key = cls(filename=filename, password=password)
422 return key
File ~\AppData\Local\Programs\Python\Python311\Lib\site-packages\paramiko\ed25519key.py:65, in Ed25519Key.__init__(self, msg, data, filename, password, file_obj)
62 pkformat, data = self._read_private_key("OPENSSH", file_obj)
64 if filename or file_obj:
---> 65 signing_key = self._parse_signing_key_data(data, password)
67 if signing_key is None and verifying_key is None:
68 raise ValueError("need a key")
File ~\AppData\Local\Programs\Python\Python311\Lib\site-packages\paramiko\ed25519key.py:114, in Ed25519Key._parse_signing_key_data(self, data, password)
112 pubkey = Message(message.get_binary())
113 if pubkey.get_text() != self.name:
--> 114 raise SSHException("Invalid key")
115 public_keys.append(pubkey.get_binary())
117 private_ciphertext = message.get_binary()
SSHException: Invalid key
所以我希望当我使用真实配置尝试时它会抛出同样的结果。
最简单的方法是使用
key_filename
的
SSHClient.connect
参数代替 pkey
。
如果您出于某种原因想要使用
pkey
,则在处理 SSHClient
时,您必须在内部复制 key_filename
的功能。大致是这样的(未经测试):
for pkey_class in (RSAKey, DSSKey, ECDSAKey, Ed25519Key):
try:
key = pkey_class.from_private_key_file(key_filename)
break
except SSHException as e:
pass