AppDividend
Latest Code Tutorials

Encryption And Decryption in Python: Pycrypto Guide

Pycrypto is a Python module that provides cryptographic services. The complete form of Pycrypto is Python Cryptography Toolkit. Pycrypto module is a collection of secure hash functions such as RIPEMD160, SHA256, and various encryption algorithms such as AES, DES, RSA, ElGamal, etc. For example, AES is very fast and reliable and is the de facto standard for symmetric encryption.

AES Encryption

The Advanced Encryption Standard (AES) is the symmetric block cipher. 

AES includes three block ciphers:

  1. AES-128
  2. AES-192
  3. AES-256

AES-128 uses the 128-bit key length to encrypt and decrypt a block of messages, AES-192 uses the 192-bit key length, and AES-256 uses a 256-bit key length to encrypt and decrypt the messages.

Each cipher encrypts and decrypts the data in blocks of 128 bits using cryptographic keys of 128, 192, and 256 bits.

Symmetric, aka a secret key, ciphers use the same key for the encrypting and decrypting, so the sender and the receiver must both know — and use — the same secret key.

All key lengths can be used to protect a Confidential and Secret level. Top Secret information requires either 192-bit or 256-bit key lengths.

In this example, we will see the AES encryption and decryption of the 16-byte text.

Steps to create encryption and decryption in Python

To use AES Encryption and Decryption in Python, we have to follow the below steps.

  1. Generating a secret key.
  2. Generating an initialization vector.
  3. Create an AES Cipher.
  4. Encrypt the message with AES
  5. Decrypt the message

Generating a secret key

AES encryption needs a strong key. The stronger the key, the stronger your encryption. This is probably the weakest link in the chain. To generate a secret key, we will use the Python os module’s urandom() method.

Python os.urandom() function is used to generate the string of size random bytes suitable for cryptographic use, or we can say this method generates the string containing random characters.

from os import urandom

secret_key = urandom(16)
print(secret_key)

Output

b'I\xff\xd5\xbb3\xae\xd7\xd8\x9c\xf1\xc3}\x8d\xd0*\x1a'

So, our secret_key has been generated. You have to generate a strong key for AES Encryption.

Let’s head to the next step.

Generating an initialization vector

The main purpose of the initialization vector is to produce different encrypted data so that an attacker cannot use cryptanalysis to infer key data or message data.

We will generate the initialization vector using the os.urandom() function.

from os import urandom

iv = urandom(16)
print(iv)

Output

b"NU\x95c'pfc\xe9\xc0X\x81\xd8\x13\x18("

So, our iv has been generated.

The initialization vector must be transmitted to the receiver for proper decryption, but it need not be kept secret. Instead, it is packed into the output file at the beginning (after 8 bytes of the original file size), so the receiver can read it before decrypting the actual data.

Create an AES cipher

We now create the AES cipher and use it for encrypting a string (or a set of bytes; the data need not be text only).

The AES cipher is created with CBC Mode, wherein each block is “chained” to the previous block in the stream. (You do not have to know the exact details unless interested. All you need to know is – to use CBC mode).

Also, for AES encryption using pycrypto, you have to ensure that the data is a multiple of 16-bytes in length. Pad the buffer if it is not and include the size of the data at the beginning of output so that the receiver can decrypt adequately.

See the following code.

from os import urandom
from Crypto.Cipher import AES

# For Generating AES Cipher text
secret_key = urandom(16)
iv = urandom(16)
obj = AES.new(secret_key, AES.MODE_CBC, iv)

In the above code, we have generated two imported modules.

  1. urandom
  2. AES

To generate the AES cipher object, we have to use the AES.new() method.

Now, AES.new() method takes three parameters.

  1. secret_key
  2. AES.MODE.CBC
  3. iv

AES.MODE.CBC is one of the classic modes of operation for symmetric block ciphers.

Classic modes of operation for symmetric block ciphers

Module’s constants for the modes of operation supported with AES:

MODE_ECB: Electronic Code Book (ECB)
MODE_CBC: Cipher-Block Chaining (CBC)
MODE_CFB: Cipher Feedback (CFB)
MODE_OFB: Output Feedback (OFB)
MODE_CTR: Counter Mode (CTR)
MODE_OPENPGP: OpenPGP Mode
MODE_CCM: Counter with CBC-MAC (CCM) Mode
MODE_EAX: EAX Mode
MODE_GCM: Galois Counter Mode (GCM)
MODE_SIV: Syntethic Initialization Vector (SIV)
MODE_OCB: Offset Code Book (OCB)

Encrypt the message with AES

This is the final step of AES encryption.

We will first define the message that needs to be encrypted, and then we will use AES.encrypt() function.

from os import urandom
from Crypto.Cipher import AES

# For Generating cipher text
secret_key = urandom(16)
iv = urandom(16)
obj = AES.new(secret_key, AES.MODE_CBC, iv)

# Encrypt the message
message = 'Lorem Ipsum text'
print('Original message is: ', message)
encrypted_text = obj.encrypt(message)
print('The encrypted text', encrypted_text)

Output

Original message is:  Lorem Ipsum text
The encrypted text b'a\xc4+(\xb2\x15\x92\x93\x17\x8c\x01\x8a\xba\xe6\xff5'

That is it. We have encrypted the message using AES in Python.

Decrypt the message in Python

Decryption requires the key that the data was encrypted with. Then, you need to send the key to the receiver using a secure channel.

We will use AES’s decrypt() method to decrypt the encrypted message and get back our original text.

from os import urandom
from Crypto.Cipher import AES

# For Generating cipher text
secret_key = urandom(16)
iv = urandom(16)
obj = AES.new(secret_key, AES.MODE_CBC, iv)

# Encrypt the message
message = 'Lorem Ipsum text'
print('Original message is: ', message)
encrypted_text = obj.encrypt(message)
print('The encrypted text', encrypted_text)

# Decrypt the message
rev_obj = AES.new(secret_key, AES.MODE_CBC, iv)
decrypted_text = rev_obj.decrypt(encrypted_text)
print('The decrypted text', decrypted_text.decode('utf-8'))

Output

Original message is:  Lorem Ipsum text
The encrypted text b'\xc8\x01\x14y\xeb\xb9\xa4#\xd5bQ\xeb\xe0\x00"\t'
The decrypted text Lorem Ipsum text

That is it. We get the original text.

So, this is how you encrypt and decrypt the string in Python.

See also

Python hash()

Python uuid

Generate a random number in Python

2 Comments
  1. Randall Shane PhD says

    FYI: This produces the error: TypeError: Only byte strings can be passed to C code. If you try to solve it by encoding the message, CBC fails with ValueError: Error 3 while encrypting in CBC mode. You might want to take a look as there is no padding function available to solve! Both encoding of the message object (as bytes) and a padding function (for non 16b length) are necessary for crypto to actually work.

  2. Randall Shane PhD says

    …The solution is:

    PAD = lambda s: s + (32 – len(s) % 32) * ‘ ‘
    encrypted_text = obj.encrypt(PAD(message).encode(“utf-8”))

    …this rectifies the message length and subsequently encodes before encrypting. Decryption functions as shown. Happy Encrypting… [R]

Leave A Reply

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.