Friday 22 March 2013

Create your own S/MIME email certificates with Openssl

Following on from creating my own Certificate Authority for signing internal https connections as covered in a previous post, the same Openssl CA can be used to create certificates for signing emails. This has many of the same benefits and limitations as self signed with SSL certificates for websites. On the plus side it is free and because you control it you can instantly create as many certificates as you desire. It is just as secure cryptographically as a certificate from a big player like Verisign. The negatives are that you will need to convince everybody you deal with to trust your certificates since they will not be automatically trusted and there is no insurance associated with them if something goes wrong. For internal use and testing they are therefore perfectly fine, for external customer facing use you are probably better off paying to get a certificate from one of the commercial players in the market.

Update the Certificate Authority for S/MIME

So assuming you have followed my previous guide and have a working Certificate Authority there is one change to make. Copy the openssl.cfn file to openssl-users.cnf, open the new file in a text editor and in the [ usr_cert ] section comment change the nsCertType as follows:
# nsCertType = server  # <---- comment out this line
nsCertType = client, email # <---- un-comment this line
Certs created will now be defaulting to client and email use so they can be used as part of  vpn or similar and also encrypt and sign emails.

Create Private Key and CSR

We can now create a private key and csr for the user in question:
$ openssl req -config openssl-users.cnf -new -newkey rsa:2048 -keyout private/Users_Name.key -out csr/Users_Name.csr -days 365
Note that the only difference here from my server key generation is that I have not added the -nodes command. This means that the private key will have a password on it that needs to be entered when used. My logic is that server keys are both on more secure machines and might need to reboot for updates on a schedule so requiring a password there might not be practical. For a users email key it will be on a normal workstation so more exposed to security risks and also you will always be there to enter the password since you will have just typed out an email!

Answer the wizard with the values you wish to have on your certificate. The "common name" should be your actual name and make sure the email address is exactly correct.

Create Certificate and Convert to PCKS12 Format

Next you need to sign the csr with the CA key:
$ openssl ca -config openssl-users.cnf -out certs/Users_Name.crt -infiles csr/Users_Name.csr
Check that the cert type is correct to make sure the config changes were done correctly. Next you need to convert this certificate into PCKS12 format so it can be used by email clients. This new file will contain the public certificate and private keys so it needs to be kept secure.
$ openssl pkcs12 -export -in certs/Users_Name.crt inkey private/Users_Name.key -out private/Users_Name.p12

Import Into Email Client

I'll leave this largely as an exercise for the reader because there are too many different email clients to choose from. The two main email clients I use are Outlook and GMail.

  • For Outlook just double click on the *.p12 file - Windows will automatically walk you through adding it to the correct certificate store and configure the security options for you.
  • For gmail it is currently not possible to use S/MIME encryption :( I am guessing that since their Postini service offers encryption they do not want to allow this competition. If you connect another mail client to GMail (Outlook/thunderbird etc) then you can set up the encryption there and it will work fine, it will just show garbage in the gmail web interface.
Remember after importing a certificate you will be able to sign email but not encrypt it! To encrypt email you need to get the public certificate of the person you want to send emails to. The easiest way to sent your public key to someone is to send them a signed email.

Wednesday 20 March 2013

Synology Self Signed SSL Certificates Invalid Cipher Type

UPDATE: The new version of Synology's DSM (version 4.2) does not have the problem discussed in this post - so the simple fix is to update your Synology to version 4.2 or above. An anonymous comment also suggests a quicker fix than mine that sounds good but since I've already upgraded to 4.2 I can not test it.

Recently I started signing my own SSL certificates for internal use at my company. One of the systems which refused to play nice with my certificates was a Synology DS412+ running version 4.1 of their DSM software. The Synology guides for creating a self signed certificate assume you will be happy creating the CA on the Synology itself, not using a self signed certificate created on another separate CA system. Since I already have my own private internal CA which is trusted on my domain this was not ideal for me. When trying to import the certificate I created on my private CA I received a very unhelpful error...
Illegal certificate
...with no clarification on what was wrong with it. My first breakthrough came when I noticed that my certificate has a block of human readable text at the top and certificates generated using the guide on the Synology Wiki did not. Removing all text in the .crt file above "-----BEGIN CERTIFICATE-----" solved this problem - it is a text file so can be edited easily with vi, notepad or any other basic text editor.

Unfortunately importing the certificate now gives a new error:
Invalid cipher type. Please use another certificate and private key.
Again, this left me stumped for a bit. I managed to get it working by using the following series of commands to generate the certificate signing request and sign it:
$ openssl genrsa -out private/synology.key 1024
$ openssl req -config -new -key private/synology.key -out csr/synology.csr
$ openssl ca -config openssl.cnf -out certs/synology.crt -infiles csr/synology.csr
However I am still no wiser as to why this works when replacing the first two lines with my normal way of generating csr's...
$ openssl req -config openssl.cnf -new -nodes -newkey rsa:1024 -keyout private/synology.key -out csr/synology.csr -days 365
fails... If anyone can shed any light on this I'd love to learn what is happening. As far as I can tell both options would create rsa 1024 bit csr's which is the obvious interpretation of "Invalid cipher" and both commands use the same config file for defaults and v3 extensions etc. At least its working now and hopefully this will let anyone with the same problem generate their own ssl certificates for Synology devices.

Monday 18 March 2013

Become Your Own SSL Certificate Authority

I have recently started signing my own SSL certificates for internal use at my company. I had several reasons to do this:

  • I was fed up of getting SSL warnings for every new system I deployed because of its self generated SSL certificates
  • I wanted to improve security and stop training myself and others to click "proceed to site" which for some was becoming an automatic reflex
  • I wanted to investigate the options for adding SSL certificates to things like VPN connections and direct access via IPv6
  • I was also interested in learning more about securing emails with SSL for identity verification etc although I'm currently more than happy with GPG it is not for everyone.
  • It sounded like a fun challenge
Please also note that I'm using the term "SSL" throughout this guide. SSL (Secure Sockets Layer) has now been depreciated and replaced with TLS (Transport Layer Security) however everyone still refers to TLS as SSL so that is what I'm doing in this guide. Certificates generated using OpenSSL as in this guide are TLS certificates and fully trustworthy which you can check by viewing the connection properties when you have applied a certificate to a server. See Wikipedia for more details on this.

In order for this to work I would need to create my own certificate authority and import that into all computers as trusted. Importing into computers can be done manually however since I have a windows domain it is easier to distribute the authority to all computers via GPO. Then I could start creating CSR's (Certificate Signing Requests) and signing SSL certs for the various systems around the company. First things first though I needed to create a Certificate Authority.

Choosing a Live Linux Distro

Conventional wisdom with Certificate Authorities is that it needs to be a dedicated machine that is not connected to any network. You can generate the keys as required on this machine and then copy them to a blank USB key which never returns to the dedicated box. In theory therefore the CA's key is only stored on a single machine that is not possible to hack into over the network and if it is compromised is not able to communicate anything confidential. In practice I have a few problems with this idea. Firstly it means you need to have a dedicated machine sitting somewhere taking up space. This machine needs to highly reliable since it will be important and probably left unused for long periods of time. You also need so make sure this machine is secure which adds overhead in the setup - decent password policy, physically securing it to make sure nobody gets near it, ensure that nobody decides to use it as a test machine for something because "it has not been touched in ages so can't be needed any more" etc. Finally you need to backup the ultra secret CA private key somewhere else anyway which leads to my solution.

I boot from a live Linux CD on a machine not connected to the network (in my case an old laptop with no hard drive). I have a pair of USB memory sticks that are only ever connected to this system (one live and one backup) for storing the private CA key and other required files and then use another blank memory stick to copy the signed SSL certificates to the relevant host. Effectively therefore my whole CA infrastructure is a simple USB memory stick which is easy to physically secure. Any time I need to use it I can get any suitable live Linux distro and boot on any isolated system. No need to worry about securing the machine I use since secret stuff is only stored in memory while the machine is on.

That said the first challenge was finding a live distro to use which already had an up to date OpenSSL installed and in a suitable working condition for running a CA since I did not really want to connect to the internet do download additional packages since that would probably weaken the overall security. Finding a list of packages included on live CD's proved easier than expected using the search at Distrowatch.  Distrowatch has a search page that lets you find distro's with a specific version of a package and also lists the package versions for each distro at the bottom of its page. Not ideal as for some it has an updated package in the current distro but the live image is much older.
  • Debian live 6.0.7 LXDE (openssl version 0.9.8o from June 2010 - typical of Debian's legendary release cycles)
  • Ubuntu 12.10 desktop (openssl version 1.0.1c)
  • Mageia 2 (openssl version 1.0.0j)
  • Fedora (openssl version 1.0.1c)
Since most live distro's seem to include Openssl the choice largely comes down to personal preference. I went with Ubuntu since it was one of the more up to date and I am most at home in Debian based systems but any of the above should work. Obviously you might hit some problems if you follow this guide exactly but use a different system as config files etc might be subtly different. Once you have decided on which distro to use you then need to get started on generating the root CA key and certificate. Watch out for keyboard layouts though - most live distro's default to US english layout which can cause chaos down the line with your password...


Creating a Certificate Authority

First you need to setup your working directories and Openssl config file:
$ mkdir CA
$ cd CA
$ mkdir certs crl newcerts private csr
$ touch index.txt
$ echo 1000 > serial
$ cp /usr/lib/ssl/openssl.cnf .
Now edit the openssl.cnf file and make the following change in the CA_default section: change "dir = ./demoCA" to "dir = . ". You can also change the defaults for country, company name etc if they will always be the same (search for countryName_default to jump to the right area of the config file).

By default certificates are created with permission to do everything EXCEPT code signing. Since all you probably want to do is connect via https securely it is also worth un-commenting this line in the [ usr_cert ] section:
nsCertType = server
Next generate the private RSA key for the CA with 4096 bits (should be enough for now, increase to match your levels of paranoia) Enter a strong password when prompted as this private key will be encrypted with tripple Des (-des3 switch)
$ openssl genrsa -des3 -out private/cakey.pem 4096
And then use this key to create the CA x509 certificate with a 10 year lifetime (or whatever you wish - since this cert should never leave the key generation system it is reasonably safe to give it a long lifetime). Enter the password you used for the key generation and then enter details for the certificate as prompted. This stuff will be visible in the final certs so don't put dummy data in there.
$ openssl req -new -x509 -extensions v3_ca -key private/cakey.pem -out cacert.pem -days 3650

Generate SSL certificates for servers

The CA is now setup and ready to go. Time to create a key and csr for a test server, this time only valid for 365 days as it will be more exposed to loss being on a server that is hosting a website. Again fill in the details with real data for the server you want the ssl cert for. Do not enter a challenge password here unless you want the server to prompt for an ssl certificate password on every reboot. This step can be completed on the server that needs the certificate rather than the CA system if preferred - you just need to copy the csr file (NOT the .key file) to the CA system in order to create the certificate. Note that if you do not do this on the CA server you probably want to omit the "-config openssl.cnf" bit from this command.
$ openssl req -config openssl.cnf -new -nodes -newkey rsa:2048 -keyout private/testserver1.key -out csr/testserver1.csr -days 365
Now you just need to sign the csr with the CA's private key (this step will need to be done on the CA system)
$ openssl ca -config openssl.cnf -out certs/testserver1.crt -infiles csr/testserver1.csr
You will now have the signed ssl certificate for the server in certs/testserver1.crt, the serial file will have been incremented by 1 and the index.txt file will have an entry for the certificate you just created.

Import the root CA certificate into your computers manually

This is nice and easy on windows - copy the cacert.pem file to your computer, rename it to cacert.crt and then double click on it. A wizard will step you through adding to the default certificate store and it will then be accessible by your web browsers (at least in Chrome and Internet Explorer - Firefox uses its own certificate store so you will need to import manually for that to work).

Import certificate into domain

I did this on my Server 2003 domain so it might be slightly different on newer server OS's. You can either re use an existing group policy or create a new one and apply it as required. In "Group Policy  Object Editor" browse to Computer Configuration --> Windows Settings --> Security Settings --> Public Key Policies --> Trusted Root Certification Authorities. Right click and choose "import" and you will get a very similar wizard to importing directly on a computer. Once done you can either wait for the group policy to propagate or on a computer run "gpupdate /force" to pull in the updated GPO with certificate immediately  Your computers will now show any relevant SSL certificates as trusted.

Tidy Up

After creating any new certificates you will need to ensure your CA folder is backed up to at least two separate highly secure memory sticks since if you lose these files you have just lost the ability to create new certificates with this Authority. Keep the certificates you generate safe as if somebody gets hold of one they will be able to impersonate that server - ideally they should only be stored on the server that hosts the SSL site and maybe on the secure memory sticks.

Troubleshooting


  • TXT_DB Error number 2 when generating certificates - By default Openssl will only generate a single certificate for each server and if you try to generate another one then it gives this cryptic error. Either you need to revoke the previous certificate or edit the openssl.cnf file and uncomment the "#unique_subject = no" line. To revoke the previous certificate find the serial number of the certificate from the index.txt file. Then issue the command "openssl ca -config openssl.cnf -revoke newcerts/<NUMBER OF CERT>.pem"