如何使用 ssh-ed25519 设置主机密钥文件作为 pysftp 的密钥

How to set up a hostkey file using ssh-ed25519 as a key for pysftp

我正在尝试使用 pysftp 在我的 Python 脚本中连接到 SFTP 站点。

因为我没有主机密钥文件,我已经按照建议创建了一个 here、"hostkey",我正在尝试加载这个文件,但是 pysftp没有连接到 sftp 站点。

python代码很简单:

cnopts = pysftp.CnOpts()
cnopts.hostkeys.load(pathToTheFile)
with pysftp.Connection(host, username=username, private_key=pathToPKey, cnopts=cnopts) as sftp:
    #do things

我首先尝试在主机密钥文件中添加以下内容:

host.com ssh-ed25519 256 AZFsh0........Qy0=

但这会导致 InvalidHostKey 错误和 Incorrect padding 错误。我猜它不需要 256 作为密钥。所以,我删除了 256。

当我尝试不使用 256 时:

host.com ssh-ed25519 256 AZFsh0........Qy0=

然后它识别出密钥,但出现'utf-8' codec can't decode byte 0x90 in position 11: invalid start byte错误。

因此,我没有加载主机密钥文件,而是尝试使用 here 中建议的以下代码添加主机密钥:

keydata = b"""AZFsh0........Qy0="""
key1 = paramiko.ed25519key.Ed25519Key(data=keydata)
key2 = paramiko.ed25519key.Ed25519Key(data=base64.b64decode(keydata))
key3 = paramiko.ed25519key.Ed25519Key(data=base64.b64decode(keydata).hex())
key4 = paramiko.ed25519key.Ed25519Key(data=decodebytes(keydata))
key5 = paramiko.ed25519key.Ed25519Key(data=decodebytes(keydata).hex())
cnopts.hostkeys.add("host.com", "ssh-ed25519", key1) 

我尝试了以上所有键,但仍然出现 Incorrect padding

等错误

我看到有人提到 this may be a bug 但 post 是 2018 年的。 有谁知道这是不可行的还是我遗漏了什么?

编辑(有效)

, which was linked in the link in Martin Prikryl 的回复中 post 的解决方案有效。

这是我使用的(我清理了一些以删除未使用的功能)。

import hashlib as hl

#Removed trim_fingerprint() and clean_fingerprint() because it wasn't necessary in my case
class FingerprintKey:
    def __init__(self, fingerprint):
        self.fingerprint = fingerprint
    def compare(self, other):
        if callable(getattr(other, "get_fingerprint", None)):
            return other.get_fingerprint() == self.fingerprint
        elif other == self.get_fingerprint():
            return True
        elif hl.md5(other).hexdigest() == self.fingerprint:
            return True
        else:
            return False
    def __cmp__(self, other):
        return self.compare(other)
    def __contains__(self, other):
        return self.compare(other)
    def __eq__(self, other):
        return self.compare(other)
    def __ne__(self, other):
        return not self.compare(other)
    def get_fingerprint(self):
        return self.fingerprint
    def get_name(self):
        return u'ssh-ed25519' # Including "256" errors out. 
    def asbytes(self):
        return self

并且是这样使用的:

cnopts = pysftp.CnOpts()
cnopts.hostkeys.add('host.com', u'ssh-ed25519 256', FingerprintKey("e2d1............c957")) # Removed ":" from the MD5 value

我遇到的主要问题是我不确定应该为 cnopts.hostkeys.add 插入什么值,等等,所以我会把这些细节放在一起,以防有人对此不熟悉.

就我而言,我使用 WinSCP 获取主机密钥指纹。

  1. 打开 WinSCP
  2. 输入主机名、用户名,并指定要连接的私钥路径
  3. 点击会话
  4. 点击Server/Protocol信息
  5. 使用Algorithm中的值作为cnopts.hostkeys.add
  6. 的第二个参数(keytype)
  7. cnopts.hostkeys.add的第三个参数(key)使用MD5中的值。实际值带有冒号(例如 e2:d1:......c9:57),但正如 的作者提到的,我也必须手动删除冒号。

进入 “主机密钥文件” 的是完整的 host/public 密钥,而不仅仅是指纹。

详见(再次):
Verify host key with pysftp

如果您只想使用指纹验证主机密钥,请参阅:

(尽管那已经在第一个答案中链接了)。