← ../

create a root certification authority with openssl

** NOTE : to use the elliptic curve ED25519 algorithm (this might cause you problem if you intend to use certificate authentication in the browser) you will need to use the openssl genpkey instead of genrsa with the extra following flags:


create and enter the directory structure

mkdir -p {PKI/CA,PKI/USERS}
cd PKI

create the certification authority

# generate key
openssl genrsa -out CA/ca.key 4096

# generate cert
openssl req -x509 -new -nodes -key CA/ca.key -days 10000 -out CA/ca.pem

create an extension file named "x509v3.cnf" that will be use to pass extra parameters to the certificate via environment variables

CERTIP = 0.0.0.0
CERTFQDN = nohost.nodomain
OCSP = http://ocsp.example.com

[x509v3_extras]
subjectAltName=IP:$ENV::CERTIP
subjectAltName=DNS:$ENV::CERTFQDN
authorityInfoAccess=OCSP;URI:$ENV::OCSP

create a client certificate

#set environment variables
export CERTFQDN=subdomain.example.com
export OCSP=http://ocsp.example.com

#generate client key
openssl genrsa -out USERS/client1.key 4096

#generate client csr
openssl req -sha256 -new -key USERS/client1.key -out USERS/client1.csr

#create the client cert (and sign it with the CA) && create a serial file for the CA to increment the serial number (file CA/ca.srl will be automatically created)
openssl x509 -req -in USERS/client1.csr -CA CA/ca.pem -CAkey CA/ca.key -CAcreateserial -out USERS/client1.pem -days 825 -extfile x509v3.cnf -extensions x509v3_extras

#(optional step) extract the pubkey from the cert (can be use for ipsec vpn pub key auth)
openssl x509 -in USERS/client1.pem -noout -pubkey > USERS/client1.pub

#(optional step) create a bundle(key+cert) and export to pks12 format (can be used for S/MIME signing & encryption in thunderbird)
cat USERS/client1.key USERS/client1.pem > USERS/client1.bundle
openssl pkcs12 -export -in USERS/client1.bundle -out USERS/client1.p12

automating the process with a bash script

the only difference on the subsequent run is that we will use the -CAserial [path/file] instead of the -CAcreateserial command

create the script "create_certs.sh" in the PKI folder :

#!/bin/bash
read -p "enter certificate file name: " CERTNAME
read -p "enter certificate subjectAltName x509v3 extension: " CERTFQDN
read -p "enter authorityInfoAccess (OCSP) x509v3 extension: " OCSP
openssl genrsa -out USERS/${CERTNAME}.key 4096
openssl req -sha256 -new -key USERS/${CERTNAME}.key -out USERS/${CERTNAME}.csr
openssl x509 -req -in USERS/${CERTNAME}.csr -CA CA/ca.pem -CAkey CA/ca.key -CAserial CA/ca.srl -out USERS/${CERTNAME}.pem -days 825 -extfile x509v3.cnf -extensions x509v3_extras
openssl x509 -in USERS/${CERTNAME}.pem -noout -pubkey > USERS/client1.pub
cat USERS/${CERTNAME}.pem USERS/${CERTNAME}.key > USERS/${CERTNAME}.bundle
openssl pkcs12 -export -in USERS/${CERTNAME}.bundle -out USERS/${CERTNAME}.p12

make the script executable and run it

chmod u+x create_certs.sh
./create_certs.sh

extra : create an OCSP responder so people can check the status of a certificate

create an index file:

touch CA/index.txt

create an "openssl.cnf" file with the needed parameters

[ ca ]
default_ca = CA_default

[CA_default]
database = CA/index.txt
default_md = default
basicConstraints = CA:FALSE

[ v3_OCSP ]
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = OCSPSigning

start the server

openssl ocsp -index CA/index.txt -port 8080 -rsigner CA/ca.pem -rkey CA/ca.key -CA CA/ca.pem -text -out log.txt

validate a certificate: (requires a restart from the above server)

openssl ca -config openssl.cnf -keyfile CA/ca.key -cert CA/ca.pem -valid USERS/client2.pem

revoke a certificate: (requires a restart from the above server)

openssl ca -config openssl.cnf -keyfile CA/ca.key -cert CA/ca.pem -revoke USERS/client1.pem

verify the status of a certificate with openssl ocsp command

openssl ocsp -issuer CA/ca.pem -cert USERS/client1.pem -url http://127.0.0.1:8080

side notes:

sources: