Home > English, Erlang > A brief introduction to ssl with Erlang

A brief introduction to ssl with Erlang


Another topic that gave me some pain when I started with Erlang was SSL. At that time my general knowledge on both the topics was really poor, so I started looking around in the Internet for a nice “tutorial for dummy”, but it was rather hard at that time to find something.

That’s why today I will show you how to create the certificates you need, and how to set up in Erlang a working connection.

Protect your connections!

The fist thing to do is to create a key for our certificate:

$ openssl genrsa -out key.pem 1024

After the key creation, you will have to answer a set of questions in order to create your certificate. Below you may find an example of this I did on my machine. I would like to point out that a very important question is “Common Name”: in fact you have to put as answer the hostname of the server you’re creating a certificate for.

$ openssl req -new -key key.pem -out request.pem

   Country Name (2 letter code) [AU]:IT
   State or Province Name (full name) [Some-State]:
   Locality Name (eg, city) []:Trento
   Organization Name (eg, company) [Internet Widgits Pty Ltd]:Pdincau's Blog
   Organizational Unit Name (eg, section) []:.
   Common Name (eg, YOUR name) []:pdincau.example.net
   Email Address []:pdincau@example.net

   Please enter the following 'extra' attributes
   to be sent with your certificate request
   A challenge password []:
   An optional company name []:

If you want to have a serious certificate, you should send request.pem to some commercial Certificate Authority, at that point you just need to sit and wait for the certificate. On the other hand, if you need a certificate for testing purpose you may consider to create a “self-signed” certificate as I will do in the next line:

$ openssl x509 -req -days 30 -in request.pem -signkey key.pem -out certificate.pem

At this point, you should have your self-signed certificate, therefore it’s definitely time for some Erlang code!

Ok, let’s see how to establish a simple ssl connection (NOT THE MOST SECURE POSSIBLE IMPLEMENTATION!) between a client and a server. First of all let’s start two Erlang shells, one for the server and one for the client (I used two different nodes to identify the two shells, but this is not really needed), and then we will start the application ssl.

Here is the server part:

$ erl -sname server
Eshell V5.7.4  (abort with ^G)

(server@paolo-laptop)1> ssl:start().
ok

The first thing to do in the server side is to create an ssl listen socket, and to perform a transport accept on it:

(server@paolo-laptop)2> {ok, ListenSocket} = ssl:listen(9999,
                                                     [{certfile,"certificate.pem"},
                                                     {keyfile, "key.pem"},
                                                     {reuseaddr, true}]).
{ok,{sslsocket,5,}}
(server@paolo-laptop)3> {ok, Socket} = ssl:transport_accept(ListenSocket).

Good, at this point we have our server listening for incoming ssl connections from clients! Let’s test it by creating a client then 🙂

$ erl -sname client
Eshell V5.7.4  (abort with ^G)

(client@paolo-laptop)1> ssl:start().
ok
(client@paolo-laptop)2> {ok, Socket} = ssl:connect("localhost", 9999,  [], infinity).

Where “localhost” is the name of the host we want to connect to, 9999 is the port, and infinity represents a timeout (which may be expressed as well in milliseconds).

Now, since the server must accept the connection from the client, we have to move back to the server shell:

(server@paolo-laptop)4> ok = ssl:ssl_accept(Socket).

Great, now we can exchange messages over our ssl connection!
Let’s test it sending two messages, one from the server to the client:

(server@paolo-laptop)5> ok = ssl:send(Socket, "foo").

and one from the client to the server:

(client@paolo-laptop)3> ok = ssl:send(Socket, "bar").

How can we check whether the two messages arrived or not? Fairly simple! We can use flush()!
Let’s flush the server messages:

(server@paolo-laptop)6> flush().
Shell got {ssl,{sslsocket,6,},"bar"}
ok

Perfect! It works great!
Notice that this is a really (really really really) example of ssl connection using Erlang. For example one interesting thing could be to upgrade a tcp connection to an ssl connection…anyway you can dig deeper on it by reading this.

Categories: English, Erlang Tags: ,
  1. Tim
    November 7, 2011 at 10:37 pm

    Nice tutorial.

    Is the ssl:accept/1 call actually necessary? I thought it was to “upgrade” a gen_tcp connection to an ssl one, but I could be wrong. I never used that in my beta-quality Erlang/Emacs mail/news client, so now I’m worried that it hasn’t been sending the password securely…

    On a somewhat unrelated tangent, I assume that the recv/2, recv/3 calls are at some level using flush/0? I haven’t used flush/0 directly yet, although I might do so in the future. I looked at the ssl.erl and ssl_connection.erl sources and traced it until it makes a call to gen_fsm:sync_send_all_state_event/3, which makes a call to gen:call/4, then gen:do_call/4, which goes into process monitor code. So I assume that flush might be used instead of recv when you are reading short buffers that won’t come close to 17 bits of data for a given tcp/ssl response.

    Regards,
    Tim

  2. Tim
    November 7, 2011 at 10:38 pm

    Oops, In my last comment, I meant ssl:ssl_accept when I referred to ssl_accept.

  3. Tim
    November 7, 2011 at 10:41 pm

    Also, I’m not doing the transport_accept call either. All I’m doing is ssl:start(), then ssl:connect(Hostname, Port, TcpOptions), then ssl:send of username and password, then ssl:recv.

  4. January 31, 2012 at 5:11 pm

    Thanks for this – a very useful beginner tutorial!

  1. No trackbacks yet.

Leave a comment