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

sar*_*gas 29 python ssl ssl-certificate python-3.x 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)
Run Code Online (Sandbox Code Playgroud)

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

jmu*_*sch 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;
 }
Run Code Online (Sandbox Code Playgroud)

它说的是SSL_CTX_check_private_key失败; 因此,私钥不正确.

  • 我以前读过它,但不知道那是什么意思。我认为它正在使用 _openssl_(在 Unix 系统上)并报告它在系统级别得到的错误。这解释了为什么错误会从源代码中的那一行产生,对吗? (2认同)

lar*_*sks 15

在您的代码中,您正在调用:

sslcontext.load_cert_chain(cert, keyfile=ca_cert)
Run Code Online (Sandbox Code Playgroud)

从文档:

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

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

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

...data...
-----END RSA PRIVATE KEY-----
Run Code Online (Sandbox Code Playgroud)

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


Max*_*ner 9

该错误意味着私钥文件丢失。在 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()
Run Code Online (Sandbox Code Playgroud)

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