Sunday, 5 March 2017

SSL/TLS for Dummies (including myself)

One would think that if you are in the business as long as myself, you know all this security stuff by heart. Well, I didn't really do so until recently. Until my previous project, I always had "the ops guys" making sure that the network configs, certificates and "all that magic" are in place.
However, in that project I ended up having to provide a lot of information myself and even creating certificates, deploying them in the correct places etc.
Although I had had some rough idea how these things work in general, I had to collect lots of information from different places on the web. I found it surprisingly complicated to get some basic answers, so I decided to scribble up my own guide for someone who'd find themselves in my shoes in the future.

What's the difference between SSL and TLS?

There is none! We used to talk about SSL (Secure Sockets Layer), but the official term is now TLS (Transport Layer Security). The most widely used version is TLS 1.2 which was standardised in 2008. All versions before TLS 1.0 (aka SSL 3.1) have been retired. From a developer's point of view, that's all you need to know about this question.

What goes on in there and what are these certificates for?

I won't go into detail about protocols and encryption algorithms here, but rather try to describe what I feel an application developer should know about the mechanisms:
The basic idea is to ensure that you know that in a conversation the party you're talking to is who they claim to be. If you go to a party and someone you've never met introduces themselves as "Hi, I'm Frank", how can you be sure that he's not actually Tim? You've basically got two choices: Ask him for a form of ID that you can recognise or hope that one of your trustworthy friends can confirm the name.
OK, the party example may be a bit pointless, but what about a business transaction? One example I like to use is what happens when you open a bank account. The bank official is legally required to verify your identity (and a few other things which we will ignore for the purpose of this article) in order for them to be able to process the application. Normally, you show some form of photo ID e.g. a passport. Depending on the specific requirements in the country, you may have to show some proof of residence as well.
With the advent of pure online banking, this approach became complicated. How can you show your photo ID in a branch of a bank that hasn't got any branches? Well - you can't. However, the bank is still required to verify your identity. At this point I can only explain how this works in Germany, because I underwent this procedure myself a few times over the past 10 years or so:
PostIdent procedure (please excuse the German texts)
The customer applying for the bank account fills in an online form (surprise, surprise!) which will enable the bank to make all necessary preparations for opening an account. However, instead of being able to work with the account right away, the applicant will have to print a personalised form and carry this to the post office - together with their identification document. They present this to the post office clerk who will then perform the actual ID check and send the form directly to the bank. Only after the bank receives this form will they complete the application process and activate the applicant's account.
So what's happening here? Effectively, the bank outsources the act of identity verification to the post office (who acts as the trustworthy friend from the party example). This process is known as Postident in Germany and used by other services than banks as well.
What does all this have to do with TLS and certificates? Well, TLS works by the same principle: "I don't know you, but if someone I trust can confirm your identity, then I'm happy."
This confirmation is what certificates are for. When the web browser accesses a site that uses TLS, the server presents a certificate to the browser. This certificate carries the server's name and the information required to verify it with an authority.
In this context, authorities are institutions which authorise other institutions' certificates by signing them. In the Postident comparison, this would be the institution that issued the customer's passport - meaning the national government. In the world of the internet, the situation is actually a bit messier than one would think. The "authorities" in the most widely known TLS use case - the HTTPS protocol - are companies whose signatures are known to the web browser (or e.g. the JVM). You may have heard of VeriSign who were bought by Symantec a while back; other well-known ones are Comodo or GlobalSign; however, even companies like Verizon or the German Telekom are in the list. Basically whoever makes the browser decides whom to trust (at least initially; once they're out in the wild, every user can add whichever authority they wish). When you access a website using a URL starting with https://, the browser applies some "crypto-magic" (which we won't explore in detail here) in order to check whether the site has been signed with a certificate from one of the authorities in the browser's trust list. Usually there is a distinction between actual "root certificates" and so-called "intermediate certificates". The former are held in the browser's (or JVM's) list of trusted authorities, the latter are held by the different authorities and signed using one of their own roots. These are usually the ones that the authority in turn uses to issue certificates to the clients. However, the signing chain is included in the certificate presented to the browser so that it can always backtrack up the ancestry far enough until it reaches a certificate in its trusted list.
So compared to the "real-life" example with PostIdent, the certificate presented by the website is the ID itself, while the certificates it's been signed with are the security features on it (the general shape, the authority's stamp, watermarks etc.).

OK. I got the idea, what about the mechanics?

As mentioned above, I'm not looking at encryption algorithms etc., but rather at how to create and use certificates.

The fundamental decision: Java Keystore or "regular" PEM files?

OK, calling this "fundamental" may be slightly exaggerated, as there are ways for converting one format into the other. On the last project we had both formats; which one was used for which service depended on the technology stack. It's unsurprisingly simple: Whatever runs on the JVM will normally use a Java Keystore, everything else won't. From here onwards, I'll describe the use of both for the needed functionality.

Creating a keypair and a Certificate Signing Request

The keypair is the basis for any certificate. There is a public and a private key. I still have to hear of a good real-life analogy for these, but they may be viewed like a mailbox with a lock. The mailman (or anyone else) can drop letters through the mailslot (= the public key), but only the owner has got the (private) key to actually access the mail once it's been delivered. Not really the same thing, but I'm open to suggestions for better examples.
Anyway, let's get down to business:

The PEM version

In the "regular" world, the certificate and private key are stored in two separate files:
openssl req -out sign_this.csr -new -newkey rsa:2048 -nodes -keyout privateKey.key
This will ask you a few questions and generate a certificate signing request and a private key file. The values for the fields will depend on your specific organisation, but one that you will always need to fill in is the so called "Common Name" which should be the full domain name to be identified by the certificate (e.g. www.blogger.com).
The CSR file will require signing by a recognised certificate authority. How to achieve this will depend on your particular organisation and the authority they use. There may be an email exchange or a direct upload/download through a special website.
The result of a signing request is a certificate file (usual endings are .pem and .crt). What you do with this file, depends on the service that uses them. Normally you will place them together with the private key somewhere on the file system and add this location to a configuration file.

The JKS version

In the Java Keystore world, creating the keypair and the CSR are two separate steps:
  1. Create the keypair:
    keytool -genkey -alias demo -keyalg RSA -keystore keystore.jks -keysize 2048
  2. Use the keypair to create a signing request:
    keytool -certreq -alias demo -keystore keystore.jks -file sign_this.csr
As above, you will have the CSR file signed by the appropriate authority for your organisation. Once you have obtained the certificate, you will import it into the keystore like this:
keytool -import -trustcacerts -alias demo -file demo.crt -keystore keystore.jks
As above, what you do with the keystore now depends on your particular service. Again, as above, you will place it somewhere in the file system and add the location to some configuration file.

My organisation is very slow in everything./I just want to set something up for early development purposes.

Great news! You can sign certificates yourself! (Just don't expect anyone outside your organisation to accept them.) I could list all the necessary steps for creating and running a certificate authority here - or I can just refer you to Jamie Nguyen's excellent tutorial. This really answered all the questions for me.
As for the client side, in the browser you will have to register a security exception in order for it to accept such a certificate. As for the JVM, very often you will find advise such as this one which tells you to import the self-signed root (or intermediate) certificate into the JVM's own trusted list. This will work, but in my opinion this shouldn't be your way of handling things if you can avoid it. Every time you update your Java installation, you will have to keep this step in mind. Not only that, but you are really undermining Java's security architecture which is intended to protect your system. So you should avoid this by all possible means. Rather, create an isolated keystore for the software that really must accept the certificate and import it into this one:
keytool -import -trustcacerts -alias root -file intermediate.crt -keystore keystore.jks
Again, there are various ways of using this keystore in your code, depending on the libraries and programming environment. I will explore a few that I've come across in a later post.

Surely, there are more commands than in this post.

Of course. The extremely helpful SSL Shopper has got one page for OpenSSL and another one for the Java keytool.

No comments:

Post a Comment