Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/ssh/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python-pysftp/paramiko-使用其指纹验证主机密钥_Python_Ssh_Paramiko_Pysftp - Fatal编程技术网

Python-pysftp/paramiko-使用其指纹验证主机密钥

Python-pysftp/paramiko-使用其指纹验证主机密钥,python,ssh,paramiko,pysftp,Python,Ssh,Paramiko,Pysftp,此代码引发异常。如何在不将SSH指纹存储在文件中的情况下验证它?我相信下面的代码是为公钥设计的。但是带有SFTP服务器的客户端验证了指纹,没有给我公钥 import os import shutil import pysftp import paramiko connection_info = { 'server': "example.com", 'user': "user", 'passwd': "password", 'target_dir': "out/

此代码引发异常。如何在不将SSH指纹存储在文件中的情况下验证它?我相信下面的代码是为公钥设计的。但是带有SFTP服务器的客户端验证了指纹,没有给我公钥

import os
import shutil

import pysftp
import paramiko

connection_info = {
    'server': "example.com",
    'user': "user",
    'passwd': "password",
    'target_dir': "out/prod",
    'hostkey': "ssh-rsa 2048 d8:4e:f1:f1:f1:f1:f1:f1:21:31:41:14:13:12:11:aa",
}

def move_files_from_server_to_local(server, localpath):
    target_dir = server['target_dir']
    keydata = "d8:4e:f1:f1:f1:f1:f1:f1:21:31:41:14:13:12:11:aa"
    key = paramiko.RSAKey(data=decodebytes(keydata))
    options = pysftp.CnOpts()
    options.hostkeys.add('example.com', 'ssh-rsa', key)
    with pysftp.Connection(
                    server['server'],
                    username=server['user'],
                    password=server['passwd'],
                    cnopts=options) as conn:
        conn.get_d(target_dir, localpath)
        delete_files_from_dir(conn, target_dir)

move_files_from_server_to_local(connection_info, "/")

代码基于。

根据您的需要,您可以使用以下两种方法之一:

如果您只需要验证一个特定的主机密钥 使用(或类似)检索主机公钥:

ssh-keyscan example.com > tmp.pub
tmp.pub
将类似于(
known\u hosts
文件格式):

example.com ssh rsa一个2岁的研究者在一个2岁的研究中发现了一个2岁的一个2岁的一个2岁的一个2岁的一个2岁的一个2岁的一个2岁的一个2岁的一个2岁的一个2岁的一个2岁的一个2岁的一个2岁的一个2岁的一个2岁的一个2岁的一个2岁的2岁的一个2岁的一个2岁的2岁的一个2岁的一个2岁的2岁的一个2岁的2岁的一个2岁的2岁的2岁的2岁的2岁的2岁的一个2岁的2岁的2岁的2岁的2岁的2岁的2岁的一个2岁的2岁的2岁的2岁的2岁的2岁的2岁的2岁的2岁的2岁的2岁的2岁的2岁的2岁的2岁的2岁的2岁的一个2岁的一SB9C+iDEiFcT/lT4/dQ+kRW6DYn66lS8peS8zCJ9CSQ==
现在,您可以使用以下方法计算该公钥的指纹:

(仅在支持多种指纹算法且默认为SHA256的较新版本的OpenSSH上使用
-E md5

您将得到如下结果:

2048 MD5:c4:26:18:cf:a0:15:9a:5f:f3:bf:96:d8:3b:19:ef:7b example.com(RSA)
如果指纹与您拥有的指纹匹配,您现在可以安全地假定
tmp.pub
是合法的公钥,并在代码中使用它:

from base64 import decodebytes
# ...

keydata = b"""AAAAB3NzaC1yc2EAAAABIwAAAQEA0hV..."""
key = paramiko.RSAKey(data=decodebytes(keydata))
cnopts = pysftp.CnOpts()
cnopts.hostkeys.add('example.com', 'ssh-rsa', key)

with pysftp.Connection(host, username, password, cnopts=cnopts) as sftp:
(基于)

如果您需要根据主机密钥的指纹自动验证主机密钥 例如,因为指纹来自外部配置

我不确定PySTFP的有限API是否允许这样做。您可能必须跳过pysftp并直接使用(pysftp在内部使用Paramiko)

使用Paramiko,您可以巧妙地实现

从如何实施开始:

class AutoAddPolicy (MissingHostKeyPolicy):
    """
    Policy for automatically adding the hostname and new host key to the
    local `.HostKeys` object, and saving it.  This is used by `.SSHClient`.
    """

    def missing_host_key(self, client, hostname, key):
        client._host_keys.add(hostname, key.get_name(), key)
        if client._host_keys_filename is not None:
            client.save_host_keys(client._host_keys_filename)
        client._log(DEBUG, 'Adding %s host key for %s: %s' %
                    (key.get_name(), hostname, hexlify(key.get_fingerprint())))
请注意,在代码中,您可以在
hexlify(key.get_fingerprint())
中找到指纹。只需将该值与您拥有的指纹进行比较。如果匹配,就返回。否则就提出例外,, 就像那个男孩一样


另一个解决方案(甚至可以与PySTFP一起使用)是以只保留指纹的方式实现。并实现其仅用于比较指纹。这样的
PKey
实例可以添加到
cnopts.hostkeys.add


OP在年发布了该方法的实现。据称,对于Python 3,需要更复杂的实现,如中所示。

基于Martin Prikryl的回答,下面是我的解决方案

def trim_fingerprint(fingerprint):
    if fingerprint.startswith('ssh-rsa 2048 '):
        return fingerprint[len('ssh-rsa 2048 '):]
    return fingerprint
def clean_fingerprint(fingerprint):
    return trim_fingerprint(fingerprint).replace(':', '')

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 md5(other).digest().encode('hex') == 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-rsa'
    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.example.com', u'ssh-rsa', FingerprintKey("ssh-rsa 2048 d8:4e:f1:f1:f1:f1:f1:f1:21:31:41:14:13:12:11:aa"))
    with pysftp.Connection(
                    'www.example.com',
                    username='user',
                    password='password',
                    cnopts=options) as conn:
        conn.get_d('remote/filedir', 'c:/local/output')

美好的我已经把这个和我的答案联系起来了Python3版本
options = pysftp.CnOpts()
options.hostkeys.clear()
options.hostkeys.add('www.example.com', u'ssh-rsa', FingerprintKey("ssh-rsa 2048 d8:4e:f1:f1:f1:f1:f1:f1:21:31:41:14:13:12:11:aa"))
    with pysftp.Connection(
                    'www.example.com',
                    username='user',
                    password='password',
                    cnopts=options) as conn:
        conn.get_d('remote/filedir', 'c:/local/output')