Creating an offline certificate authority using OpenSSL and Creating trust with Group Policy

Build the system:

I use centos6 minimal CD.
I created an encrypted physical LVM to encompass /, /home, and the swap as described previously.
There is some hardening addition hardening that you can do later.

Offline vs. Online:

Due to the nature of what one can do with the power of a trusted CA, I am not a fan of online CAs. Others think that offline CAs an ancient idea.

I’m not going to become a victim of an argument focusing on how systems and active directory aren’t secure if someone can access your GPOs and push out trusted CAs to your clients; kerberos key distribution is already online; and what about AD in general… that has to be online, doesn’t it?

Offline === Offline. What’s the best risk reduction procedure? If something doesn’t exist then there is no risk. So just focus on physical security of the system, and the physical security of the CA private key and you are good to go!


Harden the install:
You may choose to do this before or after you have finished setting up the CA. The main purpose of this is to make sure that your private key is very secure.

Restrict root logons by physical console only:

echo "tty1" > /etc/securetty
chmod 700 /root

Set a logout timeout of one minutes:

echo "TMOUT=60" >> /etc/bashrc
echo "readonly TMOUT &> /dev/null" >> /etc/bashrc
echo "export TMOUT &> /dev/null" >> /etc/bashrc

Clear command history on logout:

echo "echo > ~/.bash_history" >> /etc/bash.bash_logout
echo "history -c" >> /etc/bash.bash_logout

Configure the CA directory structure and some configuration files:

mkdir -m 0700 /root/ca /root/ca/certs /root/ca/crl /root/ca/newcerts /root/ca/private
touch /root/ca/index.txt
echo 00 > /root/ca/crlnumber
echo 1000 > /root/ca/serial
sed s@"/etc/pki/CA"@"/root/ca"@g -i /etc/pki/tls/openssl.cnf
sed s@"$dir/crl.pem"@"$dir/crl/crl.pem"@g -i /etc/pki/tls/openssl.cnf
echo "crlDistributionPoints=URI:http://CRLSERVER/janus.crl" > /root/ca/opensslx509.conf

Generate the Root CA certificate/key pair:
The first step is to generate a private key and the public key. “Key” is synonymous with certificate.

openssl genrsa -des3 -out /root/ca/private/cakey.pem 4096
chmod 400 /root/ca/private/cakey.pem
openssl req -new -x509 -extensions v3_ca -key /root/ca/private/cakey.pem -out /root/ca/cacert.pem -days 3650 #ten year long Root CA public certificate

Securely backup /root/ca/private/cakey.pem. As in, guard it with your life. This is the stamp-of-approval for all certificates you are signing going forward. Some people store this on encrypted media, like a removable USB thumbdrive that is itself encrypted.

Creating a CRL distribution point:

One of the problems I came across when researching this implementation was that most of the technical write ups are not clear about a very important point, distributing the certificate revocation list. So, I will discuss CRLs and configuring a CRL distribution point before we generate our CA certificates.

If you were to roll out a CA on Windows server, you would see that there are two CRL distribution points:

One that’s served within the Active Directory LDAP, and is an octet string value (aka hex):


The other is via an HTTP URL:


I will simply be using HTTP and be presenting the CRL via a URL as http://CRLSERVER/ca.crl.
If you do not have an HTTP server, please configure one, or use `openssl s_server` (but not on this box, since it’s offline). It’s worth noting that it is up to the clients to check the CRL as they wish, but they hopefully will all time and the complete URI of your CRL should always be accessible. If the original server goes away, no worries; just use a CNAME and/or filter on HTTP HEADER content or some other magic. Just make sure that the CRL is available at the path you’ve described.
Note that the CRL is public knowledge and doesn’t need to be secured (not that I’m implying that the web server doesn’t, just the file itself).

We will be creating a very simple config file for use with the `openssl x509 -extfile` parameter.

echo "crlDistributionPoints=URI:http://CRLSERVER/ca.crl" > /root/ca/opensslx509.conf

Copy the public certificate to a DC to distribute via GPO:

1) Copy the /root/ca/certs/ca.cer or the contents to a DC.
2) Open gpmc.msc and navigate to:

Computer Configuration/Policies/Windows Settings/Security Settings/Public Key Policies/Trusted Root Certification Authorities

3) Right-click and import ca.cer into “Trusted Root Certification Authorities.” This will push the CA to the local stores of any target clients.

Sign a certificate request (producing a certificate which includes the CRL):

openssl ca -days 3650 -extfile /root/ca/opensslx509.conf -out /root/ca/certs/therequestorscert.cer -in ~/therequest.csr

Do not delete generated certificates from your server. Copy them to the destination.

Revoke a certificate and create a new CRL:
In order to maintain a proper CRL, all the issued certs should remain on your server.

openssl ca -revoke /root/ca/certs/therequestorscert.cer -keyfile /ca/private/cakey.pem -cert /root/ca/certs/ca.cer #revoke the certificate
if [[ $(cat /root/ca/crlnumber) =~ ^[0-9]+$ ]]; then export crlvernumber=$(/root/ca/crlnumber); fi # /root/ca/crlnumber contains the version of the CRL
openssl ca -gencrl -crl_reason [unspecified, keyCompromise, CACompromise, affiliationChanged, superseded, cessationOfOperation, certificateHold, removeFromCRL] -keyfile /root/ca/private/cakey.pem -cert /root/ca/certs/ca.cer > /root/ca/crl/crl.$(/root/ca/crlnumber)
if [[ $(cat /root/ca/crlnumber) =~ ^[0-9]+$ ]]; then echo $(($(cat /root/ca/crlnumber)+1)); else cat /root/ca/crlnumber; fi > /root/ca/crlnumber #increments /root/ca/crlnumber after to process as to avoid writing older CRLs

You can then copy the crl to the location issued within all the certificates: http://CRLSERVER/ca.crl
For more CRL generation settings, see the man page.


  1. No comments yet.
  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: