3
votes

I am trying to figure out how to setup a SSL link using the Python library Twisted. I have managed to create a certificate that works on the server side, but I am totally stuck when it comes to the client side.

The example from the twisted website states:

The following examples rely on the files server.pem (private key and self-signed certificate together) and public.pem (the server’s public certificate by itself).

I have generated myself a certificate and key using OpenSSL:

# Generate Private Key:
openssl genrsa -des3 -out certs/server.key 2048

# Generate Certificate Signing Request:
openssl req -new -key certs/server.key -sha256 -out certs/server.csr

# Generate a Self-Signed Certificate:
openssl x509 -req -days 365 -in certs/server.csr -signkey certs/server.key -sha256 -out certs/server.crt

# Convert the CRT to PEM format:
openssl x509 -in certs/server.crt -out certs/server.pem -outform PEM

For the server-side I am combining certs/server.crt and certs/server.key to create server.pem and trying to use server.crt for public.

When I try and run my test program using:

certificate = ssl.PrivateCertificate.loadPEM(certData)

I get an error about not starting line. Which certificate should I be using for the client if it's not server.crt please?

2

2 Answers

3
votes

In case you want to have certificate based authentication for the clients as well:

I had that issue some time ago and wrote a blog post about my solution. It also contains a guide to create certificates and sign them with an own certificate authority. You can find the python example code at GitHub.

It uses Twisted for a simple JSONRPCServer with certificate based authentication for both, server as well as for the clients.

The main thing is to define an own AltCtxFactory for the clients:

# Use our own context factory to use our certificate to authenticate
# against the server and ensure that we are using a strong SSL/TLS
# encryption method
class AltCtxFactory(ssl.ClientContextFactory):
    def getContext(self):
        # Used TLS/SSL encryption method
        sslMethod = SSL.TLSv1_2_METHOD
        # Clients private Key, used for authentication
        privKey = "<PATH TO YOUR PRIVATE KEY>"
        # Clients certificate, used for authentication
        certificate = "<PATH TO YOUR CERTIFICATE>"
        # Our trusted Certificate Authority for server connections
        accepted_ca = "<PATH TO YOUR ACCEPTED CERTIFICATE AUTHORITY>"

        self.method = sslMethod
        ctx = ssl.ClientContextFactory.getContext(self)
        # Ensure that we verify server's certificate and use our own
        # verifyCallback method to get further details of invalid certificates
        ctx.set_verify(SSL.VERIFY_PEER | SSL.VERIFY_FAIL_IF_NO_PEER_CERT,
                   verifyCallback)
        # Ensure that we only trust our CA
        ctx.load_verify_locations(accepted_ca)
        # Use our own Callback mehtod if a password is needed to decrypt our
        # private key
        ctx.set_passwd_cb(password_cb)
        # Use our certificate for authentication against server
        ctx.use_certificate_file(certificate)
        # Use our private key for authentication against server
        ctx.use_privatekey_file(privKey)
        return ctx

Feel free to use the code in your projects.

2
votes

When I try and run my test program using:

certificate = ssl.PrivateCertificate.loadPEM(certData) I get an error about not starting line. Which certificate should I be using for the client if it's not server.crt please?

This should be ssl.Certificate.LoadPEM(certData) if you look at the example on the Twisted howto page.