What is Themis?

Themis is a high-level cryptographic services library: a library providing easy to use, highly abstracted set of functions to solve real-world security problems. We would like you to focus on building your software with security taken care of by professionals, instead of scrupulously assembling building blocks into cryptosystems yourself, resolving implementations, platform availability, vulnerabilities and performance contstraints yourself.

Themis is designed to provide complicated cryptosystems in an easy-to-use developer infrastructure, suitable for modern rapid development. It is an Open Source, Apache 2.0 licensed product that you can use free-of-charge, contribute code to or use in your own work.

Themis will provide a wide set of security instruments. The first three of which that are implemented in the current, 0.9 release are:

Themis is designed with ease of use in mind. From our experience of modern languages and elegant frameworks, we wanted to have cryptographic services with easy-to-use interfaces, which don't require complicated sequences of actions to set up ciphers, validate parameters and so on. Everything is handled within the framework, so the chance of introducing errors and breaking the overall cryptosystems is minimised.

Modular and Efficient

Themis is built around modularity: every layer is a set of abstractions with its own set of risk mitigation techniques and test suites. In this way, we plan to avoid massive refactoring when dependencies change. Equally, we intend to isolate risks on each layer and limit error proliferation.

Why we have started Themis

Themis is our internal platform for developing security procedures in future products and we want those to be built on a solid foundation. We needed an efficient cross-platform library to abstract cryptographic procedures from the implementations of algorithms, to combine elementary steps into cryptosystems, and to address common security scenarios in a easy-to-use form.

As we could not find an existing library that completely matched our vision of what we needed (while we have much respect for the elegance, innovation and approach of Daniel Bernstein's NaCl Project, we felt its narrower scope and limited set of platforms and interfaces did not quite fit our needs), we decided to make our own project Open Source and share the results with the community.

What Themis does

Themis provides high level languages such as Objective C, Java, PHP, Python or Ruby with a set of objects, each implementing some specific security procedure. The current version includes three objects:

What sets Themis apart

How it works

Themis is built around ease of use. Let's say we have a client-server communication infrastructure:

It is represented by Python server built with Tornado framework:

import tornado.ioloop
import tornado.web
class MainHandler(tornado.web.RequestHandler):
    def post(self):
        self.write(self.request.body);
application = tornado.web.Application([
    (r"/", MainHandler),
])
if __name__ == "__main__":
    application.listen(26260)
    tornado.ioloop.IOLoop.instance().start()

and Python client:

import tornado.ioloop
import tornado.httpclient;
http_client = tornado.httpclient.HTTPClient();
try:
    response = http_client.fetch(
        tornado.httpclient.HTTPRequest("http://127.0.0.1:26260", 
        "POST", 
        None, 
        "This is test message"));
    print response.body;
except tornado.httpclient.HTTPError as e:
    print("Error: " + str(e));
except Exception as e:
    print("Error: " + str(e));
http_client.close();

To add Themis secure session cryptography (most complicated and demanding object, others are even simplier than this) into this setup, you have to perform 4 steps:

Step 1. Client/server: Import the library, initialize an object

from pythemis import ssession;
class transport(ssession.mem_transport):
    def get_pub_key_by_id(self, user_id):       #callback function
        # retrieve peer public key form file, database, etc. by peer id
        return server_pub; 
session=ssession.ssession("local id", local_private_key, transport());

Step 2. Client side: initialize the session

init_session_message=session.connect_request();
#send init_session_message to server peer

Step 3. Client side: wrap message being sent in object's wrap method

wrapped_message = session.wrap(message);
#send wrapped_message to peer

Step 4. Server side: wrap message being received by server into unwrap method

res, message=session.unwrap(received_message);
if res==message.is_control:
     # receive correct control message. message must be send to peer as is
else:
     #proceed with plain message

Here's how Tornado server with Themis will look:

from pythemis import ssession;
import tornado.ioloop
import tornado.web;
class transport(ssession.mem_transport):
    def get_pub_key_by_id(self, user_id):           # callback function
       # retrieve peer public key form file, database, etc. by peer id
       return pub; 
session=ssession.ssession("server id", server_priv, transport());
class MainHandler(tornado.web.RequestHandler):        
    def post(self):
        message = session.unwrap(self.request.body);#decrypt received message
        if message.is_control:                      #session is not ectablish yet
            self.write(message);                    #send unwraped message 
                                                    #to client as is
        else:                       
            print message;                          #print accepted plain message
            self.write(session.wrap(message));      #encrypt and send reply message 
application = tornado.web.Application([
    (r"/", MainHandler),
])
if __name__ == "__main__":
    application.listen(26260)
    tornado.ioloop.IOLoop.instance().start()

And this is how client will look:

from pythemis import ssession;
import tornado.ioloop
import tornado.httpclient;
class transport(ssession.mem_transport):
        # retrieve peer public key form file, database, etc. by peer id
        return pub; 
http_client = tornado.httpclient.HTTPClient();
session=ssession.ssession("client id", client_priv, transport());
try:
    response = http_client.fetch(tornado.httpclient.HTTPRequest(
        "http://127.0.0.1:26260", 
        "POST", 
        None, 
        session.connect_request()));                #send initial message to server
    message=session.unwrap(response.body);          #decrypt accepted message
    while message.is_control:                       #if status==1 then session 
        response = http_client.fetch(tornado.httpclient.HTTPRequest("
        http://127.0.0.1:26260",                    #is not established yet
        "POST", 
        None, 
        message));                                  #send unwrapped message 
                                                    #to server as is
        message = session.unwrap(response.body);    #decrypt accepted message
    response = http_client.fetch(tornado.httpclient.HTTPRequest(
        "http://127.0.0.1:26260", 
        "POST", 
        None, 
        session.wrap("This is test message")));     #wrap and send inform message
    message = session.unwrap(response.body);        #decrypt accepted message
    print message;                                  #print accepted plain message
except tornado.httpclient.HTTPError as e:
    print("Error: " + str(e));
except Exception as e:
    print("Error: " + str(e));
http_client.close();

When built correctly, Themis shouldn't take longer than a couple of minutes to integrate into your software architecture. That's what it was built for.

Getting Themis

is as simple as doing:

git clone https://github.com/cossacklabs/themis.git

Diving deeper

Interested enough to read to the end of this long article? Want to know more?

Dive into official documentation or themis wiki @github

You can send email to [email protected]

You can follow us on cossacklabs@github

And you can follow us on Twitter: cossacklabs@twitter

Subscribe to Kukuruku Hub

Or subscribe with RSS

0 comments

Read Next