使用httlib的HTTPSConnection和PKCS#12证书时出错

Rem*_*yth 5 python authentication certificate pkcs#12 httplib

我正在尝试使用httplib的HTTPSConnection进行客户端验证,使用PKCS#12证书.我知道证书很好,因为我可以在MSIE和Firefox中使用它连接到服务器.

这是我的连接功能(证书包含私钥).我把它简化为基础知识:

def connect(self, cert_file, host, usrname, passwd):
    self.cert_file = cert_file
    self.host = host

    self.conn = httplib.HTTPSConnection(host=self.host, port=self.port, key_file=cert_file, cert_file=cert_file)

    self.conn.putrequest('GET', 'pathnet/,DanaInfo=200.222.1.1+')
    self.conn.endheaders()
    retCreateCon = self.conn.getresponse()

    if is_verbose:
        print "Create HTTPS connection, " + retCreateCon.read()
Run Code Online (Sandbox Code Playgroud)

(注意:请不要对硬编码路径发表评论 - 我试图让它首先工作;之后我会做得很好.硬编码路径是正确的,因为我在MSIE和Firefox中连接它我更改了帖子的IP地址.)

当我尝试使用PKCS#12证书(.pfx文件)运行它时,我得到了似乎是openSSL错误.这是整个错误回溯:

  File "Usinghttplib_Test.py", line 175, in 
    t.connect(cert_file=opts["-keys"], host=host_name, usrname=opts["-username"], passwd=opts["-password"])
  File "Usinghttplib_Test.py", line 40, in connect
    self.conn.endheaders()
  File "c:\python26\lib\httplib.py", line 904, in endheaders
    self._send_output()
  File "c:\python26\lib\httplib.py", line 776, in _send_output
    self.send(msg)
  File "c:\python26\lib\httplib.py", line 735, in send
    self.connect()
  File "c:\python26\lib\httplib.py", line 1112, in connect
    self.sock = ssl.wrap_socket(sock, self.key_file, self.cert_file)
  File "c:\python26\lib\ssl.py", line 350, in wrap_socket
    suppress_ragged_eofs=suppress_ragged_eofs)
  File "c:\python26\lib\ssl.py", line 113, in __init__
    cert_reqs, ssl_version, ca_certs) ssl.SSLError: [Errno 336265225] _ssl.c:337: error:140B0009:SSL routines:SSL_CTX_use_PrivateKey_file:PEM lib

请注意,openSSL错误(列表中的最后一个条目)注意到"PEM lib",我发现它很奇怪,因为我不想使用PEM证书.

为了解决问题,我将PKCS#12证书转换为PEM证书,并使用证书运行相同的代码.在那种情况下,我没有收到任何错误,我被提示输入PEM密码短语,代码确实试图到达服务器.(我收到了回复"服务不可用.请稍后再试."但我相信这是因为服务器不接受PEM证书.我无法使用PEM证书在Firefox中连接到服务器.)

httplib的HTTPSConnection应该支持PCKS#12证书吗?(也就是说,pfx文件.)如果是这样,为什么openSSL试图将其加载到PEM库中?我做错了吗?

欢迎任何建议.

编辑:证书文件包含证书和私钥,这就是我为HTTPSConnection的key_file和cert_file参数提供相同文件名的原因.

Bla*_*iro 5

这并不奇怪。Python 库参考文档对此非常清楚。来自http://docs.python.org/library/httplib.html

httplib 类。HTTPSConnection(主机[,端口[,密钥文件[,证书文件[,严格[,超时[,源地址]]]]]])

HTTPConnection 的子类,使用 SSL 与安全服务器进行通信。默认端口为 443。 key_file 是包含您的私钥的PEM 格式文件的名称。cert_file 是PEM 格式的证书链文件。


Rem*_*yth 4

在 openSSL 邮件列表上,我与 Mounir Idrassi 进行了交谈。他指出 openSSL 确实支持 PKCS#12 文件,并且根据我收到的错误消息,httplib 似乎调用了错误的函数来加载密钥。

用他的话说:

关于您收到的错误,您正在使用的 phython 模块似乎正在通过为其提供 PKCS#12 文件名来调用 SSL_CTX_use_PrivateKey_file。这不是因为 SSL_CTX_use_PrivateKey_file 仅接受两种格式:SSL_FILETYPE_PEM 和 SSL_FILETYPE_ASN1。

(我将 PKCS#12 文件名指定给 httplib 作为密钥文件,因为此文件格式在同一文件中包含证书和私钥。)

为了纠正这个问题,您有两种解决方案: - 要么向 python 模块提供 PEM 文件中的私钥。- 或者修改此 python 模块的源代码,以便使用我上面提到的 PKCS#12 函数将私钥提取为 EVP_PKEY,然后调用 SSL_use_PrivateKey 而不是 SSL_CTX_use_PrivateKey_file,以及 SSL_use_certificate 来设置关联的证书。

(我尝试了前者,但无法让它工作。并不一定意味着它不起作用;只是我无法做到。)