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

时间:2020-01-30 02:09:31

标签: python ssh sftp ssh-keys pysftp

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

由于我没有主机密钥文件,因此按照建议的here创建了一个主机密钥,并且我正在尝试加载该文件,但是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来获取主机密钥指纹。

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

1 个答案:

答案 0 :(得分:0)

“主机密钥文件” 的内容是完整的主机/公共密钥,不仅是指纹。

有关详细信息,请参见(再次):
Verify host key with pysftp

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