Python 客户端证书请求在 Ubuntu 上失败

Python client certicate request fails on Ubuntu

我有以下最小文件:

import requests
index_response = requests.get("https://my.end.point.com/", cert="mypem.pem")
print(index_response.status_code)

两者都使用 Python 2.7.15 并且没有显示任何错误,所以我不清楚从哪里开始寻找。我明白这不是一个容易重现的例子;如果有任何示例 PEM/endpoints 我可以使用,我很乐意编辑我的问题。

首先,如@wowkin2 所述,请确保您在两台计算机上使用相同版本的请求和 urllib3。我在这里使用 requests==2.22.0 和 urllib3==1.25.7。

请考虑切换到 Python3,Python2 支持将于 2020 年 1 月结束。

好的,所以如果您有相同的版本但仍然看到问题,让我们尝试先使用另一个客户端证书进行调试。 badssl.com 是提供此类客户端证书的 TLS 测试服务。使用 badssl.com 进行测试比应该的更复杂,因为它使用密码并且 requests 不支持开箱即用,但您可以通过以下方式进行测试:

import requests
from requests.adapters import HTTPAdapter
from urllib3.poolmanager import PoolManager


class ClientCertPasswordAdapter(HTTPAdapter):
    def __init__(self, password):
        self.password = password
        super(ClientCertPasswordAdapter, self).__init__()

    def init_poolmanager(self, connections, maxsize, block=False):
        self.poolmanager = PoolManager(
            num_pools=connections,
            maxsize=maxsize,
            block=block,
            key_password=self.password,
        )


print("fetching client certificate")
with open("client.pem", "wb") as f:
    r = requests.get("https://badssl.com/certs/badssl.com-client.pem")
    f.write(r.content)

print("requesting data")
s = requests.Session()
s.mount("https://client.badssl.com/", ClientCertPasswordAdapter("badssl.com"))
r = s.get("https://client.badssl.com/", cert="client.pem")
print(r.status_code)

这是否为您的两个操作系统打印 200?这将允许排除证书中的问题。

您可以进行的另一个测试是使用您的客户端证书并将其提供给服务器,该服务器不会验证它但会向您打印它收到的 public 信息。我在这里发送 badssl.com 客户端证书:

import requests
from requests.adapters import HTTPAdapter
from urllib3.poolmanager import PoolManager


class ClientCertPasswordAdapter(HTTPAdapter):
    def __init__(self, password):
        self.password = password
        super(ClientCertPasswordAdapter, self).__init__()

    def init_poolmanager(self, connections, maxsize, block=False):
        self.poolmanager = PoolManager(
            num_pools=connections,
            maxsize=maxsize,
            block=block,
            key_password=self.password,
        )


print("fetching client certificate")
with open("client.pem", "wb") as f:
    r = requests.get("https://badssl.com/certs/badssl.com-client.pem")
    f.write(r.content)

print("requesting data")
s = requests.Session()
s.mount("https://server.cryptomix.com/", ClientCertPasswordAdapter("badssl.com"))
r = s.get("https://server.cryptomix.com/secure/", cert="client.pem")
print(r.status_code)
print(r.text)

这应该打印调试信息,包括 SSL_CLIENT 信息:

[SSL_CLIENT_S_DN_C] => US
[SSL_CLIENT_S_DN_ST] => California
[SSL_CLIENT_S_DN_L] => San Francisco
[SSL_CLIENT_S_DN_O] => BadSSL
[SSL_CLIENT_S_DN_CN] => BadSSL Client Certificate
[SSL_CLIENT_I_DN_C] => US
[SSL_CLIENT_I_DN_ST] => California
[SSL_CLIENT_I_DN_L] => San Francisco
[SSL_CLIENT_I_DN_O] => BadSSL
[SSL_CLIENT_I_DN_CN] => BadSSL Client Root Certificate Authority
[SSL_CLIENT_VERIFY] => GENEROUS
[SSL_CLIENT_M_VERSION] => 3
[SSL_CLIENT_M_SERIAL] => 2B936CE32D82CE8B01FD9A0595AC6366AA014C82
[SSL_CLIENT_V_START] => Nov 27 00:19:57 2019 GMT
[SSL_CLIENT_V_END] => Nov 26 00:19:57 2021 GMT
[SSL_CLIENT_V_REMAIN] => 730
[SSL_CLIENT_S_DN] => CN=BadSSL Client Certificate,O=BadSSL,L=San Francisco,ST=California,C=US
[SSL_CLIENT_I_DN] => CN=BadSSL Client Root Certificate Authority,O=BadSSL,L=San Francisco,ST=California,C=US
[SSL_CLIENT_A_KEY] => rsaEncryption
[SSL_CLIENT_A_SIG] => sha256WithRSAEncryption
[SSL_CLIENT_CERT_RFC4523_CEA] => { serialNumber 248774298121081469895139733087446207053965642882, issuer rdnSequence:"CN=BadSSL Client Root Certificate Authority,O=BadSSL,L=San Francisco,ST=California,C=US" }

您看到两个操作系统的值相同吗?