Python Urllib2 SSL

2024-05-03 23:04:08 发布

您现在位置:Python中文网/ 问答频道 /正文

Python2.7.9现在对SSL证书验证更加严格。令人惊叹的!

以前运行的程序现在出现证书验证失败的错误并不奇怪。但我似乎无法让它们工作(不完全禁用证书验证)。

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

我将根CA证书下载到一个名为“verisign.pem”的文件中,并尝试以下操作:

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)

我仍然得到证书验证失败的错误,即使根CA在第4行正确打印出来。

openssl可以连接到此服务器。实际上,下面是我用来获取CA证书的命令:

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

我把链中的最后一个证书放在一个PEM文件中,openssl可以很好地读取这个文件。这是一份Verisign证书,上面写着:

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

有什么办法让它在验证的情况下工作吗?


Tags: 文件https程序ssls3bucket错误context
1条回答
网友
1楼 · 发布于 2024-05-03 23:04:08

总结有关问题原因的评论,并更详细地解释实际问题:

如果检查OpenSSL客户机的信任链,将得到以下结果:

 [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]是受信任的,因此信任链是完整的。

如果使用浏览器(例如使用NSS库的Google Chrome)检查信任链,则会得到以下链:

 [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]的签名,从而可以用于构建信任链。

这意味着,虽然服务器在所有情况下都发送相同的证书链,但有多种方法可以将该链验证为受信任的根证书。如何执行此操作取决于SSL库和已知的受信任根证书:

                          [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的工作方式略有不同:

  • NSS:从服务器发送的证书建立信任链。当我们得到由任何本地受信任的根证书签名的证书时,停止构建链。
  • OpenSSL从服务器发送的证书构建信任链。完成此操作后,请检查是否有可信的根证书正在签名链中的最新证书。

由于这一细微差别,OpenSSL无法对照根证书[NT]验证链[0]、[1]、[2],因为此证书不对链[2]中的最新元素进行签名,而是对[1]进行签名。如果服务器只发送[0],[1]的链,则验证将成功。

这是一个long known bug,并且存在patches,如果通过引入X509_V_FLAG_TRUSTED_FIRST选项最终在OpenSSL 1.0.2中解决了这个问题,那就很有希望了。

相关问题 更多 >