Debianhelp.co.uk

C   Creating self signed SSL Certificates Using Openssl

     Requirements apache2, openssl and libapache-mod-ssl

      For apache2 installation Click here 

       Install openssl and libapache-mod-ssl 

       apt-get install  openssl  

libapache-mod-ssl

Staring Setup

First, we will create a directory where we can work. It does not matter where this is; I am arbitrarily going to create it in my home directory.

 mkdir certificate
 cd certificate
mkdir newcerts private

 The certificate directory will contain:

Our Certificate Authority (CA) certificate

The database of the certificates that we have signed

The keys, requests, and certificates we generate

It will also be our working directory when creating or signing certificates.

The certificates/newcerts directory will contain:

A copy of each certificate we sign

The Certificate/private directory will contain:

Our Certificate private key

This key is important:

Do not lose this key. Without it, you will not be able to sign or renew any certificates.

Do not disclose this key to anyone 

Our next step is to create a database for the certificates we will sign:

 echo '01' > serialno
 touch mainindex.txt

Rather than use the configuration file that comes with OpenSSL, we are going to create a minimal configuration of our own in this directory. Start your editor (vi, nano, ...) and create a basic openssl.cnf:

#
# OpenSSL configuration file.
#
# Establish working directory.
dir = .

Creating a Root Certificate

With OpenSSL, a large part of what goes into a certificate depends on the contents of the configuration file, rather than the command line. This is a good thing, because there is a lot to specify.

The configuration file is divided into sections, which are selectively read and processed according to openssl command line arguments. Sections can include one or more other sections by referring to them, which helps to make the configuration file more modular. A name in square brackets (e.g. " req ") starts each section.

We now need to add the section that controls how certificates are created, and a section to define the type of certificate to create.

The first thing we need to specify is the Distinguished Name. This is the text that identifies the owner of the certificate when it is viewed. It is not directly referenced in the configuration file, but is included into the section processed when certificate requests are created. The command is "openssl req ", so the section is titled req .

Add the following to openssl.cnf:

[ req ]
default_bits = 1024 # Size of keys
default_keyfile = key.pem # name of generated keys
default_md = md5 # message digest algorithm
string_mask = nombstr # permitted characters
distinguished_name = req_distinguished_name

[ req_distinguished_name ]
# Variable name   Prompt string
#----------------------   ----------------------------------
0.organizationName = Organization Name (company)
organizationalUnitName = Organizational Unit Name (department, division)
emailAddress = Email Address
emailAddress_max = 40
localityName = Locality Name (city, district)
stateOrProvinceName = State or Province Name (full name)
countryName = Country Name (2 letter code)
countryName_min = 2
countryName_max = 2
commonName = Common Name (hostname, IP, or your name)
commonName_max = 64

# Default values for the above, for consistency and less typing.
# Variable name   Value
#------------------------------   ------------------------------
0.organizationName_default = The Sample Company
localityName_default = Metropolis
stateOrProvinceName_default = New York
countryName_default = US

[ v3_ca ]
basicConstraints = CA:TRUE
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer:always

Run the command as shown. In this case, the PEM pass phrase it asks for is a new one, which you must enter twice:

# openssl req -new -x509 -extensions v3_ca -keyout private/cakey.pem \
-out cacert.pem -days 3650 -config ./openssl.cnf

Then the following screen will appear enter all the required information

Using configuration from ./openssl.cnf
Generating a 1024 bit RSA private key
.......++++++
..........................++++++
writing new private key to 'private/cakey.pem'
Enter PEM pass phrase:demo1
Verifying password - Enter PEM pass phrase:demo1
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Organization Name (company) [The Sample Company]:<enter>
Organizational Unit Name (department, division) []:it
Email Address []:example@example.com
Locality Name (city, district) [Metropolis]:<enter>
State or Province Name (full name) [New York]:<enter>
Country Name (2 letter code) [US]:<enter>
Common Name (hostname, IP, or your name) [:TSC Root CA

This process  produces two files as output:

A private key in private/cakey.pem

A root CA certificate in cacert.pem

cacert.pem is the file you want to distribute to your clients.

We can query the contents of this certificate with openssl to learn to whom belongs, what it is valid for, etc.

openssl x509 -in cacert.pem -noout -text
openssl x509 -in cacert.pem -noout -dates
openssl x509 -in cacert.pem -noout –purpose

Creating a Certificate Signing Request (CSR) 

Now that we have a root certificate, we can create any number of certificates for installation into our SSL applications such as https, spop, or simap. The procedure involves creating a private key and certificate request, and then signing the request to generate the certificate.

Our configuration file needs some more definitions for creating non-CA certificates. Add the following at the end of the file:

 [ v3_req ]
basicConstraints = CA:FALSE
subjectKeyIdentifier = hash

 To avoid having to repeatedly put this on the command line, insert the following line to the req section after the distinguished_name line as shown:

 distinguished_name = req_distinguished_name
req_extensions = v3_req

 Now we are ready to create our first certificate request. In this example, we are going to create a certificate for a secure SMTP server at mail.example.com. Everything looks the same as when we created the CA certificate, but three of the ensuing prompts get different responses.

Organizational Unit: a reminder of what the certificate is for

Email Address: the postmaster

Common Name: the server hostname

The Common Name must be (or the IP address must resolve to) the server name your clients use to contact your host. If this does not match, every time they connect your clients will get a message asking them if they want to use this server. In effect, the client software is saying, "Warning! You asked for mail.example.com; the responding machine's certificate is for smtp.example.com. Are you sure you want to continue?"

 openssl req -new -nodes -out req.pem -config ./openssl.cnf

Organizational Unit Name (department, division) :Mail Server Email Address :postmaster@example.com
Common Name (hostname, IP, or your name) :smtp.example.com

This process produces two files as output:

A private key in key.pem

A certificate signing request in req.pem

These files should be kept. When the certificate you are about to create expires, the request can be used again to create a new certificate with a new expiry date. The private key is of course necessary for SSL encryption. When you save these files, meaningful names will help; for example, smtpserver.key.pem and smtpserver.req.pem.

We can view the contents to make sure our request is correct:

openssl req -in req.pem -text -verify -noout

Signing a Certificate

Now we need to add the configuration file section that deals with being a Certificate Authority. This section will identify the paths to the various pieces, such as the database, the CA certificate, and the private key. It also provides some basic default values. Insert the following into openssl.cnf just before the req section:

[ ca ]
default_ca = CA_default

[ CA_default ]
serial = $dir/serialno
database = $dir/mainindex.txt
new_certs_dir = $dir/newcerts
certificate = $dir/cacert.pem
private_key = $dir/private/cakey.pem
default_days = 1000
default_md = md5
preserve = no
email_in_dn = no
nameopt = default_ca
certopt = default_ca
policy = policy_match

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

To sign the request we made in the previous step, execute the following and respond to the prompts. Note that you are asked for the PEM passphrase selected earlier:

openssl ca -out cert.pem -config ./openssl.cnf -infiles req.pem

Once you entered the above command you should be able see the screen like below

Using configuration from ./openssl.cnf
Enter PEM pass phrase:server
Check that the request matches the signature
Signature ok
The Subjects Distinguished Name is as follows
organizationName      :PRINTABLE:'The Sample Company'
organizationalUnitName:PRINTABLE:'smtp Server'
emailAddress          :IA5STRING:'postmaster@example.com'
localityName          :PRINTABLE:'repalle'
stateOrProvinceName   :PRINTABLE:'guntur'
countryName           :PRINTABLE:'UK'
commonName            :PRINTABLE:'smtp.example.com'
Certificate is to be certified until Dec  22 14:37:38 2004 BST (1000 days)
Sign the certificate? [y/n]:y

1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated

This process updates the CA database, and produces two files as output:

A certificate in cert.pem

A copy of the certificate in newcerts/.pem

We can inspect the certificate using the following command

openssl x509 -in cert.pem -noout -text -purpose | more

The certificate has both the encoded and a human-readable versions in the same file. You can strip off the human-readable portion as follows:

mv cert.pem tmp.pem
openssl x509 -in tmp.pem -out cert.pem

Installing the Certificate and Key

This depends on the application. Some want the key and the certificate in the same file, and others want them separately. Combining them is easily done with:

cat key.pem cert.pem  key-cert.pem

After this step, you have three installable components to choose from:

  • A private key in key.pem
  • A certificate in cert.pem
  • A combined private key and certificate in key-cert.pem

Copy the appropriate files into the locations specified by the instructions for your application and system. Restart the applications, and you are in operation with your new certificate.

Apache

Apache has separate configuration directives for the key and the certificate, so we keep each in its own file. These files should be kept outside of the DocumentRoot subtree, so a reasonable directory structure might be:

File          Comment
/home/www/html Apache DocumentRoot
/home/www/ssl      SSL-related files
/home/www/ssl/cert.pem Site certificate
/home/www/ssl/key.pem Site private key

Within the directive for the site (which of course should be on port 443), include the directives that point to these files:

<VirtualHost 172.29.5.45:443>
   ServerName smtp.example.com
   DocumentRoot /home/www/html
  - other directives for this site -
   SSLEngine on
   SSLLog /var/log/apache/ssl_engine_log
   SSLCertificateFile /home/www/ssl/cert.pem
   SSLCertificateKeyFile /home/www/ssl/key.pem
</VirtualHost>

Stunnel

stunnel is used as an SSL wrapper for normal non-secure services such as IMAP and POP. It accepts as arguments (among other things) the service to execute, and the location of the certificate and private key.

The key and the certificate are provided in the same file. These can go anywhere, but a good location might be /etc/ssl/certs. Specify it on the stunnel command line as follows:

stunnel -p /etc/ssl/certs/key-cert.pem 

Distributing the CA Certificate

This is the step that stops the clients from complaining about untrusted certificates. Send cacert.pem to anyone who is going to use your secure servers, so they can install it in their browsers, mail clients, et cetera as a root certificate.

Renewing Certificates

Your certificate chain can break due to certificate expiry in two ways:

The certificates you signed with your root certificate have expired.

Your root certificate itself has expired.

In the second case, you have some work to do. A new root CA certificate must be created and distributed, and then your existing certificates must be recreated or re-signed.

In the first case, you have two options. You can either generate new certificate signing requests and sign them as described above, or (if you kept them) you can re-sign the original requests. In either case, the old certificates must be revoked, and then the new certificates signed and installed into your secure applications as described earlier.

You cannot issue two certificates with the same Common Name, which is why the expired certificates must be revoked. The certificate is in the newcerts directory; you can determine its filename by browsing index.txt and searching for the Common Name (CN) on it. The filename is the index plus the extension ".pem", for example "02.pem". To revoke a certificate:

openssl ca -revoke newcerts/02.pem -config ./openssl.cnf

You should be able to see the following screen

Using configuration from ./openssl.cnf
Enter PEM pass phrase: demo1
Revoking Certificate 02.
Data Base Updated

Now that the certificate has been revoked, you can re-sign the original request, or create and sign a new one as described above.