Python中的SSL:为什么不向服务器发送证书?

2 投票
2 回答
2782 浏览
提问于 2025-04-16 20:16

我正在写一个软件,目的是从使用SSL加密的网页获取信息。下面是我用来连接服务器的代码片段。

s = socket.socket (socket.AF_INET, socket.SOCK_STREAM)
ssl_sock = ssl.wrap_socket (
    s,
    ca_certs = '/home/stilz/Desktop/Certyfikaty/GLOWNE_CA.cer',
    cert_reqs = ssl.CERT_REQUIRED,
    ssl_version = ssl.PROTOCOL_SSLv3,
)
ssl_sock.connect ((HOST, PORT))

不过,这个代码并没有成功。它抛出了一个异常,提示“握手警报失败”。我抓取了一些从我的脚本发出的TCP数据包,并且也抓取了Internet Explorer发送的对应数据包,发现我的脚本根本没有发送证书(服务器返回的信息类似于“致命错误:没有提供证书”),而IE则正常发送了证书。根据我所知,文件ca.cer是一个x509证书(以“-----BEGIN CERTIFICATE-----”开头)。

请帮帮我,告诉我我哪里做错了。如果我提供的信息太少,请告诉我。

谢谢!

2 个回答

0

如果服务器要求客户端发送一个证书,你需要给ssl.wrap_socket提供你自己的证书的路径(也就是certfile)和与之匹配的私钥(也就是keyfile)。ca_certs这个参数只是用来让客户端验证服务器的证书是否和已知的CA证书匹配,它和发送客户端证书没有关系。

你可能需要从IE导出你的客户端证书和私钥,然后把它们转换成PEM格式。

1

首先,你需要搞清楚你是否需要在服务器上进行身份验证(只有在这种情况下,证书才会发送给服务器),或者你需要验证服务器的真实性(在这种情况下,证书不会发送给服务器)。

接下来说说你代码中的问题:

情况一:你不需要在服务器上进行身份验证。在这种情况下,你不需要指定你的证书,也就什么都不会发送给服务器。

情况二:你需要在服务器上进行身份验证。在这种情况下,你需要提供你的证书和私钥文件,这些信息分别放在keyfile和certfile参数中。只有这样,你的证书才会发送给服务器(而私钥会在握手过程中使用)。

我猜实际上你是情况一。所以首先你需要检查服务器是否提供了有效的证书,可以通过用网页浏览器连接到服务器并查看网站的证书链来确认。可能会出现网站发送了它的证书,但中间的CA证书却漏掉了的情况。

无论如何,我想提醒你去看看Python文档中关于证书的讨论,我建议你再读一遍。

撰写回答