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

Posted

技术标签:

【中文标题】如何使用 ssh-ed25519 作为 pysftp 的密钥来设置主机密钥文件【英文标题】:How to set up a hostkey file using ssh-ed25519 as a key for pysftp 【发布时间】:2020-05-15 14:32:06 【问题描述】:

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

由于我没有 hostkey 文件,所以我按照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,但该帖子来自 2018 年。 有谁知道这是不可行的还是我遗漏了什么?

编辑(这工作)

Connection to an SFTP server using pysftp and Python 3 with just the server fingerprint 中发布的解决方案在Martin Prikryl 的回复中的链接中链接有效。

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

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 来获取主机密钥指纹。

    打开 WinSCP 输入主机名、用户名,并指定要连接的私钥路径 点击会话 点击服务器/协议信息 使用算法中的值作为cnopts.hostkeys.add的第二个参数(keytype) 使用 MD5 中的值作为cnopts.hostkeys.add 的第三个参数 (key)。实际值带有冒号(例如 e2:d1:......c9:57),但正如 Connection to an SFTP server using pysftp and Python 3 with just the server fingerprint 的作者所提到的,我也必须手动删除冒号。

【问题讨论】:

【参考方案1】:

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

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

如果您只想使用指纹验证主机密钥,请参阅:Python - pysftp / paramiko - Verify host key using its fingerprint (尽管这已经在第一个答案中链接了)。

【讨论】:

以上是关于如何使用 ssh-ed25519 作为 pysftp 的密钥来设置主机密钥文件的主要内容,如果未能解决你的问题,请参考以下文章

如何以通过 ed25519 识别的用户身份使用 MYSQL Workbench 连接到 MariaDB (10.5.8)?

ssh 登录我的 EC2 实例时使用哪个密钥?

如何使用python将ed25519算法实现到jwt中?

如何使用 Bouncy Castle 创建与 OpenSSH 兼容的 ED25519 密钥?

lib25519:用于X25519加密系统和Ed25519签名系统的密码学库

PHPMyAdmin 和 ed25519