Python is a great programming language for data analysis, web development, networking and more. While working with data , storing in files, sending to a remote machine and so on, we sometimes need to encrypt the data to prevent unauthorised access.

With python cryptographic packages we can encrypt and decrypt data using various methods , we can also sign data, create hash , use secure communication and more. In this post I’m using PyCrypto package but there are more packages you can use to do the same (less or more)

Installing PyCrypto

# pip install pycrypto 1 # pip install pycrypto

PyCrypto package supports encryption and decryption with symmetric and asymmetric algorithm , hashing with various methods, digital signature, random numbers and more.

Symmetric Encryption

The simplest way to encrypt and decrypt data is to use a symmetric encryption. We need to create a key for any pair. To encrypt and decrypt the data we use the same key:

Plain Text + Key ==> Cipher Text

Cipher Text + Key ==> Plain Text

It is very easy to create a new symmetric algorithm , for example – change every second bit (1 => 0 , 0 => 1) . The big challenge is to create algorithm that will not simply hacked.

Generally a good algorithm should be easy to use (encryption and decryption) and hard to hack

Example – AES

To use AES we need to create Key and IV (initalization vector). the Key is shared between the pair , The IV can be different for each message.

from Crypto.Cipher import AES key = b'ABCDEFGHIJ123456' iv = b'1234567890ZYXWVU' cipher = AES.new(key, AES.MODE_CFB, iv) data = 'hello world' msg = iv + cipher.encrypt(data) 1 2 3 4 5 6 7 8 from Crypto . Cipher import AES key = b 'ABCDEFGHIJ123456' iv = b '1234567890ZYXWVU' cipher = AES . new ( key , AES . MODE_CFB , iv ) data = 'hello world' msg = iv + cipher . encrypt ( data )

Now the other side need the key to decrypt the message using the same Key and IV:

plain=cipher.decrypt(msg) print (plain[16:]) 1 2 3 plain = cipher . decrypt ( msg ) print ( plain [ 16 : ] )

We skip the IV to print the data

Other symmetric algorithms available in PyCrypto are DES, 3DES, RC2, RC4 and more – see Crypto.Cipher module documentation for details

Asymmetric Encryption

The big problem with symmetric encryption is how to share the keys between each pair. We can’t send it over the network in plain text because any “men in a middle” can read it. We need a secure way to exchange the keys.

Asymmetric encryption works with 2 keys for each side – private key that we need to save and never send it to anyone and public key that we can publish anywhere. The data that we encrypt with one key can only be decrypted with the other key so if someone wants to send me a message , he encrypt the message with my public key, to decrypt it back i need to use my private key

Example – RSA

Every user has a private and public key pair , minimum 512 bit. To generate key pair we need:

Choose 2 prime numbers (big) : Q, P

N = Q * P

Maximum message length we can encrypt is log(N)

Z = (P – 1) * (Q – 1)

Find E coprime to Z (that is gcd(Z,E) = 1)

Find D such as D*E=1 mod Z

E and D are the private and public keys

Encrypt using (message ^ E) mod N

Decrypt using (message ^ D) mod N

Example with numbers (very simple):

P=5

Q=11

N = P*Q =55

k<log(55) = 5 – maximum message length is 5 bit

Z=(P-1)*(Q-1)=40

E=13

D=37

D*E=481 => 481 mod 40 = 1

If we want to send the message ‘11010’ (26)

We are using the public key (13)

26^13 mod 55 = 31 (‘11111’)

send ‘11111’ to the other side

The other side has the private key (37)

31^37 mod 55 = 26

Using PyCrypto

First we generate the key pair

from Crypto.PublicKey import RSA key = RSA.generate(2048) 1 2 from Crypto . PublicKey import RSA key = RSA . generate ( 2048 )

export the public key to pem file and send it to the other side:

f = open('mykey','w') f.write(key.exportKey('<em>OpenSSH</em>')) f.close() 1 2 3 f = open ( 'mykey' , 'w' ) f . write ( key . exportKey ( '<em>OpenSSH</em>' ) ) f . close ( )

The other side open the file and encrypt data to send:

f = open('mykey.pem','r') clientkey = RSA.importKey(f.read()) encdata = clientkey.encrypt("hello python",10) 1 2 3 f = open ( 'mykey.pem' , 'r' ) clientkey = RSA . importKey ( f . read ( ) ) encdata = clientkey . encrypt ( "hello python" , 10 )

To decrypt encdata to plain text use:

t=key.decrypt(encdata) print (t) # hello python 1 2 t = key . decrypt ( encdata ) print ( t ) # hello python

Hashing

Hashing is “one way” algorithm. You can produce hash from data but you can’t do the opposite. Hashing is useful if we want to make sure the source was not tampered. For example , if you download a package from the web, you can check the hash and compare it with the reported hash provided by the author. If someone changed the package the hashing will be different

For example, if you want to download the Linux kernel source , we want to make sure that the hacker didn’t change the original code and made a security hole to help him attack the product later. So we can download also the hashing file and check the source to see the both equal

You need to download the pgp file and compare it with the generated hash

To use hashing with PcCrypto choose one of the supported algorithms: SHA, MD5 and more

Example

from Crypto.Hash import SHA256 h=SHA256.new() h.update('hello') h.hexdigest() 1 2 3 4 5 from Crypto . Hash import SHA256 h = SHA256 . new ( ) h . update ( 'hello' ) h . hexdigest ( )

Digital signature

If A wants to send data to B, he need to encrypt it using B public key. The problem we need to solve is – how B can be sure he got the message from A? The solution is signing the message with A private key:

Encrypt the message with B public key

Encrypt the result with A private key

Send to B

B uses A public key to decrypt the message and then its private key to get the plain text

To use digital signature with PyCrypto use DSA class