通过将浏览器指向https://graph.facebook.com/me,我得到了一个加密的HTTPS连接,证书链是:
(root)
因此,我从https://www.digicert.com/digicert-root-certificates.htm下载了根证书(我也从浏览器导出了它,diff显示它们是相同的),并尝试使用内置的SSL模块来验证到graph.facebook.com连接的真实性。
我刚刚执行了示例http://docs.python.org/library/ssl.html#client-side-operation,将ca_cert替换为"DigiCertHighAssuranceEVRootCA.crt“,将地址替换为graph.facebook.com。连接尝试失败,例外情况如下:
ssl.SSLError: [Errno 1] _ssl.c:499: error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed如果我对ev-root.digicert.com (这是DigiCert为测试客户端是否能够验证其证书而提供的地址)尝试相同的代码和证书,那么一切都很好。通过浏览器,我可以验证在此连接中使用的链是:
(root)
(通过运行ssl.get_server_certificate(('graph.facebook.com',443),我的浏览器获得了标识为"*.facebook.com“的相同证书,这意味着Python和我的浏览器获得相同的证书来进行验证。
为什么Chrome可以用给定的根证书来验证graph.facebook.com,而Python可以用相同的根证书验证另一个站点,但是Python不能验证graph.facebook.com?
发布于 2011-10-29 21:07:13
我从OpenSSL邮件列表中得到了答案。"DigiCert高级保证EV根CA“似乎是由另一个证书颁发机构在自我签名之前签署的。现在有两个版本的证书。其中一个与SSL实现捆绑在一起,由DigiCert提供供下载,它是自签名的,可以用作根CA来验证它签署的其他证书。另一个版本是由Facebook服务器在SSL握手过程中返回的版本,该握手过程由一些Entrust证书签名。两者都有相同的公钥和密钥。
NSS是Firefox和Chrome的SSL实现,它显然正确地遵循了X.509规范,忽略了服务器发送的链中的最后一个证书,并使用自己信任的版本"DigiCert高级保证EV根CA“来验证该链。Python的实现是通过OpenSSL实现的,它使用主机提供的证书验证"DigiCert高级保证CA-3“,然后尝试验证最后一个证书。因为它是由其他CA签名的,而且我没有提供该证书,所以它失败了。我不认为这种行为是正确的,因为我已经信任链中间的证书,理论上我没有必要检查其余的证书。
我的解决方案是向ssl模块提供验证"DigiCert高保证EV根CA“的信任证书。
发布于 2017-09-21 07:59:14
如果您在代理后面工作,您还可能希望在浏览器中打开https://graph.facebook.com,并从那里检查证书路径。您的代理可能是网站证书的颁发者。在本例中,标识代理证书,将其解压缩到pem文件中,并将内容附加到Python证书cacert.pem证书中。
https://stackoverflow.com/questions/7700274
复制相似问题