Overview
- Intro
- Checking if OpenSSL is already installed
- Installing OpenSSL in Linux
- Installing OpenSSL in Windows
- Generate a private RSA key
- Generate certificate signing request (CSR) with the key
- Sign the certificate signing request with the key
- View certificate details
- Removing a passphrase from a private key
- Single command to generate a key and certificate
- Python script to run HTTPS server
Intro
This tutorial will walk through the process of creating your own self-signed certificate. You can use this to secure network communication using the SSL/TLS protocol. For example, to run an HTTPS server. If you don't need self-signed certificates and want trusted signed certificates, check out my LetsEncrypt SSL Tutorial for a walkthrough of how to get free signed certificates.
Self-signed certificates are convenient when developing locally, but I don't recommend them for production environments. If you want to run a public website, getting a trusted signed certificate can be a better option. With a self-signed certificate, users will get a warning on their first visit to your site that is using an untrusted certificate. You can purchase one from somewhere like GoDaddy or you can get a free certificate with Let's Encrypt. If you just need a self-signed cert for personal use or testing, continue and learn how to sign your own certificate.
OpenSSL is the tool used in this tutorial. Learn more about OpenSSL at https://www.openssl.org/.
The two important files you will need when this is all done is the private key file and the signed certificate file. Those two files are required when setting up an SSL/TLS server. The private key should always be kept secret.
Generating a self signed certificate consists of a few steps:
- Generate a private RSA key
- Generate certificate signing request (CSR) with the key
- Sign the certificate signing request with the key
If you already have a private key, you could skip the first step. Next, we will look at the commands to perform each action individually. At the end, we will see one command that can do everything in a single step.
Checking if OpenSSL is already installed
You will need openssl installed to run these commands. To check if it's installed already try this in your command prompt:
openssl version
If you get a version number then you have it installed. If you get an error saying unrecognized command, you will need to install it. Mac computers should already have it installed, but you could use brew to install a newer version.
Installing OpenSSL in Linux
Chances are openssl is already installed in Linux. If not, you can install it using your distributions package manager. For example like this in Debian/Ubuntu based distributions:
sudo apt-get install openssl
You can also download the source from https://www.openssl.org/.
Installing OpenSSL in Windows
For Windows, check out http://gnuwin32.sourceforge.net/packages/openssl.htm to download the GPG binaries. You might need to update your PATH environment variable to point to the new openssl/bin directory, if you get a message about openssl not being a recognized command.
If you get an error regarding the config file when running openssl on Windows like this:
Unable to load config info from /usr/local/ssl/openssl.cnf
Then you will need to set the environment variable OPENSSL_CONF to the path of the default (or your own custom) openssl.cnf file. If you installed openssl to C:\opt\openssl then you would set it like this:
set OPENSSL_CONF=C:\opt\openssl\share\openssl.cnf
Generate a private RSA key
You can generate your private key with or without a passphrase to protect it. You only need to choose one of these options. This will generate a 2048-bit RSA private key.
# Generate 2048 bit RSA private key (no passphrase)
openssl genrsa -out privkey.pem 2048
# To add a passphrase when generating the private key
# include a cipher flag like -aes256 or -des3
openssl genrsa -aes256 -out privkey.pem 2048
Generate certificate signing request (CSR) with the key
Using the private key generated in the previous step, we need to create a certificate signing request. You can generate the certificate signing request with an interactive prompt or by providing the extra certificate information in the command line arguments. You only need to choose one of these options.
# Generate certificate signing request (CSR)
openssl req -new -key privkey.pem -out signreq.csr
# To avoid the interactive prompt and fill out the information in the command, you can add this
openssl req -new -key privkey.pem -out signreq.csr -subj "/C=US/ST=NRW/L=Earth/O=CompanyName/OU=IT/CN=www.example.com/emailAddress=email@example.com"
Sign the certificate signing request with the key
The last step in the process is to sign the request using a private key. In this example we are signing the certificate request with the same key that was used to create it. That's why it earns the name "self-signed".
# Sign the certificate signing request
openssl x509 -req -days 365 -in signreq.csr -signkey privkey.pem -out certificate.pem
View certificate details
To view the details of a certificate and verify the information, you can use the following command:
# Review a certificate
openssl x509 -text -noout -in certificate.pem
Removing a passphrase from a private key
If you have a private key that is protected with a passphrase and you want to create a copy that has no passphrase on it, you can do it like this:
# If a private key has a passphrase, remove it.
# Will be prompted to enter the passphrase
openssl rsa -in server.key -out server-nopassphrase.key
Single command to generate a key and certificate
Earlier we covered the steps involved with creating a self-signed cert: generating a key, creating a certificate signing request, and signing the request with the same key. It is important to understand that process, but there is a more convenient way achieve the same goal in one step without creating the intermediary certificate signing request file.
openssl req -newkey rsa:2048 -nodes -keyout privkey.pem -x509 -days 36500 -out certificate.pem
If you want to passphrase the private key generated in the command above, omit the -nodes (read: "no DES") so it will not ask for a passphrase to encrypt the key.
Just like before, you can add the subject information to the certificate in the command and avoid the interactive prompt.
openssl req -newkey rsa:2048 -nodes -keyout privkey.pem -x509 -days 36500 -out certificate.pem -subj "/C=US/ST=NRW/L=Earth/O=CompanyName/OU=IT/CN=www.example.com/emailAddress=email@example.com"
# Same thing but in different formatting
openssl \
req \
-newkey rsa:2048 -nodes \
-keyout privkey.pem \
-x509 -days 36500 -out certificate.pem \
-subj "/C=US/ST=NRW/L=Earth/O=CompanyName/OU=IT/CN=www.example.com/emailAddress=email@example.com"
Python script to run HTTPS server
The code below demonstrates how to run a simple HTTPS server using the key and certificate you just created. Running the script will start up a web server that serves your current directory. Use curl or a web browser to
If you want to learn how to work with cryptography and certificates with Go, check out my book Security with Go. It dedicates an entire chapter to hashing, symettric and asymmetric encryption, certificates, and practical applications. Modify the settings at the top before running.
#!/usr/bin/python
# Sets up an HTTPS server that serves directory contents
import sys
import ssl
# Settings
listen_target = ('localhost', 9999) # https://localhost:9999/
certificate_file = './certificate.pem'
private_key_file = './privkey.pem'
# Python 3 version
if sys.version_info[0] == 3:
import http.server
httpd = http.server.HTTPServer(listen_target, http.server.SimpleHTTPRequestHandler)
# Python 2 version
elif sys.version_info[0] == 2:
import BaseHTTPServer, SimpleHTTPServer
httpd = BaseHTTPServer.HTTPServer(listen_target, SimpleHTTPServer.SimpleHTTPRequestHandler)
# Wrap the socket with SSL
httpd.socket = ssl.wrap_socket(httpd.socket,
certfile=certificate_file, keyfile=private_key_file, server_side=True)
# Start listening
httpd.serve_forever()