ProfK
ProfK

Reputation: 51063

Host key not found error with pysftp connection

I am trying to push a file to an FTP server using the following code from a Python 3 course I am following. I know this question has been asked before, but other questions don't seem to have tried as many attempts as I have.

import pysftp as sftp
import paramiko
from base64 import decodebytes

def get_cnoopts():
    #keydata = b"""2048 SHA256:XpP32aA8DFDaJ46A3V7GEXk+wJldB3K7HHAFlD4pvQ4 root@DevTuts (RSA)"""
    keydata = b"""2048 SHA256:XpP32aA8DFDaJ46A3V7GEXk+wJldB3K7HHAFlD4pvQ4"""
    key = paramiko.RSAKey(data=decodebytes(keydata))
    cnoopts = sftp.CnOpts()
    cnoopts.hostkeys.add("178.62.45.50", "ssh-rsa", key)

def push_file():
    s = sftp.Connection("198.63.45.20", username="root", password="sfewewetw", cnopts=get_cnoopts())
    local_path = "testme.txt"
    remote_path = "/home/testme.txt"

    s.put(local_path, remote_path)
    s.close()

push_file()

I have changed sensitive data above to protect the innocent, so this code will never work for you as is.

I first tried without the cnopts=get_cnoopts() argument, and then I get the very explanatory error:

SSHException: No hostkey for host 178.62.45.50 found.

Then I found the code for get_cnoopts in an answer here on this SO answer, but now I have to find a key that doesn't throw an error on decodebytes.

Finding host keys with ssh-keyscan yields:

# 178.62.45.50:22 SSH-2.0-OpenSSH_7.6p1 Ubuntu-4ubuntu0.3
178.62.45.50 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHTaCuJ+5dzrHyHWr7GwD/c2x7cwL2IaEiXpI+ygd4Ma
# 178.62.45.50:22 SSH-2.0-OpenSSH_7.6p1 Ubuntu-4ubuntu0.3
178.62.45.50 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDGeglgB51BVCuh6wVZFrp2iyBEOFpaLDiSobQT+41Nn39kSGEJXBUPJ+aJfLRZ2e4Eu2o+3DV4gKsG4IEnV10WpBQxAmuq4EQesO/wTQdfgregarteartyertyer5sJwKkyTvLxBLX3AplbS1zBrSTvMWnqqvNV8IaqcR43JOkdt8frtm6dELalNpdTN4Vm/+VdRiFpzUIUj4lyVcnlttXXreE7p8qciRRfCFYA5OhsAvsSDxccv99dvHDYsrdomHZRbpYzel2QNSWLylEsnbRLDABY13n4xtELXC0Us8QyMjhF2x5l7fkm4RYjQmheNdkoN1Ot
# 178.62.45.50:22 SSH-2.0-OpenSSH_7.6p1 Ubuntu-4ubuntu0.3
178.62.45.50 ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNretryreyrtZE8I2opSVi7R+2nlGMOs05s8j1NZfH3vIB7mL1ehfPbgp8Sjg8daQxQkm0U+NqWjCRE=

I tried all key lines, and the first gives me:

SSHException: No hostkey for host 178.62.45.50 found.

When I say I tried all key lines is that for each potential key given by ssh-keyscan, I have substituted each line in the output for my keydata variable value in my Python script.

Now I have tried using the entire string for keydata, and skipping the words from the beginning of the key string and both give me the same error. Using the second and third key strings I get the same error. The answer I examined also suggests using pysftp.CnOpts(knownhosts='known_hosts') where 'known_hosts' contains a server public key.

Then I tried another approach suggested in the same answer, as an alternative to get_cnoopts:

def get_cnoopts():
    cnoopts = sftp.CnOpts(knownhosts="""178.62.45.50 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDGeglgB51BVCuh6wVZFrp2iyBEOFpaLDiSobQT+41Nn39kSGEJXBUPJ+aJfLRZ2e4Eu2o+3DV4gKsG4IEnV10WpBQxAmuq4EQesO/wTQCXuUPw7LknIbIA3pFvJUxOa1K3xRm2TZgs9esJwKkyTvLxBLX3AplbS1zBrSTvMWnqqvNV8IaqcR43JOkdt8frtm6dELalNpdTN4Vm/+VdRiFpzUIUj4lyVcnlttXXreE7p8qciRRfCFYA5OhsAvsSDxccv99dvHDYsrdomHZRbpYzel2QNSWLylEsnbRLDABY13n4xtELXC0Us8QyMjhF2x5l7fkm4RYjQmheNdkoN1Ot""")
    return cnoopts

and I got the same error. Then I tried another suggestion, to use the winSCP->Server and protocol information dialogue, which lists MD5 and SHA-256 keys nice and explicitly. I have tried both key strings, with and without prefixes likessh-ed25519 255`, with the same error.

I suspect either the course's code is out of date, or I'm introducing some sort of encoding problem with copy and pasting between a source and my Python code. What could be wrong here?

Upvotes: 0

Views: 1562

Answers (1)

Ola Tuvesson
Ola Tuvesson

Reputation: 5201

Your get_cnoopts() doesn't return anything, so cnoopts=get_cnoopts() will be the same as cnoopts=. Try adding return cnoopts to the end of your get_cnoopts() function:

def get_cnoopts():
    keydata = b"""AAAA..."""
    key = paramiko.RSAKey(data=decodebytes(keydata))
    cnoopts = sftp.CnOpts()
    cnoopts.hostkeys.add("178.62.45.50", "ssh-rsa", key)
    return cnoopts

I've been frustrated by pysftp's key handling myself - I only managed to get it to work by manually loading (like you do) the host's RSA key, after copy/pasting from the output of ssh-keyscan. But the key snippets you show in your code look incorrect: an ssh RSA key should always begin with "AAAA" followed by a continuous stream of base64-encoded text (so no spaces, or hyphens). Try making these two changes and report back.

Upvotes: 1

Related Questions