【发布时间】:2015-06-08 02:03:33
【问题描述】:
我正在实现一个使用 API 的 Web 应用程序。在响应期间,API 服务器通过 X509 证书(PEM 格式,由签名证书和一个或多个指向根 CA 证书的中间证书组成)的链接发送我必须下载并使用该证书进行进一步验证。
在使用证书之前,我需要确保链中的所有证书结合起来创建一个信任链到受信任的根 CA 证书(以检测和避免任何恶意请求)。我在 python 中很难做到这一点,我对该主题的研究没有产生任何有用的东西。
使用请求和 M2Crypto 可以轻松获取和加载证书
import requests
from M2Crypto import RSA, X509
mypem = requests.get('https://server.com/my_certificate.pem')
cert = X509.load_cert_string(str(mypem.text), X509.FORMAT_PEM)
但是,验证证书链是个问题。我将证书写入磁盘以通过子进程之类的方式使用openssl 之类的命令行实用程序是不可行的,因此必须通过 python 完成。我也没有任何打开的连接,因此使用基于连接的验证解决方案(如此答案/线程中提到的:https://stackoverflow.com/a/1088224/4984533)也不起作用。
在关于这个问题的另一个线程上(https://stackoverflow.com/a/4427081),方丈解释说 m2crypto 无法进行此验证,并说他已经编写了一个扩展来允许验证(使用模块 m2ext),但他的补丁似乎从来没有工作, 即使我知道它是有效的,也总是返回 false:
from m2ext import SSL
ctx = SSL.Context()
ctx.load_verify_locations(capath='/etc/ssl/certs/') # I have run c_rehash in this directory to generate a list of cert files with signature based names
if not ctx.validate_certificate(cert): # always happens
print('Invalid certificate!')
在https://stackoverflow.com/a/9007764/4984533 的一个类似线程上也有这个答案,其中 John Matthews 声称编写了一个补丁可以做到这一点,但不幸的是补丁链接现在已经失效——无论如何,该线程上有一条评论说明该补丁不适用于 openssl 0.9.8e。
所有与在 python 中验证证书信任链相关的答案似乎要么链接到死补丁,要么返回到m2ext。
是否有一种简单、直接的方法来验证我在 Python 中的证书信任链?
【问题讨论】:
-
Btw pyopenssl 包装了 openssl,因此您无需从命令行使用它。如果您还没有python.org/dev/peps/pep-0476,也值得一读
-
感谢 Avi 的链接,我以前没见过。然而,它对我目前的困境没有帮助(它似乎特别是关于 http 客户端)。如有必要,我使用命令行程序进行验证没有问题——但如果我需要在每次请求时将 pem 文件写入磁盘,则没有问题。如果 openssl verify 命令可以接收原始字符串,那么我可以使用我想的(尽管对于我认为在 Python 中肯定是微不足道的事情来说,这似乎是一个 hacky 解决方法)。
标签: python validation ssl m2crypto