Python Urllib2 SSL 错误 [英] Python Urllib2 SSL error

查看:57
本文介绍了Python Urllib2 SSL 错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Python 2.7.9 现在对 SSL 证书验证更加严格.太棒了!

Python 2.7.9 is now much more strict about SSL certificate verification. Awesome!

对于以前运行的程序现在出现 CERTIFICATE_VERIFY_FAILED 错误,我并不感到惊讶.但我似乎无法让它们工作(不完全禁用证书验证).

I'm not surprised that programs that were working before are now getting CERTIFICATE_VERIFY_FAILED errors. But I can't seem to get them working (without disabling certificate verification entirely).

一个程序使用 urllib2 通过 https 连接到 Amazon S3.

One program was using urllib2 to connect to Amazon S3 over https.

我将根 CA 证书下载到名为verisign.pem"的文件中,然后尝试:

I download the root CA certificate into a file called "verisign.pem" and try this:

import urllib2, ssl
context = ssl.create_default_context()
context.load_verify_locations(cafile = "./verisign.pem")
print context.get_ca_certs()
urllib2.urlopen("https://bucket.s3.amazonaws.com/", context=context)

而且我仍然收到 CERTIFICATE_VERIFY_FAILED 错误,即使根 CA 在第 4 行中正确打印出来.

and I still get CERTIFICATE_VERIFY_FAILED errors, even though the root CA is printed out correctly in line 4.

openssl 可以正常连接到此服务器.其实这里是我用来获取CA证书的命令:

openssl can connect to this server fine. In fact, here is the command I used to get the CA cert:

openssl s_client -showcerts -connect bucket.s3.amazonaws.com:443 < /dev/null

我将链中的最后一个证书放入 PEM 文件中,openssl 读取正常.这是一个 Verisign 证书:

I took the last cert in the chain and put it in a PEM file, which openssl reads fine. It's a Verisign certificate with:

Serial number: 35:97:31:87:f3:87:3a:07:32:7e:ce:58:0c:9b:7e:da
Subject key identifier: 7F:D3:65:A7:C2:DD:EC:BB:F0:30:09:F3:43:39:FA:02:AF:33:31:33
SHA1 fingerprint: F4:A8:0A:0C:D1:E6:CF:19:0B:8C:BC:6F:BC:99:17:11:D4:82:C9:D0

任何想法如何在启用验证的情况下使其工作?

Any ideas how to get this working with validation enabled?

推荐答案

总结一下关于问题原因的评论,更详细地解释真正的问题:

To summarize the comments about the cause of the problem and explain the real problem in more detail:

如果您检查 OpenSSL 客户端的信任链,您会得到以下信息:

If you check the trust chain for the OpenSSL client you get the following:

 [0] 54:7D:B3:AC:BF:... /CN=*.s3.amazonaws.com 
 [1] 5D:EB:8F:33:9E:... /CN=VeriSign Class 3 Secure Server CA - G3
 [2] F4:A8:0A:0C:D1:... /CN=VeriSign Class 3 Public Primary Certification Authority - G5
[OT] A1:DB:63:93:91:... /C=US/O=VeriSign, Inc./OU=Class 3 Public Primary Certification Authority

第一个证书[0]是服务器发送的叶子证书.以下证书 [1] 和 [2] 是服务器发送的链式证书.最后一个证书[OT]是可信根证书,它不是由服务器发送的,而是在可信CA的本地存储中.链中的每个证书都由下一个签名,最后一个证书[OT]是可信的,所以信任链是完整的.

The first certificate [0] is the leaf certificate sent by the server. The following certifcates [1] and [2] are chain certificates sent by the server. The last certificate [OT] is the trusted root certificate, which is not sent by the server but is in the local storage of trusted CA. Each certificate in the chain is signed by the next one and the last certificate [OT] is trusted, so the trust chain is complete.

如果您通过浏览器(例如使用 NSS 库的 Google Chrome)检查信任链,您将获得以下链:

If you check the trust chain instead by a browser (e.g. Google Chrome using the NSS library) you get the following chain:

 [0] 54:7D:B3:AC:BF:... /CN=*.s3.amazonaws.com 
 [1] 5D:EB:8F:33:9E:... /CN=VeriSign Class 3 Secure Server CA - G3
[NT] 4E:B6:D5:78:49:... /CN=VeriSign Class 3 Public Primary Certification Authority - G5

这里[0]和[1]又是服务器发送的,但是[NT]是受信任的根证书.虽然这从主题看起来与链式证书 [2] 完全一样,但指纹表明证书是不同的.如果您仔细查看证书 [2] 和 [NT],您会发现证书中的公钥是相同的,因此 [2] 和 [NT] 都可用于验证 [1],因此可用于构建信任链.

Here [0] and [1] are again sent by the server, but [NT] is the trusted root certificate. While this looks from the subject exactly like the chain certificate [2] the fingerprint says that the certificates are different. If you would take a closer looks at the certificates [2] and [NT] you would see, that the public key inside the certificate is the same and thus both [2] and [NT] can be used to verify the signature for [1] and thus can be used to build the trust chain.

这意味着,虽然服务器在所有情况下都发送相同的证书链,但有多种方法可以验证该链直至可信根证书.这取决于 SSL 库和已知的受信任根证书:

This means, that while the server sends the same certificate chain in all cases there are multiple ways to verify the chain up to a trusted root certificate. How this is done depends on the SSL library and on the known trusted root certificates:

                          [0] (*.s3.amazonaws.com)
                           |
                          [1] (Verisign G3) --------------------------\
                           |                                          |
      /------------------ [2] (Verisign G5 F4:A8:0A:0C:D1...)         |
      |                                                               |
      |              certificates sent by server                      |
 .....|...............................................................|................
      |              locally trusted root certificates                |
      |                                                               |
     [OT] Public Primary Certification Authority        [NT] Verisign G5 4E:B6:D5:78:49
     OpenSSL library                                    Google Chrome (NSS library)

但问题仍然存在,为什么您的验证不成功.您所做的是将浏览器使用的受信任根证书 (Verisign G5 4E:B6:D5:78:49) 与 OpenSSL 一起使用.但是浏览器 (NSS) 和 OpenSSL 中的验证工作略有不同:

But the question remains, why your verification was unsuccessful. What you did was to take the trusted root certificate used by the browser (Verisign G5 4E:B6:D5:78:49) together with OpenSSL. But the verification in browser (NSS) and OpenSSL work slightly different:

  • NSS:根据服务器发送的证书构建信任链.当我们获得由任何本地受信任的根证书签署的证书时,停止构建链.
  • OpenSSL_ 根据服务器发送的证书构建信任链.完成此操作后,请检查我们是否拥有对链中最新证书进行签名的受信任根证书.

由于这种细微的差异,OpenSSL 无法根据根证书 [NT] 验证链 [0],[1],[2],因为该证书并未签署链 [2] 中的最新元素,而是[1].如果服务器只发送 [0],[1] 的链,则验证将成功.

Because of this subtle difference OpenSSL is not able to verify the chain [0],[1],[2] against root certificate [NT], because this certificate does not sign the latest element in chain [2] but instead [1]. If the server would instead only sent a chain of [0],[1] then the verification would succeed.

这是一个长期已知的错误并且存在补丁,希望通过引入 X509_V_FLAG_TRUSTED_FIRST<在 OpenSSL 1.0.2 中最终解决该问题/code> 选项.

This is a long known bug and there exist patches and hopefully the issue if finally addressed in OpenSSL 1.0.2 with the introduction of the X509_V_FLAG_TRUSTED_FIRST option.

这篇关于Python Urllib2 SSL 错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆