如果SSL实验室显示“此服务器的证书链不完整,则可以完成证书握手。等级上限为B.”?

时间:2017-07-27 07:54:46

标签: python ssl urllib handshake pyopenssl

我正在尝试在以“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脚本中完全解决吗?

3 个答案:

答案 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)

请注意,如果需要与您正在执行此操作的服务器通信,则可以将适当的cafilecapath参数传递给{ {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()

并成功检索到该页面。