Rachna College of Engineering and Technology, Gujranwala
(A Constituent College of UET, Lahore)
Department of Computer Science
Lab 6 [Python Modern Cryptography Basics] [CLO 2]
Learning Objectives:
By the end of this lab, students will be able to:
• Install and configure the cryptography Python library on Kali Linux
• Understand the concepts of basics modern cryptography and AES.
• Implement AES basic mode in Python for encryption and decryption.
Core Terminology:
AES (Advanced Encryption Standard) was adopted by NIST in 2001 after a 5-year public competition. It
replaced DES (Data Encryption Standard) which had become insecure due to its small 56-bit key size. AES
is a symmetric block cipher that operates on 128-bit (16-byte) data blocks with key sizes of 128, 192, or 256
bits.
AES is a substitution-permutation network (SPN) — it alternates layers of substitution (confusion) and
permutation (diffusion), applied over multiple rounds. 128-bit key = 10 rounds; 192-bit = 12 rounds; 256-bit
= 14 rounds. Each round applies four transformations:
Step Description & Purpose
SubBytes Non-linear substitution. Each byte is replaced by a value from a pre-
computed lookup table called the S-Box (Substitution Box). This
provides confusion — makes the relationship between key and
ciphertext complex and non-linear.
ShiftRows Rows of the 4x4 state matrix are cyclically shifted left by different
amounts (0,1,2,3 bytes). This provides diffusion — bytes from
different positions affect each other.
MixColumns Each column of the state is treated as a polynomial and multiplied
by a fixed polynomial over GF(2^8). Provides further diffusion —
changes to one byte affect the entire column.
AddRoundKey The current round key (derived from the original key via Key
Schedule) is XORed with the state. This is where the secret key
influences the encryption. XOR is fast and reversible.
Modes of Operation:
The mode of operation determines how AES (a block cipher) handles messages longer than 16 bytes. The
choice of mode is critical — some modes are catastrophically insecure for certain use cases.
Mode Full Name Security Notes Best Used For
ECB Electronic Codebook NEVER use for real data — Never use
identical plaintext blocks (educational only)
produce identical ciphertext
blocks. Patterns visible!
CBC Cipher Block Chaining Secure if IV is random and File encryption,
unpredictable. Vulnerable to VPNs
padding oracle attacks if not
implemented carefully.
CTR Counter Mode Turns block cipher into stream Network streams,
cipher. Fast, parallelizable. disk encryption
1
CSC-201L Information Security (Lab) Semester Spring 2026
MUST NOT reuse (key,
nonce) pair.
GCM Galois/Counter Mode Provides authenticated TLS 1.3, HTTPS,
encryption (AEAD). Encrypts APIs
AND authenticates in one
pass. Gold standard.
⚠️ Warning
ECB (Electronic Codebook) mode is the most dangerous mode. Because identical 16-
byte plaintext blocks always produce identical ciphertext blocks, structure in the
plaintext leaks into the ciphertext. The famous 'ECB penguin' demonstrates this — an
image of Tux the Linux penguin encrypted with ECB still shows the outline clearly.
Lab Tasks:
Task 1.1 — Install Required Libraries
pip install cryptography --break-system-packages
# The 'cryptography' library provides both high-level recipes and low-level hazmat
primitives
python3 -c "from [Link] import Cipher; print('OK')"
Task 2: AES-CBC Encryption and Decryption
CBC (Cipher Block Chaining) is one of the most widely understood AES modes. Each plaintext block is
XORed with the previous ciphertext block before encryption. The first block is XORed with the
Initialization Vector (IV).
nano ~/aes_cbc.py
#!/usr/bin/env python3
"""AES-CBC Encryption & Decryption with PKCS7 Padding"""
import os
from [Link] import Cipher, algorithms, modes
from [Link] import padding
def aes_cbc_encrypt(plaintext: bytes, key: bytes) -> tuple:
"""
Encrypts plaintext with AES-128-CBC.
Returns (ciphertext, iv) tuple — IV must be stored alongside ciphertext.
"""
# Generate a random 16-byte IV (never reuse!)
iv = [Link](16)
# Apply PKCS7 padding to make plaintext a multiple of 16 bytes
padder = padding.PKCS7(128).padder() # 128 = block size in bits
padded_data = [Link](plaintext) + [Link]()
# Create AES cipher in CBC mode
cipher = Cipher([Link](key), [Link](iv))
encryptor = [Link]()
ciphertext = [Link](padded_data) + [Link]()
return ciphertext, iv
def aes_cbc_decrypt(ciphertext: bytes, key: bytes, iv: bytes) -> bytes:
"""Decrypts AES-128-CBC ciphertext."""
2
CSC-201L Information Security (Lab) Semester Spring 2026
cipher = Cipher([Link](key), [Link](iv))
decryptor = [Link]()
padded_plaintext = [Link](ciphertext) + [Link]()
# Remove PKCS7 padding
unpadder = padding.PKCS7(128).unpadder()
plaintext = [Link](padded_plaintext) + [Link]()
return plaintext
if __name__ == '__main__':
# AES-128 requires exactly 16 bytes, AES-256 requires 32 bytes
key = [Link](16) # 128-bit key — use [Link] for cryptographic keys!
message = b'Top Secret Message: AES CBC Demo'
print(f'Plaintext : {message}')
print(f'Key (hex) : {[Link]()}')
ciphertext, iv = aes_cbc_encrypt(message, key)
print(f'IV (hex) : {[Link]()}')
print(f'Ciphertext: {[Link]()}')
print(f'CT length : {len(ciphertext)} bytes (padded to block boundary)')
recovered = aes_cbc_decrypt(ciphertext, key, iv)
print(f'Decrypted : {recovered}')
print(f'Match : {message == recovered}')
python3 ~/aes_cbc.py
📝 Note
PKCS7 padding appends N bytes each with value N. If the plaintext is already a multiple of the block size, a
full extra block of padding (16 bytes of value 0x10) is appended. This ensures the unpadder can always
unambiguously remove padding.
<<Good Luck>>
3
CSC-201L Information Security (Lab) Semester Spring 2026