Skip to content
 

SSL certificates as easy as 1,2,.. 3!

These days I yet again faced the problem of establishing of secure connection between my client and server applications. Although this time the task by itself was quite small and simple and (so a hand–made solution would definitely suffice) I’d decided to go via standard approach, i.e. using something that has already been invented, tested and proved to be useful.

When we’re talking about transport–level security that’s undisputidly what is called a Secure Sockets Layer, or SSL. There is a number of free libraries out there implementing SSL, like popular OpenSSL or less popular Ajisai (based on cryptographic C++ library Botan). In my case I had to stick to OpenSSL as I also was about to use RCF for my client–server communication and RCF had already got support for OpenSSL integration to secure it’s transport channels.

OpenSSL uses certificates to make secured interactions work. So we immediately face a problem of getting these certificates. Searching the Internet would not give immediate understanding of what kind of certificate to we need and where to get the required one. so I’ve put all the pieces of information together and am sharing that knowledge with you :)

First of all let me point out that most of OpenSSL usage instructions here were extracted from here — a beautiful post regarding setting–up of a secured Apache web–server.

Let’s get away a bit from our original goal (securing a custom client–server communication channel with SSL) and will have a look at more common SSL usage scenario: securing a connection between some privately held web–server with client web–browsers. Using SSL here resolves 2 problems:

  1. It ensures client that the server he’s talking to is really the actual server matching the one client wants to talk to and not the forged one. I.e. client can be sure that someserver.com is really someserver.com and not badguysserver.com trying to look like (pretend he is) a someserver.com.
  2. It ensures that information between server and client will not be stolen or modified by any 3–rd party in between.

Both are achieved at first by ensuring server’s authenticity. Using asymmetrical cryptography server just proves that it does really hold the private key it wants client to believe it holds, i.e. server signs its message first. Then anyone having the public key (client) can ensure that the correct private key was used for signature. But when client receives a signature it has no idea if the signature comes really from that server: i.e. private key is proven, but not ensured that it is exactly the one required. In order to solve that, the hierarchy of Certificate Authorities was invented — client queries Certificate Authority if the received signature is authentic, or, more precisely, client just checks who issued the certificate that server used to make the signature. If server’s certificate was issued by a trusted Certificate Authority that would automatically mean that the server is authentic. Certificate Authority, before it issues certificates to for servers, performs a lot of checks and procedures. That means that only true server owners would receive certificates from CA. Basically “receiving” a certificate from CA would just mean that CA itself signs the certificate the server provides. Anyway, the list of trusted CA’s in its place is well known and is usually placed on client’s computer. Such CA’s are generally added to client’s system automatically during initial installation or update. Later client can add additional CA’s to his system (for example some not well known CAs that client still would like to trust to).

Once authenticity of server is proved using the method above, client and server interchange symmetrical cryptographic keys (using asymmetrical data interchange), and that keys are used to protect the session.

That’s why using a server certificate not signed by a well known CA for a web server would generally cause problems — clients visiting the web page will be prompted that the authenticity of the server is not checked. This also answers the question how CA’s earn their living — they just take some money to sign certificates of servers, in order for latter ones to be recognized by every potential client (which of course would already trust that CAs).

How one can try avoiding the need to sign his certificate with a well known CA?
Obviously, by using an unknown CA, for example even one’s own CA! Then just all clients have to be convinced to trust that home–made CA which won’t likely to happen :)
That’s why everyone out there uses pretty good known CAs for certificates located on public web services.

But what about our original case? There is a big difference with what we have in a web–server area: for our case we control both: the server and the client. That means that we can setup the client to check against any CA that we want and not only against some narrow list of big known trusted CAs.

So for our scenario we need to, firstly, create our own CA’s private key and CA’s certificate, and, secondly, create an actual server certificate and sign it with our CA’s certificate. After that we can embed CA certificate to client’s code so that client will check server’s authenticity using our own CA. And this will immediately solve 3 problems for us:

  1. Our clients will check our server’s authenticity
  2. Connection between our server and our client will be protected
  3. We won’t spend money on getting signature / certificate from public recognized CA :)

So how can we manage that?

As it was first noted, let’s deal with our own CA certificate. To create it we’ll need first to generate a private key for our CA.

openssl genrsa -out ca.key 4096

This will create a 4096 bit RSA private key for our CA, named ca.key.

Now we have to create a CA certificate request based on CA private key for our future signed CA certificate. We will then sign this certificate request using the same key we just generated (so we’ll have a self–signed CA certificate).

openssl req -new -key ca.key -out ca.req

This will crete a certificate request located in ca.req file.

Finally we have to sign our CA certificate request with itself, i.e. with it’s own private key:

openssl x509 -req -days 3650 -in ca.req -signkey ca.key -out ca.crt

This way we get our home–made CA certificate valid for 10 years, signed with our CA key. The certificate is located in ca.crt file. This certificate will be embedded into our client, to check authenticity of our server.

Later after initially publishing this article I discovered a single command that could substitute 2 commands from the above

openssl req -new -x509 -days 3650 -key ca.key -out ca.crt

This should create self-signed CA certificate without intermediate step of creation of CA certificate request.

Having CA private key and CA certificate we now would like to create server’s certificate.
This is pretty similary to creation of CA’s certificate with the only exclusion: on step 3 we will sign our server certificate not with itself (its own private key), but with our CA’s private key.

// Creating server private key
openssl genrsa -out server.key 4096
// Generating server certificate request, based on server private key
openssl req -new -key server.key -out server.req
// Signing server's certificate request with our CA's certificate (using CA's private key to prove that we have rights to use it)
openssl x509 -req -days 3650 -set_serial 01 -in server.req -CA ca.crt -CAkey ca.key -out server.crt

Voila! Now you can make your server use server.crt to use for server-side SSL and ship your clients with ca.crt, to check server’s authenticity. Obviously you can create certificate(s) for your clients just in the same manner, if you require them.

Please note, that in order to use certificate on server you’ll need both: your server’s certificate and server’s private key used to produced that certificate. In some cases you’ll be able to provide both separately and in some others (like RCF library) you’ll need to combine them into one file:

cat server.crt server.key > server.pem

That’s pretty all — what I need for my RCF + OpenSSL stuff.

6 Comments

  1. Grammar Nazi says:

    < …server use server.crt to use for server-side…

    WUT? Have you been taught about tautology at school? ;) Though, despite this, very interesting article. Keep it up!

  2. Dmitry Shandyba says:

    Hey, Mr. M., I don’t feel it like tautology :-D
    Yes, it sounds not that smoothly, but how am I supposed to call “server” if not “server” and “server-side” if not “server-side” ? :-) ))

  3. Mato says:

    Hello,
    can you please post few lines of code, where you are setting RcfServer and RcfClient with OpenSSL? My program always frozes, when I call requestTransportFilters method. Thank you for help.

  4. Dmitry Shandyba says:

    Hi Mato,

    you are welcome to look at this link: http://blog.shandyba.com/2010/03/27/rcf-1-2-openssl/.

    This example 100% works and, well, I don’t experience any freezings… So give it a try!

    Good luck! :)

  5. Mato says:

    Thank you very very much :)

Leave a Reply