We are proud to present Themis, a novel cryptographic services library.
Every good work of software starts by scratching a developer's personal itch. (The Cathedral and the Bazaar)
What is Themis?
Themis is a high-level cryptographic services library: a library that provides easy to use, highly abstracted set of functions for solving 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 the building blocks of cryptosystems, 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 such instruments 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, etc. 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. 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 an 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 that implement some specific security procedure each. 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 the ease of use. Each high level language interface is tested against 'native' programmers' expectations. Code style and syntactic sugar are adjusted according to the 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 the best practices 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 whichever 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 the 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 (the 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 what the client side will look like:
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.
is as simple as doing:
git clone https://github.com/cossacklabs/themis.git
Interested enough to read to the end of this long article? Want to know more?
- Dive into the official documentation or themis wiki @github
- You can send an email to firstname.lastname@example.org
- You can follow us on cossacklabs@github
- And you can follow us on Twitter: cossacklabs@twitter
P.S. If you're looking for new ideas, this is the right place. If you're looking to implement security, talk to us, we can help. If you're looking for ready-made solutions, consider also looking into Acra, Hermes, or Toughbase .