对于那些需要与需要私钥的 ssh/sftp 服务器集成并希望使用特定公钥对已知主机执行主机密钥验证的人来说,下面是带有 paramiko 的代码片段:
import paramiko
sftp_hostname = "target.hostname.com"
sftp_username = "tartgetHostUsername"
sftp_private_key = "/path/to/private_key_file.pvt"
sftp_private_key_password = "private_key_file_passphrase_if_it_encrypted"
sftp_public_key = "/path/to/public_certified_file.pub"
sftp_port = 22
remote_path = "."
target_local_path = "/path/to/target/folder"
ssh = paramiko.SSHClient()
# Load target host public cert for host key verification
ssh.load_host_keys(sftp_public_key)
# Load encrypted private key and ssh connect
key = paramiko.RSAKey.from_private_key_file(sftp_private_key, sftp_private_key_password)
ssh.connect(host=sftp_hostname, port=sftp_port, username=sftp_username, pkey=key)
# Get the sftp connection
sftp_connection = ssh.open_sftp()
directory_list = sftp_connection.listdir(remote_path)
# ...
if sftp_connection: sftp_connection.close()
if ssh: ssh.close()
请注意,仅支持经典 Openssh 格式 ,否则需要使用以下命令进行转换(也适用于最新的 Openssh 格式):
$chmod 400 /path/to/private_key_file.pvt
$ssh-keygen -p -f /path/to/private_key_file.pvt -m pem -P <currentPassphrase> -N <newPassphrase>
为了避免中间人攻击,重要的是不要 paramiko.AutoAddPolicy()
像上面那样以编程方式使用和加载公共主机密钥,也不要从 ~/.ssh/known_hosts
该文件必须采用以下格式 "<host_name> ssh-rsa AAAAB3NzaC1yc2EAAAA..."
如果您没有公钥并且您信任目标主机(小心 mitm),您可以使用 $ssh-keyscan target.hostname.com
命令下载它。
上述代码是我发现的唯一可以避免连接时出现以下错误的方法:
paramiko.ssh_exception.SSHException: Server 'x.y.z' not found in known_hosts
使用以下方式加载公共证书时也会出现此错误:
key = paramiko.RSAKey(data=decodebytes(sftp_public_key))
ssh_client.get_host_keys().add(sftp_hostname, 'ssh-rsa', key)
另外,以下代码也无法让我加载证书(也尝试过用 base64 对证书进行编码):
ssh_client=paramiko.SSHClient()
rsa_key = paramiko.RSAKey.from_private_key_file(sftp_private_key, sftp_private_key_password)
rsa_key.load_certificate(sftp_public_key)
它总是以以下内容结束:
File "/usr/local/lib/python3.9/site-packages/paramiko/pkey.py", line 720, in from_string
key_blob = decodebytes(b(fields[1]))
File "/usr/lib64/python3.9/base64.py", line 538, in decodebytes
return binascii.a2b_base64(s)
binascii.Error: Incorrect padding
上述代码适用于与 GoAnywhere 的 SFTP 集成。
我希望这会有所帮助,我没有找到任何可行的示例,并且花了很多时间进行搜索和测试。使用 pysftp 包装器的实现现在被认为从 2016 年开始停止。