ssl ca authority

OpenSSL is a free, open-source library that you can use for digital certificates. One of the things you can do is build your own CA (Certificate Authority).

A CA is an entity that signs digital certificates. An example of a well-known CA is Verisign. Many websites on the Internet use certificates for their HTTPS connections that were signed by Verisign.

Besides websites and HTTPS, there are some other applications/services that can use digital certificates. For example:

VPNs: instead of using a pre-shared key you can use digital certificates for authentication. Wireless: WPA 2 enterprise uses digital certificates for client authentication and/or server authentication using PEAP or EAP-TLS. Instead of paying companies like Verisign for all your digital certificates. It can be useful to build your own CA for some of your applications. In this lesson, you will learn how to create your own CA.

Configuration

In my examples, I will use a Ubuntu server, the configuration of openSSL will be similar though on other distributions like CentOS.

Prerequisits

  • fqdn
  • ntpd

OpenSSL Configuration

OpenSSL uses a configuration file that is easy to read. There are a couple of things that we will change in it:

vim /usr/lib/ssl/openssl.cnf

Look for the following section:

[ CA_default ]
dir     = ./demoCA

And change it, so it looks like this:

[ CA_default ]                                                                                                                                                                                
dir             = /root/ca

The “/root/ca” folder is where we will store our private keys and certificates.

You might also want to take a look at the default policy:

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

For Dev Lab you should change to something like this

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

CA Time

Switch to root and create the directory structures that we need.

sudo su
mkdir /root/ca
cd /root/ca
mkdir newcerts certs crl private requests

We need 2 Files....

touch index.txt
echo '1234' > serial

Build the root private key

openssl genrsa -aes256 -out private/cakey.pem 4096

We can now use the root private key to create the root certificate

openssl req -new -x509 -key /root/ca/private/cakey.pem -out cacert.pem -days 3650 -set_serial 0

The root certificate will be saved as the “cacert.pem” filename and is valid for 10 years.

Create a certificate

Our root CA is now up and running. Normally when you want to install a certificate on a device (a web server for example), then the device will generate a CSR (Certificate Signing Request). This CSR is created by using the private key of the device.

On our CA, we can then sign the CSR and create a digital certificate for the device.

Another option is that we can do everything on our CA. We can generate a private key, CSR and then sign the certificate…everything “on behalf” of the device.

That’s what I am going to do in this example; it’s a good way to test if your CA is working as expected.

I’ll generate a private key, CSR and certificate for an imaginary “web server”.

Walkthrough

Let’s use the requests folder for this:

cd /root/ca/requests/

Generate a Private Key

openssl genrsa -aes256 -out some_serverkey.pem 2048

With the private key, we can create a CSR:

openssl req -new -key some_serverkey.pem -out some_server.csr

Now we can sign the CSR that we just created:

openssl ca -in some_server.csr -out some_server.pem 

That’s all there is to it. The “some_server.pem” file is the signed digital certificate for our web server. If you want you can delete the CSR, move the private key to the “private” folder, and move the new certificate to the “certs” folder:

#Optional rm some_server.csr
mv some_serverkey.pem /root/ca/private/
mv some_server.pem /root/ca/certs/

Let’s take a closer look at the certificates. We can verify them with OpenSSL, but it might be nice to see them on your computer. I’ll use a Windows computer for this.

Windows doesn’t recognize the .PEM file extension so you might want to rename your certificates to .CRT.

Problems

I regenerated this for wiki.eq.com my test site - and got

failed to update database
TXT_DB error number 2

The reason seems (and it makes sense) the SSL subsystem already knows about the original wiki.eq.com ssl certificate - so it needs to be removed.

I found it in the file

/root/ca/index.txt

Just remove the line from the file - and repeat the steps.

Other Suggestions seem to be

openssl ca -revoke bad_crt_file -keyfile ca_key -cert ca_crt

Verifying

mkdir -p ~/.cert/wiki.eq.com/
$ cd ~/.cert/wiki.eq.com/

Now lets pull the certificate back

openssl s_client -showcerts -connect wiki.eq.com:443

File Extension

Encodings (also used as extensions)

  • .DER
    • The DER extension is used for binary DER encoded certificates. These files may also bear the CER or the CRT extension. Proper English usage would be “I have a DER encoded certificate” not “I have a DER certificate”.
  • .PEM

    • The PEM extension is used for different types of X.509v3 files which contain ASCII (Base64) armored data prefixed with a “—– BEGIN …” line. Common Extensions
  • .CRT

    • The CRT extension is used for certificates. The certificates may be encoded as binary DER or as ASCII PEM. The CER and CRT extensions are nearly synonymous. Most common among *nix systems
  • CER

    • alternate form of .crt (Microsoft Convention) You can use MS to convert .crt to .cer (.both DER encoded .cer, or base64[PEM] encoded .cer) The .cer file extension is also recognized by IE as a command to run a MS cryptoAPI command (specifically rundll32.exe cryptext.dll,CryptExtOpenCER) which displays a dialogue for importing and/or viewing certificate contents.
  • .KEY

    • The KEY extension is used both for public and private PKCS#8 keys. The keys may be encoded as binary DER or as ASCII PEM.

The only time CRT and CER can safely be interchanged is when the encoding type can be identical. (ie PEM encoded CRT = PEM encoded CER)

Script

#!/bin/bash


new() {
    rm -Rf /root/ca
    mkdir /root/ca/
    cd /root/ca
    mkdir newcerts certs crl private requests
    touch index.txt
    echo '1234' > serial
}

ca() {
    COUNTRY="OM"    
    STATE="London"
    LOCATION="London"
    ORG="Al Zadjel, Om"
    COMMON_NAME="X1 Oman CA"    
    COMMON_NAME_INTERMEDIATE="X1 Oman Intermediate CA"  
    COMMON_NAME2="Oman Cert Issuer CA"
        #COMMON_NAME_ORG="*.lvmt.home.ts"   
    COMMON_NAME_ORG=$(hostname -f)      
    OPUNIT="Sw Dev."




    #Generate and self-sign the Root CA
    #===========================================================
    openssl genrsa -out ca.key 2048
    #openssl genrsa -aes256 -out ca.key 4096
    openssl req -new -x509 -days 3650 -key ca.key -subj "/C=$COUNTRY/ST=$STATE/L=$LOCATION/O=$ORG/CN=$COMMON_NAME/OU=$OPUNIT" -out ca.crt

    #===Generate and sign the intermediate CA
    #============================================================
    openssl req -newkey rsa:2048 -nodes -keyout intermediate.key -subj "/C=$COUNTRY/ST=$STATE/L=$LOCATION/O=$COMMON_NAME_INTERMEDIATE/CN=$COMMON_NAME2/OU=$OPUNIT" -out intermediate.csr
    openssl x509 -req -extfile <(printf "subjectAltName=DNS:localhost")  -in intermediate.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out intermediate.crt -days 2000 -sha256


    #===Generate a certificate and sign with the intermediate CA
    #============================================================
    openssl req -newkey rsa:2048 -nodes -keyout server.key -subj "/C=$COUNTRY/ST=$STATE/L=$LOCATION/O=$ORG/CN=$COMMON_NAME_ORG/OU=$OPUNIT" -out server.csr
    openssl x509 -req -extfile <(printf "subjectAltName=DNS:localhost") -days 730 -in server.csr -CA intermediate.crt -CAkey intermediate.key -CAcreateserial -out server.crt


    #===Generate a certificate chain
    #===========================================================
    cat intermediate.crt ca.crt > fullchain.crt
    #===Verify the certificate (CRT) info
    #============================================================
    openssl x509 -in server.crt -text -noout
    #===Verifies the Chain of Trust
    #============================================================
    openssl verify -CAfile ca.crt intermediate.crt
    openssl verify -verbose -CAfile <(cat intermediate.crt ca.crt) server.crt
}

install(){
echo "Moving files to the required Apache directory"
cp server.crt     /etc/ssl/certs/server.crt
cp server.key     /etc/ssl/private/server.key 
cp fullchain.crt  /etc/ssl/certs/fullchain.crt
}

display(){
    openssl x509 -in fullchain.crt -text -noout
}

new
ca
install
service apache2 restart
display

Apache on Ubuntu

  • apt-get install apache2

Modify the /etc/apache2/sites-enabled/000-default.conf to look like this

<VirtualHost 10.208.163.134:443>
    ServerAdmin webmaster@localhost
    DocumentRoot /var/www/html
    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined
    SSLEngine on

    SSLCertificateFile  /etc/ssl/certs/server.crt
    SSLCertificateKeyFile /etc/ssl/private/server.key 
    SSLCertificateChainFile /etc/ssl/certs/fullchain.crt
#SSLCertificateFile server.crt      >> Your public certificate
#SSLCertificateKeyFile server.key   >> Your private key
#SSLCertificateChainFile chain.crt  >> List of intermediate certificates;
#                                 in your case, only one - GoDaddy intermediate CA

</VirtualHost>

Enable the SSL Mods by

cd /etc/apache2/mods-enabled
ln -s ../mods-available/ssl.load ssl.load

Now try it ...

service apache2 restart

Open a Web Browser ... and open https://IP/index.html

I still get a warning that there are errors

This script will - create a new CA - create new certificate - create a new chain - update keys to APache2 - restart apache2 - register the ca as trusted !!

Use with caution

#!/bin/bash


new() {
    rm -Rf /root/ca
    mkdir /root/ca/
    cd /root/ca
    mkdir newcerts certs crl private requests
    touch index.txt
    echo '1234' > serial
}

cadir () {
cd /root/ca
}

buildCaCnf() {
    cat << EOF > ca.cnf
    [req]
    default_bits = 2048
    prompt = no
    default_md = sha256
    distinguished_name = dn

    [dn]
    C=${COUNTRY}
    ST=${STATE}
    L=${LOCATION}
    O=${CAORG}
    OU=${CAOPUNIT}
    CN=${CACOMMON_NAME}
    emailAddress=${emailAddress}

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

buildIntCnf() {
    cat << EOF > int.cnf
    [req]
    default_bits = 2048
    prompt = no
    default_md = sha256
    distinguished_name = dn

    [dn]
    C=${INTCOUNTRY}
    ST=${INTSTATE}
    L=${INTLOCATION}
    O=${INTORG}
    OU=${INTOPUNIT}
    CN=${INTCOMMON_NAME}
    emailAddress=${INTemailAddress}
    subjectAltName=$(hostname -f)

    [ v3_intermediate_ca ]
    subjectKeyIdentifier = hash
    authorityKeyIdentifier = keyid:always,issuer
    #basicConstraints = critical, CA:true, pathlen:0
    #keyUsage = critical, digitalSignature, cRLSign, keyCertSign
EOF
}

buildCertCnf() {
    cat << EOF > cert.cnf
    [req]
    default_bits = 2048
    prompt = no
    default_md = sha256
    distinguished_name = dn

    [dn]
    C=${COUNTRY}
    ST=${STATE}
    L=${LOCATION}
    O=${ORG}
    OU=${OPUNIT}
    CN=${COMMON_NAME}
    emailAddress=${emailAddress}
    subjectAltName=$(hostname -f)

    [SAN]
    subjectAltName=$(hostname -f)

EOF
}

ca() {
    COUNTRY="OM"
    INTCOUNTRY="OM" 
    STATE="London" && INTSTATE=$STATE
    LOCATION="London" && INTLOCATION=$LOCATION
    ORG="Al Zadjel, Om" && INTORG="INT Issuing Org"
    CAORG="CA Oman Natl Post Office"
        COMMON_NAME="X1 Oman CA"    
        INTCOMMON_NAME="X1 Oman Intermediate CA"    
    CACOMMON_NAME="Oman Cert Issuer CA"
        #COMMON_NAME_ORG="*.lvmt.home.ts"   
    COMMON_NAME_ORG=$(hostname -f)      
    OPUNIT="Sw Dev."
        CAOPUNIT="National Certification issuing Unit"
    INTOPUNIT="Cert Issuing Department"
    emailAddress="Bob123@gmail.com"
    INTemailAddress="intemail@intagency.net.om"


    cadir
        buildCaCnf  


    #Generate and self-sign the Root CA
    #===========================================================
    openssl genrsa -out ca.key 2048
    openssl req -new -x509 -days 3650 -key ca.key -config <(cat ca.cnf) -out ca.crt 
}

ca2() {

    buildIntCnf
    #===Generate and sign the intermediate CA
    #============================================================
    openssl req -newkey rsa:2048 -nodes -keyout intermediate.key -config <(cat int.cnf) -out intermediate.csr
    openssl x509 -req -extfile <(printf "subjectAltName=DNS:10.208.163.134")  -in intermediate.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out intermediate.crt -days 2000 -sha256  

        buildCertCnf
    #===Generate a certificate and sign with the intermediate CA
    #============================================================
    openssl req -newkey rsa:2048 -nodes -keyout server.key -config <(cat cert.cnf) -out server.csr 

    openssl x509 -req -extfile <(printf "subjectAltName=DNS:10.208.163.134") -days 730 -in server.csr -CA intermediate.crt -CAkey intermediate.key -CAcreateserial -out server.crt
}


ca3() {
    #===Generate a certificate chain
    #===========================================================
    cat intermediate.crt ca.crt > fullchain.crt
    #===Verify the certificate (CRT) info
    #============================================================
    openssl x509 -in server.crt -text -noout
    #===Verifies the Chain of Trust
    #============================================================
    openssl verify -CAfile ca.crt intermediate.crt
    openssl verify -verbose -CAfile <(cat intermediate.crt ca.crt) server.crt
}

install(){
echo "Moving files to the required Apache directory"
cp server.crt     /etc/ssl/certs/server.crt
cp server.key     /etc/ssl/private/server.key 
cp fullchain.crt  /etc/ssl/certs/fullchain.crt
}

display(){
    openssl x509 -in fullchain.crt -text -noout
}





cert() {
echo | openssl s_client -connect 10.208.163.134:443 2>/dev/null | openssl x509 > /usr/local/share/ca-certificates/10.208.134.443.crt
cp ca.crt /usr/share/ca-certificates
#dpkg-reconfigure ca-certificates
update-ca-certificates
}

new
ca
cert
ca2
ca3
install
service apache2 restart
#display