我正在尝试在以“https”开头的网站上使用urllib.request.urlopen。错误输出是:
ssl.SSLError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed
有很多很好的线程可以解决这个错误。包括提及SSL实验室评级的this one。我可以在我测试过的每个其他“https”网站上使用urllib.request.urlopen。
SSL Labs显示以下输出:
Key RSA 2048 bits (e 65537)
Issuer Let's Encrypt Authority X3
AIA: http://cert.int-x3.letsencrypt.org/
Signature algorithm SHA256withRSA
Extended Validation No
Certificate Transparency No
OCSP Must Staple No
Revocation information OCSP
Revocation status Good (not revoked)
DNS CAA No (more info)
Trusted Yes
为了澄清,我的问题是:是否有完成握手的解决方案,不包括绕过证书验证?如果有解决方案,可以在linux,macOS和Windows上的python脚本中完全解决吗?
答案 0 :(得分:1)
您可以通过将缺少的中间证书添加到活动X509Store:
来解决此问题cert_text = '''
-----BEGIN CERTIFICATE-----
...put your actual certificate text here...
-----END CERTIFICATE-----
'''
# fill this out depending on which specific intermediate cert you're missing
missing_cert = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, cert_text)
context = ssl.create_default_context() # load default trusted certificates
store = context.get_cert_store() # get the X509Store for that context
store.add_cert(missing_cert) # add your missing cert to it
urllib.request.urlopen(site, context=context)
请注意,如果仅需要与您正在执行此操作的服务器通信,则可以将适当的cafile
或capath
参数传递给{ {1}}。
答案 1 :(得分:1)
我无法为 urllib 回答这个问题,但是我可以使用 python 请求来解决这个问题。请注意,这仅适用于相关网站存在可信证书链但服务器可能缺少根证书或中间证书的情况。
使用 SSL 实验室服务器测试 (linked here),运行测试并向下滚动到认证路径。如果存在受信任的证书路径,但服务器由于某种原因没有提供完整的链,您可以在此处以文本形式下载完整的受信任路径。复制完整的证书链并将其保存为 .pem 文件并将此文件的路径传递给 requests 函数:
r = requests.get(url, verify = "path/to/chain.pem")
requests 模块可以抛出各种与 SSL 相关的认证失败,其中许多将是服务器端问题,您真的希望避免禁用 SSL 验证。此解决方案仅适用于存在完整证书但相关颁发者或服务器草率省略根证书或中间证书的罕见情况。
答案 2 :(得分:0)
我能够解决这个问题(对于基于debian的系统,我正在运行Debian 9)。我仍然需要在macOS和Windows上测试解决方案。
在SSL Labs报告的"认证路径"标题,显示:
1 Sent by server www.exampleSITE.com
BLAH BLAH BLAH
2 Extra download Let's Encrypt Authority X3
BLAH BLAH BLAH
3 In trust store DST Root CA X3 Self-signed
BLAH BLAH BLAH
我导航到/etc/ssl/certs/
并注意到没有Let's Encrypt
个证书。然后我下载了.pem并重新开始。
cd /etc/ssl/certs
sudo wget https://letsencrypt.org/certs/lets-encrypt-x3-cross-signed.pem
sudo c_rehash
然后我测试了之前给我错误的python行
page = urllib.request.urlopen('https://www.exampleSITE.com').read()
并成功检索到该页面。