A Guide to CA, CSR, CRT, and Keys (Digital Certificates)


January 17, 2024, Updated: August 01, 2025

Getting Started

In this post, I will guide you through the concepts of certificates and keys. Following the explanation of these concepts, I will demonstrate how to generate self-signed certificates specifically for deployment purposes. The image below shoes a scenario in which your application requests a Signed Certificate (CRT) from a Certificate Authotity (CA) and then uses the certificate to prove its authenticity to clients.

Certificate Authorities (CA), Certificate Signing Requests (CSR), Certificate (CRT) and public and private keys relation with examples
Illustrative example: An application utilizes its public and private keys to request a signed certificate from a Certificate Authority (CA). The application will then use the signed certificate to prove its authenticity.


Fundamental Concepts

Application Public/Private Keys

Every application needs a public and private key to encript and decrypt its communication. Let’s create a key pair first:

# Generate a private key
openssl genpkey -algorithm RSA -out app_private_key.pem

# The public key can be extracted from private key
openssl rsa -pubout -in app_private_key.pem -out app_public_key.pem

We have the public and private keys for the application. Now, corresponding to step 1, let’s create the Certificate Signing Request (.CSR). Please note that by providing the -addext field, you specify the domain and IP addresses that this request will be valid for.

# Generate the certificate sign request
openssl req -new -key app_private_key.pem -out app_csr.csr \
  -subj "/C=CA/ST=ON/L=Toronto/O=ExampleOrg/OU=IT/CN=example.org/emailAddress=hey@example.org" \
  -addext "subjectAltName=DNS:host.docker.internal,DNS:myapp.local,IP:172.18.0.1,IP:10.30.20.11"

You can also combine all of the above commands into a single one:

openssl req -nodes -newkey rsa:2048 -keyout app_private_key.pem -out app_csr.csr \
  -subj "/C=CA/ST=ON/L=Toronto/O=ExampleOrg/OU=IT/CN=example.org/emailAddress=hey@example.org" \
  -addext "subjectAltName=DNS:host.docker.internal,IP:10.30.20.18,IP:172.18.0.3"

In step 2, we need to send this request to a Certificate Authotiry (CA) to obtain a certificate. A CA is typically a trusted third party, such a the free service provided by certbot. However, we will set up a local self-configured CA for ths purpose of this guide.

CA Public/Private Keys

The CA uses the application’s public key to validate the signed request (step 2). It then employs its private key to encrypt the CSR message (step 3), resulting in the generation of the signed certificate (CRT).

In this process, the CA uses a CA certificate instead of simply using its private key to sign the CSR. The CA certificate helps associate information such as Country, State, Address, etc., of the CA and establishes the chain of trust.

# Generate the private key, the public key 
# can be extracted from private key
openssl genpkey -algorithm RSA -out ca_private_key.pem

# Generate the Self-Signed CA certificate
openssl req -x509 -new -key ca_private_key.pem -days 365 -out ca_certificate.crt \
  -subj "/C=CA/ST=ON/L=Toronto/O=ExampleOrg/OU=IT/CN=example.org/emailAddress=hey@example.org"

# You can extract the public key from either the 
# private key or the ca certificate
# You can extract more information such as adress from ca certificate

You can also combine all of the above commands into a single one:

openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
  -keyout ca_private_key.pem -out ca_certificate.crt \
  -subj "/C=CA/ST=ON/L=Toronto/O=ExampleOrg/OU=IT/CN=example.org/emailAddress=hey@example.org"

Self-Signed Certificate

In step 3 we sign the certificate request and generate the signed certificate (step 4):

# Use CA certificate to sign the CSR
openssl x509 -req -in app_csr.csr \
  -CA ca_certificate.crt \
  -CAkey ca_private_key.pem \
  -CAcreateserial -out app_certificate.crt

Verification

When working with an application, you often deal with these three files:

  • tls.key: The private key of the application, corresponding to app_private_key.pem above
  • tls.crt: The certification issued by the CA, corresponding to app_certificate.crt above
  • ca.crt: The CA certificate, corresponding to ca_certificate.crt above

You can then verify the authenticity of the application certificate tls.crt using:

openssl verify -CAfile ca.crt tls.crt 
# tls.crt: OK

There is another useful tool called mkcert, which simplifies the process even further:

# First, create a directory in which we'll create the certificates
mkdir -p certs

# Export the CAROOT env variable
export CAROOT=$(pwd)/certs

# Install a new CA
# the following command will create 2 files 
# rootCA.pem and rootCA-key.pem
mkcert -install

# Generate SSL certificates
# Here, we're creating certificates valid for both 
# "host.docker.internal" and "172.17.0.1"
mkcert -cert-file=$CAROOT/tls.crt \
  -key-file=$CAROOT/tls.key \
  host.docker.internal 172.17.0.1

That’s it!


Linux Networking Cybersecurity