如何在Python requests库中添加OCSP支持?

1 投票
2 回答
3217 浏览
提问于 2025-04-21 06:20

有没有办法用 requests 库来实现 OCSP 检查呢?

我现在看到的唯一可行的方法是使用 pyOpenSSL,不过这意味着你需要单独建立一个连接去服务器获取证书,然后再连接到证书的发行者去验证它。

那么,是否有这样的实现呢?你们有没有解决这个问题,并愿意分享一下经验?

M2Crypto 看起来也是一个可以用于 SSL 连接的选择,虽然我不太确定这个库可能会有什么缺点,但它肯定比 requests 更底层。

附注:
显然,Python 在处理更复杂的 HTTP/HTTPS 连接时表现得很糟糕。

urllib 甚至连 SSL/TLS 证书都不检查,而 requests 自带一套 CA 证书(而不是使用系统的 CA),而且似乎不支持通过 PAC 配置代理。

我甚至尝试过使用 Qt 的 HTTP 栈(它使用操作系统的设置),但在处理多个并发连接时遇到了卡顿的问题。

2 个回答

1

其实,OpenSSL是支持OCSP的。我之前成功地用SSL.Connection打开了一个连接,但接下来我的问题是如何在这个连接上建立一个真正的HTTP连接。

我不知道这是否有帮助。实际上,OpenSSL确实支持OCSP。我之前能够通过SSL.Connection打开一个连接,但我的问题是如何在这个连接上进行真正的HTTP连接。

下面的代码可以让你打开一个OCSP连接,并完成整个OCSP的握手。下一步就是从这个连接创建一个HTTP连接。

ssl_context = Context(tls_method)
ssl_context.use_certificate_file(clientcert)
ssl_context.use_privatekey_file(clientkey)
ssl_context.load_verify_locations(cafile=None, capath=trusted_ca)
ssl_context.set_verify(VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT |VERIFY_CLIENT_ONCE, callback=self.verify_callback)
ssl_context.set_ocsp_client_callback(
        callback=self.ocsp_callback, data=None)
tcp_conn = socket.create_connection((host, port))
ssl_conn = Connection(ssl_context, tcp_conn)
ssl_conn.set_tlsext_host_name(host.encode())
ssl_conn.request_ocsp()
ssl_conn.set_connect_state()
ssl_conn.do_handshake()
2

从简单了解pyOpenSSL和M2Crypto来看,我怀疑它们是否能提供OCSP验证所需的功能,而且我没有看到有什么认真的尝试在Python中实现这个功能,更多信息可以查看这个链接

实现OCSP绝对不是一件简单的事情。OpenSSL的API没有文档说明,你需要从源代码中提取必要的部分。然后你还得尝试把这些部分组合在一起,做成一个用户可以实际使用的界面。

显然,Python在处理更复杂的HTTP/HTTPS连接时表现得很糟糕。

这不仅仅是Python的问题。如果你看看各种工具和编程语言,很多在验证证书这项基本任务上都做得不好,也就是检查证书是否有效,以及不要忘记检查证书中的名称是否与给定的主机名匹配。而且大多数工具要么不支持OCSP,要么只提供类似OpenSSL的API,这样用起来并不简单。

撰写回答