Skip to content

heroku/tak

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

11 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Tak

An Erlang library to perform SSL certificate pinning.

Validating the SSL certificate presented by a server can be a very challenging task. There are an inordinately large number of complicated rules to follow, and one change in DNS or leaving the certificate alone for more than a year can result in validation failures - the names don't match or the certificate expires. Additionally, if we validate certificates in the same manner that web browsers do, we'll trust anyone's certificate for 'secureservice.example.com' no matter if we know that it should only ever be signed by "Bob's CA and Grill".

We can skip most of the complication if we give the SSL client a copy of the only certificates that should be used by the server - this approach is known as Certificate Pinning.

Tak is a library that helps you process certificate chains and turn them into a configuration usable with the SSL client library in Erlang/OTP.

Build

$ rebar compile

Pinning a connection to a certificate

To start with, your application will need a copy of the SSL certificate chain used by the server you want to connect to. This chain should be in PEM form (the one that looks like "-----BEGIN CERTIFICATE-----").

At application start time, you should read this pem data and run it through tak:pem_to_cert_chain/1. For instance, if the certificate chain lives in the file myapp/priv/service_certs.pem, you could do something like:

FileName = filename:join(code:priv_dir(?MODULE),
                         "service_certs.pem"),
{ok, PemData} = file:read_file(FileName),
ServiceCertChain = tak:pem_to_cert_chain(PemData).

You can even pre-prepare the options you'll need to pass to the ssl library:

ServiceSSLOptions = tak:chain_to_ssl_options(ServiceCertChain).

Or you can skip a few steps:

FileName = filename:join(code:priv_dir(?MODULE),
                         "service_certs.pem"),
{ok, PemData} = file:read_file(FileName),
ServiceSSLOptions = tak:pem_to_ssl_options(PemData).

Then when you want to connect to the service:

ssl:connect("service.example.com", 443, ServiceSSLOptions).

This will then connect to the service and validate that the certificate the server presents is exactly the same as our copy.

Advice

Turning the PEM data into the certificate chain and then the SSL options is a somewhat expensive process. Why not do that once at startup and then store it in the application environment for your OTP app?

load_ssl_options(PemData) ->
    application:set_env(my_cool_app, service_ssl_options,
                        tak:pem_to_ssl_options(PemData)).

Then when you need to use it, just:

ssl:connect("service.example.com", 443,
            application:get_env(my_cool_app, service_ssl_options)).

This makes sure the processing happens once and is stored in ETS for quick use at connect time.


Neat picture of Tak


Tak by ~InvaderJabber on deviantART

About

Tak: SSL Certificate Pinning in Erlang.

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages