12

我正在尝试做一个小型安全 HTTPS 客户端以用于学习目的,并了解 SSL 的所有机制目前如何在更高级别上工作,因此我正在尝试通过 ssl.wrap_socket 将简单的套接字转换为 ssl。

我可能把整个概念倒过来了,但是,这就是我正在做的事情:

s.connect((host, port))
if port == 443:
    f = open('cacerts.txt', 'r')
    calist = f.read()
    f.close()
    ca = ssl.get_server_certificate((host, port), ssl_version=ssl.PROTOCOL_SSLv3|ssl.PROTOCOL_TLSv1)
    if not ca in calist:
        f = open('cacerts.txt', 'a')
        f.write(ca)
        f.close()
    s = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_SSLv3|ssl.PROTOCOL_TLSv1, cert_reqs=ssl.CERT_REQUIRED, ca_certs="cacerts.txt")
    s.do_handshake()

当我调用 do_handshake() 时,我得到了这个:

Traceback (most recent call last):
  File "SSL_test.py", line 84, in Requester
    s = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_SSLv3|ssl.PROTOCOL_TLSv1, cert_reqs=ssl.CERT_REQUIRED, ca_certs="cacerts.txt")
  File "C:\Python26\lib\ssl.py", line 338, in wrap_socket
    suppress_ragged_eofs=suppress_ragged_eofs)
  File "C:\Python26\lib\ssl.py", line 120, in __init__
    self.do_handshake()
  File "C:\Python26\lib\ssl.py", line 279, in do_handshake
    self._sslobj.do_handshake()
ssl.SSLError: [Errno 1] _ssl.c:490: error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed

我已经搜索了一段时间并试图找到与我所做的接近的东西,但每个人都指向 PyOpenSSL 或 Twisted,如果我可以远离这些库,我更愿意,主要是因为稍后我'我计划把它带入一个尖锐的生产环境,我只被允许使用 Python2.6 的内置库。

任何帮助都会很棒!

4

2 回答 2

10

这里的问题是,除非证书是自签名的并且设置了 CA 位,否则您无法自行验证证书(这就是您要尝试做的事情)。您应该将网站的真实 CA 证书添加到cacerts.txt文件中。另一种选择(例如在网络浏览器中“无论如何都连接”)是在遇到此类异常后将其删除cert_reqsssl.CERT_NONE并了解中间可能有一个人。这不是ssl模块问题,这就是 SSL/X.509 的工作方式。

于 2011-09-21T15:53:04.857 回答
1

如果您只是学习,您也可以使用Anonymous Diffie-Hellman,即服务器根本没有证书,并且您的客户端不关心验证它。

下面是一个简单(且不安全)的测试。

测试服务器,由openssl软件包提供:

openssl s_server  -nocert -cipher "ALL:aNULL:eNULL"

测试客户端Python

...
ssl.wrap_socket(..., ciphers="ALL:aNULL:eNULL")
...

--

如果你想玩证书,opensslpackage 可以生成你想要的东西,但是要正确使用它有点棘手。好的 GUI 工具是TinyCA,它用 perl 编写并使用 openssl 命令,但为您提供了一个不错的框架来创建自己的 CA、签署自己的证书等。

如果您赶时间,只需安装 apache,启动它,您的发行版(linux 或 wamp)很可能会创建一个自签名证书来帮助您入门。将 apache 配置到可以https://localhost使用浏览器连接的位置。然后使用该服务器连接到,我认为如果您将服务器的自签名 CA 添加到您的客户端 CA 列表/文件中,您会成功的。

于 2013-12-03T10:02:53.143 回答