Introducing Themis

Information Security

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:

  • Secure Message: a simple encrypted messaging solution applicable to a wide range of applications.
  • Secure Session: a safer, session-oriented messaging solution with better security attributes (at the cost of some stricter demands in its implementation).
  • Secure Cell: a multi-mode encrypted container, suitable for storing anything from encrypted files to database records and format-preserved strings.

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:

  • Secure Message: a sequence-independent, stateless, contextless messaging system. Works best for cases which are low-bandwidth and don’t require frequent sequential message exchange or complex APIs.
  • Secure Session: a sequence and session dependent, stateful messaging system. This works best for RPC, IPC, message and data exchange, socket-like datagram and event-passing layouts.
  • Secure Cell: a multi-mode protected data container, can be used on files, SQL records or any form of structured data record.

What sets Themis apart

  • Themis is simple. Themis is built around ease of use. Each high level language interface is tested against ‘native’ programmers expectations. Code style and syntax sugar are adjusted according to best practices of each language and validated by our security team so that usability doesn’t impact security.
  • Themis is modern. The design of our cryptographic stack and our approach to implementation and modularity is intended to reflect best practice in current cryptography using algorithms and techniques based on their track record and risk assessments based on modern attack scenarios.
  • Themis is widely available. The set of high-level languages, in which Themis is available, will grow with each release. We will also be adding more platforms and architectures. Themis is written in ANSI C and designed to build everywhere so if Themis is not available for your platform right now — it will be soon.
  • Themis is mobile, server or anything you make it. Themis is already multi-platform, available for mobile clients, servers or however way you choose to use it. Themis can be used in any network layout. It is threaded and concurrency-friendly.
  • Themis is built with users’ needs in mind. We’ve been in the ‘consumer’ developer’s chair for quite some time using all kinds of less-than-perfect tools.

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

Comments

    3,751

    Ropes — Fast Strings

    Most of us work with strings one way or another. There’s no way to avoid them — when writing code, you’re doomed to concatinate strings every day, split them into parts and access certain characters by index. We are used to the fact that strings are fixed-length arrays of characters, which leads to certain limitations when working with them. For instance, we cannot quickly concatenate two strings. To do this, we will at first need to allocate the required amount of memory, and then copy there the data from the concatenated strings.