python的ssl模块是否正确验证了证书?(我有一个奇怪的例子,困扰我)

sni*_*ies 5 python security ssl https certificate

问题:

Python的ssl模块并没有抱怨证书,尽管cacert.pem文件中没有提供颁发CA(下面的测试用例2).我使用从Mozilla中提取的CA. Firefox正在抱怨未知的CA(在这种情况下是国防部).

似乎只有证书本身得到验证,而不是CA已知.我正在运行Python 2.7.1并使用ssl版本的OpenSSL 0.9.8r.

测试用例:

检查Firefox中的以下站点以及下面的python示例客户端.

  1. https://www.verisign.com - 应该工作,CA是众所周知的
  2. https://www.us.army.mil - 不应该工作,因为CA不知道
  3. https://www.pcwebshop.co.uk - 不应该工作,只有Parallels Panel证书

案例2.虽然它不应该由python客户端验证.

案例3.按预期抛出异常:

routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed
Run Code Online (Sandbox Code Playgroud)

示例Python客户端:

CA文件:http://curl.haxx.se/ca/cacert.pem(由curl维护者提供的mozilla默认CA).

http://docs.python.org/library/ssl.html#client-side-operation的略微修改版本:

# test_ssl.py   
import socket, ssl, pprint, sys
host = sys.argv[1]

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# require a certificate from the server
ssl_sock = ssl.wrap_socket(s,
                           # http://curl.haxx.se/ca/cacert.pem
                           ca_certs="cacert.pem", 
                           cert_reqs=ssl.CERT_REQUIRED)

ssl_sock.connect((host, 443))

print repr(ssl_sock.getpeername())
print ssl_sock.cipher()
print pprint.pformat(ssl_sock.getpeercert())

# Set a simple HTTP request -- use httplib in actual code.
ssl_sock.write("""GET / HTTP/1.0\r
Host: """ + host + """\r\n\r\n""")

# Read a chunk of data.  Will not necessarily
# read all the data returned by the server.
data = ssl_sock.read()
print data

# note that closing the SSLSocket will also close the underlying socket
ssl_sock.close()
Run Code Online (Sandbox Code Playgroud)

用法:

python test_ssl.py www.verisign.com
python test_ssl.py www.us.army.mil
python test_ssl.py www.pcwebshop.co.uk
Run Code Online (Sandbox Code Playgroud)

更新:

在strcat和其他人的帮助下,我可以确认这种行为特定于:

  • OSX Lion 10.7.1
  • Python 2.7.1和Python 2.6.7
  • OpenSSL 0.9.8r 2011年2月8日

我测试了两个mac和其他几个盒子.我怀疑Mac上的OpenSSL在我传递给它的文件旁边使用了第二个CA证书源.也许这使得www.us.army.mil成为一个特殊的测试用例,因为safari似乎也相信它开箱即用.有谁知道其他大型自签名网站或Mac上的openssl如何工作?

sni*_*ies 1

解决方案是:

通过测试我可以确认,在 OSX 上 openssl 确实使用系统 CA 证书存储,即使没有指定,如上面的 python 示例所示。

我使用 www.us.army.mil 作为测试用例,因为它是一个自签名网站(http://royal.pingdom.com/2008/08/19/new-ssl-policy-in-firefox-hurting -数万个站点/)。事实证明,OSX 上的系统 CA 证书包含两个 DoD 证书,因此 Safari 不会抱怨,我的 python 测试客户端也不会抱怨。

如果我不信任Keychan 访问 -> 系统根 -> 证书中的这些证书,python 客户端会显示预期的行为,这确认 python ssl / OpenSSL 在 OSX 10.7.1 上使用系统根证书,无论是否指定。我不知道这是否是预期的行为,但这确实让我感到惊讶。