使用Python 3,我尝试使用SSL上下文连接到远程SMTP主机,但我得到以下错误:
[SSL:DH_KEY_TOO_SMALL] dh密钥太小(_ssl.c:1056)
以下是我使用的代码:用途:
from smtplib import SMTP
import ssl, os, certifi
ssl_context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH, cafile=certifi.where())
ssl_context.options |= ssl.OP_NO_TLSv1
ssl_context.options |= ssl.OP_NO_TLSv1_1
ssl_context.load_cert_chain(os.path.join(certsdir, 'certificate.pem'), os.path.join(certsdir, 'id_rsa'))
ssl_context.load_dh_params(os.path.join(certsdir, 'dhparams.pem'))
ssl_context.check_hostname = False
ssl_context.verify_mode = ssl.CERT_NONE
smtp = SMTP(server_name)
smtp.connect((host, 25))
smtp.ehlo()
if smtp.has_extn('starttls'):
smtp.starttls(None, None, ssl_context)
smtp.ehlo()
smtp.mail(fromaddr)
smtp.rcpt(toaddr)
smtp.data(message)
smtp.quit()
是我这边的问题,还是目标服务器那边的问题?我能做些什么来避免这个问题吗?
我使用certifi
作为证书列表,它基于Mozilla的建议,并且是最新的。
1条答案
按热度按时间roejwanj1#
问:问题是在我的端,还是在目标的服务器端?
服务器提供了一个弱DH密钥,客户端(你的脚本)想要一个更强的密钥。这个问题通常应该在服务器端解决。请注意,调用
load_dh_params
没有意义,因为设置DH键只与服务器端相关。我能做些什么来避免这个问题吗?
首先不要使用DH密码。所有现代客户端都支持ECDHE密码,而ECDHE密码没有这个问题。无论如何,DH都很慢。通常,客户端也会选择ECDHE密码,如果提供的话,这个错误不会发生。虽然可能是客户端的TLS堆栈太旧,更喜欢DH,但这样的旧堆栈通常不会抱怨弱DH。因此,更有可能的是,服务器的SSL堆栈太旧了,以至于它不能提供客户端默认需要的更现代的密码。
为了确保客户端不提供DH密码,因此使用ECDHE或RSA密钥交换,请相应地设置密码:
注意,RSA密钥交换也被认为是过时的,因为它不提供任何前向保密。因此,您可以通过使用密码字符串
DEFAULT:!DH:!kRSA
来尝试服务器是否可以在没有DH和没有kRSA的情况下运行。