【发布时间】:2021-12-28 23:49:55
【问题描述】:
我正在使用 paramiko (v2.7.1) 连接到具有授权密钥的主机。当我没有明确传递密钥时,我可以连接。但是,当我用key_filename 传递它时,我得到一个错误:
ValueError: ('Invalid private key', [_OpenSSLErrorWithText(code=67764350, lib=4, func=160, reason=126, reason_text=b'error:040A007E:rsa routines:RSA_check_key_ex:iqmp not inverse of q')])
我检查了路径是否正确,并且密钥确实与远程主机上的公钥匹配(以防我们使用其他方法登录)。
我也可以直接连接 w/ssh,无论是 w/o 显式密钥还是 with。当我没有明确指定密钥时, ssh -vvv 会打印到私钥的匹配路径。密钥使用rsa-sha2-512 编码。最后,当我从 ~/.ssh 中移动密钥并清除身份验证缓存时,我无法再连接 ssh,证明它绝对是让我进入的密钥。
还有什么我可以做的吗?我目前正在手动测试一个脚本,该脚本旨在在默认位置未安装密钥的情况下运行?
我的代码:
vm = paramiko.SSHClient()
vm.set_missing_host_key_policy(paramiko.AutoAddPolicy())
vm.connect(
DEST_ADDR, username=DEST_USER, key_filename=DEST_KEY_FILE,
)
代码不能按原样工作,但如果我注释掉key_filename 参数,它就可以工作。键的访问方式是否因查找方式而异?
追溯:
ValueError Traceback (most recent call last)
<ipython-input-25-57a83e5f85d1> in <module>
3 # vm.connect(
4 # JUMP_ADDR, username=JUMP_USER, key_filename=JUMP_KEY_FILE)
----> 5 vm.connect(
6 DEST_ADDR, username=DEST_USER, key_filename=DEST_KEY_FILE,
7 ) # sock=vmchannel)
/usr/local/share/anaconda3/lib/python3.8/site-packages/paramiko/client.py in connect(self, hostname, port, username, password, pkey, key_filename, timeout, allow_agent, look_for_keys, compress, sock, gss_auth, gss_kex, gss_deleg_creds, gss_host, banner_timeout, auth_timeout, gss_trust_dns, passphrase, disabled_algorithms)
433 key_filenames = key_filename
434
--> 435 self._auth(
436 username,
437 password,
/usr/local/share/anaconda3/lib/python3.8/site-packages/paramiko/client.py in _auth(self, username, password, pkey, key_filenames, allow_agent, look_for_keys, gss_auth, gss_kex, gss_deleg_creds, gss_host, passphrase)
674 for pkey_class in (RSAKey, DSSKey, ECDSAKey, Ed25519Key):
675 try:
--> 676 key = self._key_from_filepath(
677 key_filename, pkey_class, passphrase
678 )
/usr/local/share/anaconda3/lib/python3.8/site-packages/paramiko/client.py in _key_from_filepath(self, filename, klass, password)
584 cert_path = filename + cert_suffix
585 # Blindly try the key path; if no private key, nothing will work.
--> 586 key = klass.from_private_key_file(key_path, password)
587 # TODO: change this to 'Loading' instead of 'Trying' sometime; probably
588 # when #387 is released, since this is a critical log message users are
/usr/local/share/anaconda3/lib/python3.8/site-packages/paramiko/pkey.py in from_private_key_file(cls, filename, password)
233 :raises: `.SSHException` -- if the key file is invalid
234 """
--> 235 key = cls(filename=filename, password=password)
236 return key
237
/usr/local/share/anaconda3/lib/python3.8/site-packages/paramiko/rsakey.py in __init__(self, msg, data, filename, password, key, file_obj)
53 return
54 if filename is not None:
---> 55 self._from_private_key_file(filename, password)
56 return
57 if (msg is None) and (data is not None):
/usr/local/share/anaconda3/lib/python3.8/site-packages/paramiko/rsakey.py in _from_private_key_file(self, filename, password)
174 def _from_private_key_file(self, filename, password):
175 data = self._read_private_key_file("RSA", filename, password)
--> 176 self._decode_key(data)
177
178 def _from_private_key(self, file_obj, password):
/usr/local/share/anaconda3/lib/python3.8/site-packages/paramiko/rsakey.py in _decode_key(self, data)
192 n, e, d, iqmp, q, p = self._uint32_cstruct_unpack(data, "iiiiii")
193 public_numbers = rsa.RSAPublicNumbers(e=e, n=n)
--> 194 key = rsa.RSAPrivateNumbers(
195 p=p,
196 q=q,
/usr/local/share/anaconda3/lib/python3.8/site-packages/cryptography/hazmat/primitives/asymmetric/rsa.py in private_key(self, backend)
365 def private_key(self, backend=None) -> RSAPrivateKey:
366 backend = _get_backend(backend)
--> 367 return backend.load_rsa_private_numbers(self)
368
369 def __eq__(self, other):
/usr/local/share/anaconda3/lib/python3.8/site-packages/cryptography/hazmat/backends/openssl/backend.py in load_rsa_private_numbers(self, numbers)
600 evp_pkey = self._rsa_cdata_to_evp_pkey(rsa_cdata)
601
--> 602 return _RSAPrivateKey(self, rsa_cdata, evp_pkey)
603
604 def load_rsa_public_numbers(self, numbers):
/usr/local/share/anaconda3/lib/python3.8/site-packages/cryptography/hazmat/backends/openssl/rsa.py in __init__(self, backend, rsa_cdata, evp_pkey)
387 if res != 1:
388 errors = backend._consume_errors_with_text()
--> 389 raise ValueError("Invalid private key", errors)
390
391 # Blinding is on by default in many versions of OpenSSL, but let's
ValueError: ('Invalid private key', [_OpenSSLErrorWithText(code=67764350, lib=4, func=160, reason=126, reason_text=b'error:040A007E:rsa routines:RSA_check_key_ex:iqmp not inverse of q')])
【问题讨论】:
-
当我没有明确传递密钥时,我可以连接...听起来您无需身份验证即可连接,如果是这样,那就是一个安全漏洞。错误消息非常清楚,与连接尝试无关。您的私钥文件已损坏,或者至少错误消息是这样说的。实际上,文件的格式可能与预期不同。
-
no -- 见 ssh -vvv -- 它明确列出了密钥并说它的签名
sign_and_send_pubkey: signing using rsa-sha2-512这是明确指定密钥的情况,也不是。 ...是的:我希望 paramiko 以不同的方式查找密钥,并且如果明确指定,对格式(或尝试错误的编码?)更加挑剔.... and 当我使用 paramiko w /o 显式键我得到INFO:paramiko.transport:Authentication (publickey) successful!-- 没有那么多细节,但似乎使用了一个键。 -
错误信息清晰无误。也许只是为了测试尝试使用不同的键。
-
确实——而且错了!当我传递一个无效的密钥(启用调试)时,它使用该密钥失败,但随后在回退尝试中成功。 (不确定是否有关闭回退的选项。)