Home‎ > ‎Dabbles‎ > ‎RaspberryPi‎ > ‎

RaspberryPi 221 - Implementing an Intermediate Certificate Authority

posted Nov 22, 2015, 2:59 AM by Joshua S   [ updated Nov 30, 2015, 3:00 AM ]
This tutorial will implement an Intermediate Certificate Authority (CA) using the RaspberryPi's builtin OpenSSL framework.  This allows us to create sub-CA's under the authority of the primary CA.  You can do this for many reasons -- perhaps one is for VPN while another is for LDAPS, but more importantly, this allows you to revoke a certificate -- or an entire root certificate -- in the event of compromise while still maintaining the broader web of trust and making restoration of operations much simpler.

To give credit where credit is due; this lesson is based heavily off of this lesson from others.  For a really good overview of the concepts behind CAs and PKI, check out this post.

With any of the Dabbles on this site, if you have questions, suggestions, or thoughts, please feel free to send me an eMail (I'm still working to figure out how to enable comments on Google Sites -- suggestions would be appreciated)!

Supply List:
  • RaspberryPi  The actual RaspberryPi hardware this will all be built around.  In this tutorial, a Raspberry Pi 2 is used and has a memory card with the Raspbian operating system pre-installed.
  • PuTTY SSH Client – PuTTY is a free and open-source terminal emulator, serial console and network file transfer application. It supports several network protocols, including SCP, SSH, Telnet, rlogin, and raw socket connection.  Other SSH tools can be used, but this tutorial will leverage PuTTY.

  • I know I said this guide was going to be comprehensive and not skip any steps, so what better way to start this off than by skipping steps.  I am not writing out instructions for the following (and illustrating from XKCD):
    • Buying a MicroSD Card
    • Buying a RaspberryPi 
    • Finding the IP Address of your Pi
      • This can be done in many ways, including on your router or using an IP scanner such as (AngryIP Scanner or NMAP) -- if there are requests from the "Contact Me" form; I'll look to create a tutorial for this.
    • Obtaining and installing PuTTY
  • Using PuTTY (or the SSH client of your choice) enter the IP Address or DNS Name of the RaspberryPi.
  • If this is the first time you connect, you will get a warning that the RaspberryPi's host key is unknown.  Click "Accept" or "Connect Once" to proceed with the connection.
  • Once connected, log onto the Pi using the credentials you created.  If you have not defined your own credentials, you should, but these are the default credentials:
  • UserID:  pi 
  • Password:  raspberry
  • First things first, in the previous dabble, we created the directories for the primary Certificate Authority (CA).  Now, we need to set up the directory structure, called intermediate, to support Intermediate Certificate Authorities.  Note -- if you have set up an Intermediate Certificate Authority previously using these Dabbles then skip on to the next step and do not attempt to recreate this directory.
sudo mkdir /root/ca/intermediate

  • With the main directory structure for the intermediate CAs created, it is time to create the the intermediate CA that we specifically want to deploy.  In this example, let's call it VPN as we'll plan to use these certificate pairs to deploy a VPN in a later lesson.
sudo mkdir /root/ca/intermediate/VPN

  • we need to create a directory structure to hold all of the files and configurations related to the Certificate Authority (CA).  We'll create subfolders for certscrlnewcerts, and private.  Note, we need to apply fairly restrictive permissions to these directories given the sensitive nature of the CA when the generated certificates are used for Authentication and Authorization.  
sudo mkdir /root/ca/intermediate/VPN/certs
sudo mkdir /root/ca/intermediate/VPN/crl
sudo mkdir /root/ca/intermediate/VPN/csr
sudo mkdir /root/ca/intermediate/VPN/newcerts
sudo mkdir /root/ca/intermediate/VPN/private
sudo chmod 700 /root/ca/intermediate/VPN/private

  • OpenSSL uses the index.txt and serial files as a flat file database.  We need to create both files, and create the serial file with an initial value of 1000 inside the file.
sudo touch /root/ca/intermediate/VPN/index.txt
sudo nano /root/ca/intermediate/VPN/serial

  • Now, we'll copy our OpenSSL configuration file from the root CA into our new intermediate CA.  Most of the options will be the same, so copying the existing configuration will save time and prevent errors in recreating the file.  Once we've copied it over, we'll use nano to edit the contents.  I've attached a sample copy of the configuration file at the end of this lesson.
sudo cp /root/ca/openssl.cnf /root/ca/intermediate/VPN/openssl.cnf
sudo nano /root/ca/intermediate/VPN/openssl.cnf

  • With the file opened for editing, let's change the following lines under the [ CA_default ] section:
    • Note -- while the tutorial I followed had me name each private key, certificate, etc. with the name of the intermediate CA (VPN), in reflection I would likely have left these unchanged or used something like iCA instead to make it very clear that these are part of the intermediate CA and not just an object that it generated.
dir                                  = /root/ca/intermediate/VPN
private_key                          = $dir/private/VPN.key.pem
certificate                          = $dir/certs/VPN.cert.pem
crl                                  = $dir/crl/VPN.crl.pem
policy                               = policy_loose

  • Great work, now that the configuration file is complete, we need to create the intermediate key which will allow us to issue trusted certificates.  It is important that this key pair is closely guarded as a compromise would result in a fundamental compromise of the Public Key Infrastructure (PKI) we are creating with this CA.  We will be protecting it by generating it with AES-256 bit encryption and a strong password and issuing restrictive file level permissions.  Additionally, we'll use a 4096-bit key length within the certificate to safeguard any certificates it generates.
sudo openssl genrsa -aes256 -out /root/ca/intermediate/VPN/private/VPN.key.pem 4096
sudo chmod 400 /root/ca/intermediate/VPN/private/VPN.key.pem

  • With the intermediate key created, we need to create a certificate signing request (CSR).  We'll use the same details as the root CA, but the Common Name will be unique.  Note -- we need to make certain we specify the Intermediate CA configuration file (/root/ca/intermediate/VPN/openssl.cnf) and not the root CA configuration file.  Note, for the Organizational Unit Name and Common Name, ensure this is the name you want to use for the Intermediate Certificate Authority.
sudo openssl req -config /root/ca/intermediate/VPN/openssl.cnf -new -sha256 -key /root/ca/intermediate/VPN/private/VPN.key.pem -out /root/ca/intermediate/VPN/csr/VPN.csr.pem
<Intermediate CA Password (from the previous step)>
<Your CA / Organizational details>
sudo chmod 444 /root/ca/intermediate/VPN/private/VPN.key.pem

  • Good, we have our signing request generated.  Now, we need to create an intermediate certificate using the root CA.  Note -- we need to make certain we specify the root CA configuration file (/root/ca/openssl.cnf) and not the Intermediate CA configuration file.  
sudo openssl ca -config /root/ca/openssl.cnf -extensions v3_intermediate_ca -days 7200 -notext -md sha256 -in /root/ca/intermediate/VPN/csr/VPN.csr.pem -out /root/ca/intermediate/VPN/certs/VPN.cert.pem
<Root CA Password>
sudo chmod 444 /root/ca/intermediate/VPN/certs/VPN.cert.pem

  • Let's make sure the root CA registered the signature process.  To do this, we need to look in the index.txt file of the root CA using the cat command.  Review any entries to ensure our new intermediate CA is listed.
sudo cat /root/ca/index.txt

  • Good -- we know the certificate was signed, now let's check that the details of the cert look correct using OpenSSL.  Validate the details to ensure they align with your inputs.
sudo openssl x509 -noout -text -in /root/ca/intermediate/VPN/certs/VPN.cert.pem

  • OK -- now that we know the details look good, let's validate the intermediate CA cert against the root cert to ensure the chain of trust is intact.  If we get a response of "OK" we know everything worked.
sudo openssl verify -CAfile /root/ca/certs/ca.cert.pem /root/ca/intermediate/VPN/certs/VPN.cert.pem

  • When applications validate certificates, they need to validate the full certificate chain -- including the root certificate.  In our case, this can be done either by installing the root certificate on every client (ideal if you run your own intranet) or by including the root in the chain.  In this example, we'll include the root in the chain because a number of devices (think phones, IP webcams, etc.) do not always allow us to install the root certificate.  So -- let's create our certificate chain with both our intermediate and root certificate like this (note, for some reason this doesn't always work well with sudo, so I sudo su'd to root for these commands):
cat /root/ca/intermediate/VPN/certs/VPN.cert.pem /root/ca/certs/ca.cert.pem > /root/ca/intermediate/VPN/certs/ca-chain.cert.pem
chmod 444 /root/ca/intermediate/VPN/certs/ca-chain.cert.pem

  • Perfect -- just one more step.  We need to generate our Diffie-Hellman parameters.  Some applications will use these to increase the security of the key exchange.  In this step, we'll generate the parameter file, but show later, in the server and client certificate tutorials, how to include these in our certificates.  Generating the parameters is easy -- just issue the below command.  One note, similar to key strength, we'll use 2048 bit strength since this will be used in a key exchange, but you can also use stronger (4096) for better security or weaker (1024) for better performance. 
    • Note -- the process to generate the parameters is very very slow; so be patient.
sudo openssl dhparam -out /root/ca/intermediate/VPN/certs/dh2048.pem 2048
sudo chmod 444 /root/ca/intermediate/VPN/certs/dh2048.pem 

  • Congratulations!  Your Intermediate Certificate Authority is now configured and ready to go!  
Joshua S,
Nov 29, 2015, 5:55 AM