使用 pysftp 和 Python 3 仅使用服务器指纹连接到 SFTP 服务器
Connecting to an SFTP server using pysftp and Python 3 with just the server fingerprint
我遇到了一种奇怪的情况,我需要第一次连接到 SFTP 服务器,但我似乎无法找到一种方法来访问 [=24] 的已知主机条目=] 如果我说:
可以正常连接
import pysftp
cnopts = pysftp.CnOpts()
cnopts.hostkeys = None
with pysftp.Connection('host', username='me', password='pass', cnopts=cnopts):
但显然这会让你在中间攻击中受到攻击。所以我尝试连接:
cnopts = pysftp.CnOpts(knownhosts='config/known_host')
cnopts.hostkeys = None
with pysftp.Connection(host, username=username, password=password, cnopts=cnopts) as sftp:
而且我收到了各种各样的错误消息。最近的一个是:
paramiko.hostkeys.InvalidHostKey
问题是我没有主机密钥,因为我是第一次连接。我试图从其他连接中获取密钥。我使用 WinSCP,但它将密钥存储在注册表文件中,格式与 known_host 不同。我尝试使用 ssh-keyscan 通过 PuTTY 获取它,但服务器甚至不允许我启动终端会话。我们不拥有这个盒子,托管服务提供商也不太可能提供我们需要的东西。
我运气不好吗?我应该继续绕过检查密钥吗?
解决方案可以在 找到,但我不得不稍微修改一下才能使用 Python 3.
import hashlib as hl
def trim_fingerprint(fingerprint):
#if fingerprint.startswith('ecdsa-sha2-nistp384 384 '):
#return fingerprint[len('ecdsa-sha2-nistp384 384 '):]
return fingerprint
def clean_fingerprint(fingerprint):
#return trim_fingerprint(fingerprint).replace(':', '')
return trim_fingerprint(fingerprint)
class FingerprintKey:
def __init__(self, fingerprint):
self.fingerprint = clean_fingerprint(fingerprint)
def compare(self, other):
if callable(getattr(other, "get_fingerprint", None)):
return other.get_fingerprint() == self.fingerprint
elif clean_fingerprint(other) == self.get_fingerprint():
return True
#elif hl.md5(other).digest().encode('hex') == self.fingerprint:
#The line below is required for Python 3. Above is Python 2.
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'ecdsa-sha2-nistp384'
def asbytes(self):
# Note: This returns itself.
# That way when comparisons are done to asbytes return value,
# this class can handle the comparison.
return self
我不得不从指纹中手动删除任何“:”,因为它根本无法让脚本执行此操作。
用法:
options = pysftp.CnOpts()
options.hostkeys.clear()
options.hostkeys.add('www.sample.com', u'ecdsa-sha2-nistp384 384 ', AuthOnFingerPrint.FingerprintKey(serverkey))
其中serverkey是指纹。
我遇到了一种奇怪的情况,我需要第一次连接到 SFTP 服务器,但我似乎无法找到一种方法来访问 [=24] 的已知主机条目=] 如果我说:
可以正常连接import pysftp
cnopts = pysftp.CnOpts()
cnopts.hostkeys = None
with pysftp.Connection('host', username='me', password='pass', cnopts=cnopts):
但显然这会让你在中间攻击中受到攻击。所以我尝试连接:
cnopts = pysftp.CnOpts(knownhosts='config/known_host')
cnopts.hostkeys = None
with pysftp.Connection(host, username=username, password=password, cnopts=cnopts) as sftp:
而且我收到了各种各样的错误消息。最近的一个是:
paramiko.hostkeys.InvalidHostKey
问题是我没有主机密钥,因为我是第一次连接。我试图从其他连接中获取密钥。我使用 WinSCP,但它将密钥存储在注册表文件中,格式与 known_host 不同。我尝试使用 ssh-keyscan 通过 PuTTY 获取它,但服务器甚至不允许我启动终端会话。我们不拥有这个盒子,托管服务提供商也不太可能提供我们需要的东西。
我运气不好吗?我应该继续绕过检查密钥吗?
解决方案可以在
import hashlib as hl
def trim_fingerprint(fingerprint):
#if fingerprint.startswith('ecdsa-sha2-nistp384 384 '):
#return fingerprint[len('ecdsa-sha2-nistp384 384 '):]
return fingerprint
def clean_fingerprint(fingerprint):
#return trim_fingerprint(fingerprint).replace(':', '')
return trim_fingerprint(fingerprint)
class FingerprintKey:
def __init__(self, fingerprint):
self.fingerprint = clean_fingerprint(fingerprint)
def compare(self, other):
if callable(getattr(other, "get_fingerprint", None)):
return other.get_fingerprint() == self.fingerprint
elif clean_fingerprint(other) == self.get_fingerprint():
return True
#elif hl.md5(other).digest().encode('hex') == self.fingerprint:
#The line below is required for Python 3. Above is Python 2.
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'ecdsa-sha2-nistp384'
def asbytes(self):
# Note: This returns itself.
# That way when comparisons are done to asbytes return value,
# this class can handle the comparison.
return self
我不得不从指纹中手动删除任何“:”,因为它根本无法让脚本执行此操作。
用法:
options = pysftp.CnOpts()
options.hostkeys.clear()
options.hostkeys.add('www.sample.com', u'ecdsa-sha2-nistp384 384 ', AuthOnFingerPrint.FingerprintKey(serverkey))
其中serverkey是指纹。