Self-signed Certificates Made Simple

Learn how to create a self-signed certificate to add a security layer to your local communications or test/development environments.

Hey listen… A self-signed certificate is a digital certificate NOT signed by a recognized public or private certificate authority (CA). Instead, it is signed by the same entity using the certificate also known as myself. Self-signed certificates are commonly used for testing or securing communication within a private network.

Create a self-signed certificate is a relatively simple task, and can be done using OpenSSL, a widely used open-source cryptographic tool/library.

Here is a simple guide on how to create a self-signed certificate and I will follow these steps:

  • Install required tools
  • Create your own CA
  • Create a private key to generate the CSR
  • Create a certificate with the CSR, the CA and the private key
  • Using the self-signed certificate

I’m using Ubuntu Linux 20.04 to generate a certificate but the commands should be similar for other Linux distributions.

If you don’t have OpenSSL installed, use apt, yum, rpm, source code or whatever to install it.

On Ubuntu and Debian alike systems, you can install it with the following:

sudo apt install openssl -y

Now create a directory to put your files to be generated with the command:

mkdir mycertificate && cd mycertificate

Before generating a certificate, you’ll need your own CA (Certificate Authority) to sign it, as said before. Use this command to generate the CA:

openssl req -x509 \
-sha256 -days 3560 \
-nodes \
-newkey rsa:2048 \
-subj "/CN=my.domain.com/C=BR/ST=Bahia/L=Salvador" \
-keyout CA.key -out CA.crt

This command will generate a CA certificate and its private key valid for 10 years. You should change the command to fit your needs. Here are the meanings: CN (common name), C (country name), ST (state or province name) and L (locality).

The next step is to generate a private key using the following command:

openssl genrsa -out server.key 2048

Now we create a CSR (Certificate Signing Request). But to create a CSR we will write a configuration file:

cat > csr.conf <<EOF
[ req ]
default_bits = 2048
prompt = no
default_md = sha256
req_extensions = req_ext
distinguished_name = dn

[ dn ]
C = BR
ST = Bahia
L = Salvador
O = MyOrganization
OU = MyOrganization Unit
CN = my.domain.com

[ req_ext ]
subjectAltName = @alt_names

[ alt_names ]
DNS.1 = my.domain.com
DNS.2 = www.my.domain.com
IP.1 = 192.168.0.254
IP.2 = 192.168.0.253

EOF

Now run this command to generate the CSR:

openssl req -new \
-key server.key \
-config csr.conf \
-out server.csr

This will create a new CSR file named server.csr in the current directory. If you omit the option -config csr.conf, you will be prompted to enter some information about the certificate, such as the country, state, and organization name.

You should have these files in your directory: CA.key, CA.crt, csr.conf, server.csr and server.key.

Now let’s create another configuration file for the final certificate:

cat > cert.conf <<EOF

authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = @alt_names

[alt_names]
DNS.1 = my.domain.com

EOF

To generate the certificate run this command:

openssl x509 -req \
-in server.csr \
-CA CA.crt -CAkey CA.key \
-CAcreateserial -out server.crt \
-days 3650 \
-sha256 -extfile cert.conf

The command should generate a file named server.crt and it should be used with the previously generated key. The -days option specifies the number of days the certificate will be valid.

Example of use with nginx:

server {
    listen 443 ssl;
    server_name my.domain.com www.my.domain.com;

    ssl_certificate /path/to/mycertificate/server.crt;
    ssl_certificate_key /path/to/mycertificate/server.key;
    
    location / {
        root /var/www/html/my.domain.com/;
        index index.html;
    }
}

After generating the self-signed certificate, you can use it to secure communication between two entities. However, it’s worth noting that web browsers or operating systems do not trust self-signed certificates by default. This means that if you use a self-signed certificate on a public website, visitors will see a warning message in their browser.

If you want to use this certificate on a group of LAN computers, you could add the CA to the trust list of the operating system.

On Ubuntu, you can run these commands:

cp CA.crt /usr/local/share/ca-certificates/my.ca.entity/CA.pem
sudo update-ca-certificates

This will copy the CA to /usr/local/share/ca-certificates/CA_FOLDER_NAME and create links to the trusted CA folder with update-ca-certificates. So next time you browse the example site, chrome will not complain about a “not trusted” certificate.