什么" SSLError:[SSL] PEM lib(_ssl.c:2532)"意味着使用Python ssl库?

时间:2015-05-07 18:55:32

标签: python python-3.x ssl ssl-certificate python-asyncio

我正在尝试使用Python 3 asyncio模块连接到另一方并收到此错误:

     36     sslcontext = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
---> 37     sslcontext.load_cert_chain(cert, keyfile=ca_cert)
     38

SSLError: [SSL] PEM lib (_ssl.c:2532)

问题在于错误的意思。我的证书是正确的,密钥文件(CA证书)可能不是

5 个答案:

答案 0 :(得分:25)

假设正在使用3.4版:

请参阅:https://github.com/python/cpython/blob/3.4/Modules/_ssl.c#L2529-L2535

 PySSL_BEGIN_ALLOW_THREADS_S(pw_info.thread_state);
 r = SSL_CTX_check_private_key(self->ctx);
 PySSL_END_ALLOW_THREADS_S(pw_info.thread_state);
 if (r != 1) { 
    _setSSLError(NULL, 0, __FILE__, __LINE__);
    goto error;
 }

它的含义是SSL_CTX_check_private_key失败了;因此,私钥不正确。

答案 1 :(得分:15)

在您的代码中,您正在致电:

sslcontext.load_cert_chain(cert, keyfile=ca_cert)

来自documentation

  

加载私钥和相应的证书。证书文件   string必须是包含PEM格式的单个文件的路径   证书以及需要的任何数量的CA证书   建立证书的真实性。密钥文件字符串,如果   present,必须指向包含私钥的文件。否则   私钥也将从certfile中获取。见   讨论证书以获取有关证书的更多信息   存储在certfile中。

根据示例中参数的名称,看起来您正在将CA证书传递给keyfile参数。这是不正确的,您需要传入用于生成本地证书的私钥(否则客户端无法使用您的证书)。私钥文件类似于:

-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: AES-128-CBC,9BA4973008F0A0B36FBE1426C198DD1B

...data...
-----END RSA PRIVATE KEY-----

如果您要验证此证书已签署的SSL证书的有效性,则只需要CA证书。在这种情况下,您可能会使用SSLContext.load_verify_locations()来加载CA证书(尽管我最近没有使用过SSL模块,因此请不要在这一点上说明。)

答案 2 :(得分:0)

该错误表示缺少私钥文件。 在openssl shell中生成密钥对: openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365

启动Python SSL服务器:

from http.server import HTTPServer, 
             SimpleHTTPRequestHandler

import ssl

httpd = HTTPServer(('localhost', 4443), 
                           SimpleHTTPRequestHandler)

httpd.socket = ssl.wrap_socket(httpd.socket, 
                 certfile='/tmp/cert.pem',keyfile='
                           /tmp/key.pem', server_side=True)

httpd.serve_forever()

(我们使用端口4443,以便我可以以普通用户身份运行测试;通常的端口443需要root特权)。

答案 3 :(得分:0)

使用openssl生成受密码保护的自签名证书后,我遇到了类似的问题,并得到以下输出:

ontext.load_cert_chain(certfile= certificate_private, keyfile= certificate)
ssl.SSLError: [SSL] PEM lib (_ssl.c:4012)

在阅读了两次以了​​解load_cert_chain的文档之后,我想到了以下解决方案:

import ssl
    
context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
context.load_cert_chain(certfile= certificate_private, keyfile= certificate_key, password= certificate_password)

connection = http.client.HTTPSConnection(host, port=443, context=context)
connection.request(method="POST", url=request_url, headers=request_headers, body=json.dumps(request_body_dict))
response = connection.getresponse()

证书文件为cert.pem的地方
密钥文件是key.pem
密码是我生成自签名证书时使用的密码,类似于on this answer

答案 4 :(得分:0)

就我而言,此错误表示我的证书具有错误的文件扩展名。我必须使用以下命令将cert.dir文件转换为cert.pem文件:

openssl x509 -inform der -in cert.der -out cert.pem