AES 256 Encryption and Decryption in Python

The following python program demonstrates how to perform AES 256 encryption and decryption using the pycrypto library. Please note that this example is written in Python 3.

First ensure that pycrypto library is installed on your system by running the following command,

pip3 install pycrypto

In the following python 3 program, we use pycrypto classes for AES 256 encryption and decryption. The program asks the user for a password (passphrase) for encrypting the data. This passphrase is converted to a hash value before using it as the key for encryption. The following program encrypts a sample text and then prints both the encrypted message and decrypted message on the console.

# AES 256 encryption/decryption using pycrypto library

import base64
import hashlib
from Crypto.Cipher import AES
from Crypto import Random

BLOCK_SIZE = 16
pad = lambda s: s + (BLOCK_SIZE - len(s) % BLOCK_SIZE) * chr(BLOCK_SIZE - len(s) % BLOCK_SIZE)
unpad = lambda s: s[:-ord(s[len(s) - 1:])]

password = input("Enter encryption password: ")


def encrypt(raw, password):
    private_key = hashlib.sha256(password.encode("utf-8")).digest()
    raw = pad(raw)
    iv = Random.new().read(AES.block_size)
    cipher = AES.new(private_key, AES.MODE_CBC, iv)
    return base64.b64encode(iv + cipher.encrypt(raw))


def decrypt(enc, password):
    private_key = hashlib.sha256(password.encode("utf-8")).digest()
    enc = base64.b64decode(enc)
    iv = enc[:16]
    cipher = AES.new(private_key, AES.MODE_CBC, iv)
    return unpad(cipher.decrypt(enc[16:]))


# First let us encrypt secret message
encrypted = encrypt("This is a secret message", password)
print(encrypted)

# Let us decrypt using our original password
decrypted = decrypt(encrypted, password)
print(bytes.decode(decrypted))

Here is the above program in action,

python3 aes_encryption.py
Enter encryption password: my password
b’sYjpPpTpPFSvdsvhTRQrNnyD669siUFtpziX8JrdFDF1zM9PF8kWbjDUnC9uS7lp’
This is a secret message

Note that the above program uses SHA256 algorithm to generate the key from the passphrase. If you want high level of security, this should be replaced with password based key derivation function PBKDF2. The following example uses the PBKDF2 to generate the key,

# AES 256 encryption/decryption using pycrypto library

import base64
from Crypto.Cipher import AES
from Crypto import Random
from Crypto.Protocol.KDF import PBKDF2

BLOCK_SIZE = 16
pad = lambda s: s + (BLOCK_SIZE - len(s) % BLOCK_SIZE) * chr(BLOCK_SIZE - len(s) % BLOCK_SIZE)
unpad = lambda s: s[:-ord(s[len(s) - 1:])]

password = input("Enter encryption password: ")


def get_private_key(password):
    salt = b"this is a salt"
    kdf = PBKDF2(password, salt, 64, 1000)
    key = kdf[:32]
    return key


def encrypt(raw, password):
    private_key = get_private_key(password)
    raw = pad(raw)
    iv = Random.new().read(AES.block_size)
    cipher = AES.new(private_key, AES.MODE_CBC, iv)
    return base64.b64encode(iv + cipher.encrypt(raw))


def decrypt(enc, password):
    private_key = get_private_key(password)
    enc = base64.b64decode(enc)
    iv = enc[:16]
    cipher = AES.new(private_key, AES.MODE_CBC, iv)
    return unpad(cipher.decrypt(enc[16:]))


# First let us encrypt secret message
encrypted = encrypt("This is a secret message", password)
print(encrypted)

# Let us decrypt using our original password
decrypted = decrypt(encrypted, password)
print(bytes.decode(decrypted))

How to Calculate MD5 Hash of a File in Python

MD5 is a message digest algorithm used to create a unique fixed size value from variable input data. MD5 is commonly used to check whether a file is corrupted during transfer or not (in this case the hash value is known as checksum). Any change in the file will lead to a different MD5 hash value.

The following Python program computes MD5 hash of a given file. The computed 128 bit MD5 hash is converted to readable hexadecimal form.

# Python program to find MD5 hash value of a file
import hashlib

filename = input("Enter the file name: ")
with open(filename,"rb") as f:
    bytes = f.read() # read file as bytes
    readable_hash = hashlib.md5(bytes).hexdigest();
    print(readable_hash)

Note that the above program may fail for large input files since we read the entire file to memory before computing the MD5 hash. The following python program is an improved version capable of handling large files,

# Python program to find MD5 hash value of a file
import hashlib

filename = input("Enter the file name: ")
md5_hash = hashlib.md5()
with open(filename,"rb") as f:
    # Read and update hash in chunks of 4K
    for byte_block in iter(lambda: f.read(4096),b""):
        md5_hash.update(byte_block)
    print(md5_hash.hexdigest())

Here is the above program is action,

python3 md5hash2.py
Enter the file name: md5hash2.py
0101ae2ac06b8a52154100e37d8bafea

How to Bubble Sort Numbers in Python

The following python program uses the bubble algorithm to sort a list of numbers. The program allows the user to input the list of numbers from the console. Please note that bubble sort is a very inefficient algorithm and hence is not recommended in production code with large data.

# Bubble sort in python
# Sorts numbers in ascending order
str_input = input("Please enter numbers separated by spaces: ")

# split the string into numbers & create a list of numbers
numbers = [int(x) for x in str_input.split()]

count = len(numbers)

for outer in range(count-1): # bubbles each number to the end
    for i in range(count-outer-1):
        if numbers[i] > numbers[i+1]:
            # swap numbers!
            numbers[i],numbers[i+1] = numbers[i+1],numbers[i]

print(numbers)

The above program asks the user to enter a list of numbers separated by spaces. This is split into individual numbers using the split() function and then converted to a list of numbers using the int() function and list comprehension.

The program then uses two nested loops to sort the numbers. The outer loop runs as many times as the numbers in the list. For each inner loop iteration, the largest number is bubbled to the right. Hence for each outer loop iteration, we get the next large number bubbled to the right.  Note that we are using a tuple assignment in python to swap two values in the list. There is no need for a temporary variable for swapping variable values.

Here is the sample output from the program,

python3 bubblesort.py
Please enter numbers separated by spaces: 8 129 22 42 22 1
[1, 8, 22, 22, 42, 129]

How to Add Two Matrices in Python

The following program demonstrates how two matrices can be added in python using the list data structure. Matrix addition works by adding corresponding entries in the matrices based on their position. The following sample program adds two 3×3 matrices, but the program can be easily modified for any size matrix. You just need to change the input data,

# matrixadd.py - Matrix addition in python
# The following example adds two 3x3 matrices
m1 = [
    [9, 2, 2],
    [2, 4, 2],
    [9, 9, 9]
]

m2 = [
    [10,1,2],
    [4,2,1],
    [9,3,4]
]

result = [] # start with outer list

for i in range(len(m1)):
    result.append([]) # add the inner list
    for j in range(len(m1[0])):
        result[i].append(m1[i][j] + m2[i][j])

print(result)

Here is a step by step explanation of the program,

  • Matrices are stored in two dimensional list variables.
  • We create a simple empty list for the result.
  • We then iterate through the matrix values. The outer loop iterates through the number of rows. The inner loop iterates through the number of columns.
  • For each row iterated, we add an empty inner list for values in the result variable.
  • We finally compute the sum for each corresponding elements in matrices and then append it to the inner list for each row of the result.

Following is the output from the above program,

python3 matrixadd.py
[[19, 3, 4], [6, 6, 3], [18, 12, 13]]

How to Reverse a Number in Python

The following python program reverses a given multi-digit number. In this example, we simply print the digits in reverse order without removing redundant zeros. For example, if the input number is "1000", the reversed number displayed will be "0001" instead of "1".

number = int(input("Enter a number: "))
reverse_number = ''

while number > 0:
    last_digit = number % 10
    reverse_number = reverse_number + str(last_digit)
    number = number // 10

print("Reverse number is: ", reverse_number)

The above program uses the following logic to reverse the number,

  1. Extract the last digit using the modulus operator (Remainder of a number after dividing by 10)
  2. Add the last digit as the first digit in the reversed string
  3. Now remove the last digit from the original number dividing it with 10 (note the use of integer division operator //. The / operator if used will return a fraction!)
  4. Repeat from step 1 until the original number has no remaining digits

The following program uses a slightly different approach. In this example, we store the reversed number as an integer instead of a string. This ensures that when we reverse "1000", we get "1" instead of "0001". Note that before adding the last digit we multiply the previous number by 10 to increase its place value.

number = int(input("Enter a number: "))
reverse_number = 0

while number > 0:
    last_digit = number % 10
    reverse_number = reverse_number*10 + last_digit
    number = number // 10

print("Reverse number is: ", reverse_number)

The output of the program when run from console,

Enter a number: 9899
Reverse number is:  9989