В зависимости от ваших потребностей вы можете использовать любой из этих двух методов:
Если вам нужно проверить только один конкретный ключ хоста
Используйте ssh-keyscan
(или аналогичный), чтобы получить открытый ключ хоста:
ssh-keyscan example.com > tmp.pub
tmp.pub
будет выглядеть так (формат файла known_hosts
):
example.com ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA0hVqZOvZ7yWgie9OHdTORJVI5fJJoH1yEGamAd5G3werH0z7e9ybtq1mGUeRkJtea7bzru0ISR0EZ9HIONoGYrDmI7S+BiwpDBUKjva4mAsvzzvsy6Ogy/apkxm6Kbcml8u4wjxaOw3NKzKqeBvR3pc+nQVA+SJUZq8D2XBRd4EDUFXeLzwqwen9G7gSLGB1hJkSuRtGRfOHbLUuCKNR8RV82i3JvlSnAwb3MwN0m3WGdlJA8J+5YAg4e6JgSKrsCObZK7W1R6iuyuH1zA+dtAHyDyYVHB4FnYZPL0hgz2PSb9c+iDEiFcT/lT4/dQ+kRW6DYn66lS8peS8zCJ9CSQ==
Теперь вы можете вычислить отпечаток этого открытого ключа с помощью ssh-keygen
:
ssh-keygen -l -f tmp.pub -E md5
(используйте -E md5
только с более новыми версиями OpenSSH, которые поддерживают несколько алгоритмов отпечатков пальцев и по умолчанию используют SHA256)
Вы получите что-то вроде:
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:
(на основе Подтвердите ключ хоста с помощью pysftp)
Если вам нужно автоматизировать проверку ключа хоста по его отпечатку пальца
Например. потому что отпечаток пальца поступает из внешней конфигурации.
Я не уверен, позволяет ли это ограниченный API pysftp. Вероятно, вам придется пропустить pysftp и напрямую использовать библиотеку Paramiko (pysftp использует Paramiko для внутренних целей).
С Paramiko вы можете грамотно реализовать MissingHostKeyPolicy
интерфейс a >.
Начнем с того, как реализован AutoAddPolicy
:
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())
. Просто сравните это значение с вашим отпечатком пальца. Если совпадает, просто вернись. В противном случае вызовите исключение, например RejectPolicy
делает.
Другое решение (которое будет работать даже с pysftp) - реализовать PKey
таким образом, что на нем хранится только отпечаток пальца. И реализуйте его __cmp__
метод, чтобы сравните только отпечаток пальца. Такой экземпляр PKey
затем может быть добавлен к cnopts.hostkeys.add
.
OP опубликовал реализацию этого подхода в своем ответе. Предположительно для Python 3 требуется более сложная реализация, как показано в Подключение к серверу SFTP с использованием pysftp и Python 3 только с отпечатком сервера < / а>.
person
Martin Prikryl
schedule
19.10.2017