Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What does "SSLError: [SSL] PEM lib (_ssl.c:2532)" mean using the Python ssl library?

I am trying to use connect to another party using Python 3 asyncio module and get this error:

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

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

The question is just what the error mean. My certificate is correct, the keyfile (CA certificate) might not.

like image 643
sargas Avatar asked May 07 '15 18:05

sargas


4 Answers

Assuming that version 3.6 is being used:

See: https://github.com/python/cpython/blob/3.6/Modules/_ssl.c#L3523-L3534

 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;
 }

What it is saying is that SSL_CTX_check_private_key failed; thus, the private key is not correct.

Reference to the likely version:

  • https://github.com/python/cpython/blob/3.4/Modules/_ssl.c#L2529-L2535
like image 163
jmunsch Avatar answered Nov 16 '22 16:11

jmunsch


In your code, you are calling:

sslcontext.load_cert_chain(cert, keyfile=ca_cert)

From the documentation:

Load a private key and the corresponding certificate. The certfile string must be the path to a single file in PEM format containing the certificate as well as any number of CA certificates needed to establish the certificate’s authenticity. The keyfile string, if present, must point to a file containing the private key in. Otherwise the private key will be taken from certfile as well. See the discussion of Certificates for more information on how the certificate is stored in the certfile.

Based on the name of the arguments in your example, it looks like you are passing a CA certificate to the keyfile argument. That is incorrect, you need to pass in the private key that was used to generate your local certificate (otherwise the client cannot use your certificate). A private key file will look something like:

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

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

You only need the CA certificate if you are trying to verify the validity of SSL certificates that have been signed by this certificate. In that case, you would probably use SSLContext.load_verify_locations() to load the CA certificate (although I have not worked with the SSL module recently, so don't take my word on that point).

like image 39
larsks Avatar answered Nov 16 '22 15:11

larsks


The error means a private key file is missing. Generate a key pair in openssl shell: openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365

Start Python SSL Server:

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()

(We use port 4443 so that I can run the tests as normal user; the usual port 443 requires root privileges).

like image 6
Max Kleiner Avatar answered Nov 16 '22 17:11

Max Kleiner


In my case, this error meant that my certificate had the wrong file extension. I had to convert my cert.der file to a cert.pem file using the below:

openssl x509 -inform der -in cert.der -out cert.pem 
like image 3
Pelonomi Moiloa Avatar answered Nov 16 '22 16:11

Pelonomi Moiloa