Overview

The best way to learn is by doing. In cryptography, we need to deal with big number which may not have native language support. The earliest comprehensive library is http://read.pudn.com/downloads85/sourcecode/crypt/325570/examples/onb/DH.example/onb.c__.htm and http://www.amazon.com/Implementing-Elliptic-Cryptography-Michael-Rosing/dp/1884777694.

There are plenty of c library, like Miracl, PBC, OpenssL, Nacl, libsodium, etc. On the other hand, the low level routine like gmp, ntl, flint, gnugp are also popular. We will however focus on full open source LibTom project http://www.libtom.net/ and ocassionally use Miracl or others.

The decision of choosing LibTom is its code is written for novice or student and it has accompanied book http://shop.oreilly.com/product/9781597491129.do and https://goo.gl/p2QWJt. Of course there is open tex file for each subprojects and a complete book called Tommath.pdf in the archieve file.

Though it has built-in support for long integer. The cryptography modules inside python are not as plentiful as other fields like machine learning or network secruity (see https://lwn.net/Articles/595790/). To the best of our knowledge, the sympy provides somewhat complete cryptography tools http://docs.sympy.org/dev/_modules/sympy/crypto/crypto.html.

If you would like to get a flavor of crypto, sage may be a good choice, and there are relative plenty source for it http://www.sagemath.org/library-publications.html#books.

However, in this tutorial I will use pycrtpo and cryptography instead since it is directly builds upon python, and also contains a collections of great toolkit. See https://www.dlitz.net/software/pycrypto/doc/ and https://cryptography.io/en/latest/

Other python biding like pynacl may also be helpful, keep track with it !!

Pycrypto

How can we do encryption (only pairing x)

In [10]:
from Crypto.Cipher import AES
key = 'starpasswordhere'
plaintext = 'Martinet is god!'
 
encobj = AES.new(key, AES.MODE_ECB)
ciphertext = encobj.encrypt(plaintext)

print ciphertext.encode('hex') # For read friendly
292138362368e0cdd76508781b3f3b82

You might have noticed that the length of hex-encoded ciphertext is 32 characters. By encoding it in hex, we've doubled the size because each binary character is represented by two hex characters, thus the actual ciphertext is only 16 characters

The common encoding way in cryptography is base64 (which is the same as many other applications), see http://blog.rlr-uk.com/2011/03/base64-encoding-is-not-cryptography.html for the reason

You may notice that we could not change the size of key and plaintext arbitrary in this example, we will relax this constraint by padding and utilizing so called KDF (key derivation function) in later sections

In [11]:
import binascii
 
key = 'starpasswordhere'
ciphertext = binascii.unhexlify('292138362368e0cdd76508781b3f3b82')
 
decobj = AES.new(key, AES.MODE_ECB)
plaintext = decobj.decrypt(ciphertext)
 
# Resulting plaintext
print plaintext
Martinet is god!

Cryptography

Let's see another well-documented toolbox cryptography (exactly the name!!)

In [14]:
from cryptography.hazmat.primitives.ciphers import (
    Cipher, algorithms, modes
)
from cryptography.hazmat.backends import default_backend
key = 'starpasswordhere'
plaintext = 'Martinet is god!'
encryptor = Cipher(algorithms.AES(key),modes.ECB(),backend=default_backend()).encryptor()
ciphertext = encryptor.update(plaintext) + encryptor.finalize()
print ciphertext.encode('hex') 
292138362368e0cdd76508781b3f3b82
In [17]:
decryptor = Cipher(algorithms.AES(key), modes.ECB(), backend=default_backend()).decryptor()
plaintext = decryptor.update(ciphertext) + decryptor.finalize()
print plaintext
Martinet is god!
In [ ]: