Creating a Simple Certification Authority Using Bash Script and OpenSSL

  ·   3 min read

In today’s digital landscape, securing communications and data integrity is paramount. One of the foundational elements of this security is the use of certificates, which are often issued by a Certification Authority (CA). While there are many commercial and open-source CAs available, sometimes you need a simple, custom solution for internal use or testing purposes. In this article, we’ll explore how to create a simple CA using a Bash script and OpenSSL, a robust open-source toolkit for SSL/TLS.

Prerequisites

Before we begin, ensure you have the following:

  1. A Unix-like operating system (Linux, macOS, etc.)
  2. OpenSSL installed (version 1.1.1 or later is recommended)
  3. Basic knowledge of Bash scripting

Step-by-Step Guide

Step 1: Set Up the Directory Structure

First, create a directory structure to store your CA files:

mkdir -p ~/myCA/{certs,crl,newcerts,private}
chmod 700 ~/myCA/private
touch ~/myCA/index.txt
echo 1000 > ~/myCA/serial

This structure will help organize your CA’s certificates, private keys, and other necessary files.

Step 2: Create the OpenSSL Configuration File

Create an openssl.cnf file in the ~/myCA directory with the following content:

[ ca ]
default_ca = CA_default

[ CA_default ]
dir               = ~/myCA
certs             = $dir/certs
crl_dir           = $dir/crl
new_certs_dir     = $dir/newcerts
database          = $dir/index.txt
serial            = $dir/serial
RANDFILE          = $dir/private/.rand

private_key       = $dir/private/ca.key.pem
certificate       = $dir/certs/ca.cert.pem

crlnumber         = $dir/crlnumber
crl               = $dir/crl.pem
crl_extensions    = crl_ext
default_crl_days  = 30

default_md        = sha256

name_opt          = ca_default
cert_opt          = ca_default
default_days      = 375
preserve          = no
policy            = policy_strict

[ policy_strict ]
countryName             = match
stateOrProvinceName     = match
organizationName        = match
organizationalUnitName  = optional
commonName              = supplied
emailAddress            = optional

[ req ]
default_bits        = 2048
distinguished_name  = req_distinguished_name
string_mask         = utf8only

default_md          = sha256

[ req_distinguished_name ]
countryName                     = Country Name (2 letter code)
stateOrProvinceName             = State or Province Name
localityName                    = Locality Name
0.organizationName              = Organization Name
organizationalUnitName          = Organizational Unit Name
commonName                      = Common Name
emailAddress                    = Email Address

[ v3_ca ]
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical, CA:true
keyUsage = critical, digitalSignature, cRLSign, keyCertSign

[ crl_ext ]
authorityKeyIdentifier=keyid:always

Step 3: Generate the CA’s Private Key and Certificate

Run the following commands to generate the CA’s private key and self-signed certificate:

openssl genrsa -aes256 -out ~/myCA/private/ca.key.pem 4096
chmod 400 ~/myCA/private/ca.key.pem

openssl req -config ~/myCA/openssl.cnf \
      -key ~/myCA/private/ca.key.pem \
      -new -x509 -days 7300 -sha256 -extensions v3_ca \
      -out ~/myCA/certs/ca.cert.pem
chmod 444 ~/myCA/certs/ca.cert.pem

You’ll be prompted to enter information for the certificate’s distinguished name (DN). Ensure that the information matches the policy defined in the openssl.cnf file.

Step 4: Create a Bash Script for Automation

To streamline the process of issuing certificates, create a Bash script named issue_cert.sh:

#!/bin/bash

if [ "$#" -ne 1 ]; then
    echo "Usage: $0 <common_name>"
    exit 1
fi

COMMON_NAME=$1

openssl genrsa -out ~/myCA/private/$COMMON_NAME.key.pem 2048
chmod 400 ~/myCA/private/$COMMON_NAME.key.pem

openssl req -config ~/myCA/openssl.cnf \
      -key ~/myCA/private/$COMMON_NAME.key.pem \
      -new -sha256 -out ~/myCA/csr/$COMMON_NAME.csr.pem \
      -subj "/C=US/ST=State/L=Locality/O=Organization/CN=$COMMON_NAME"

openssl ca -config ~/myCA/openssl.cnf \
      -extensions server_cert -days 375 -notext -md sha256 \
      -in ~/myCA/csr/$COMMON_NAME.csr.pem \
      -out ~/myCA/certs/$COMMON_NAME.cert.pem
chmod 444 ~/myCA/certs/$COMMON_NAME.cert.pem

Make the script executable:

chmod +x issue_cert.sh

Step 5: Issue a Certificate

To issue a certificate for a specific common name, run the script:

./issue_cert.sh example.com

This will generate a private key and a signed certificate for example.com.

Conclusion

You’ve now set up a simple Certification Authority using a Bash script and OpenSSL. This setup is suitable for internal use, testing, or educational purposes. For production environments, consider using more robust solutions like Let’s Encrypt or other established CAs.

References