Practical 1: Implementing Substitution and Transposition
Ciphers
Objective: Understand classical encryption techniques by implementing substitution and
transposition ciphers.
Procedure:
1. Implement a Caesar Cipher (shift cipher) as an example of a substitution cipher.
2. Implement a simple transposition cipher.
3. Encrypt and decrypt a given message with both ciphers.
Solution:
# Caesar Cipher
def caesar_cipher(text, shift):
encrypted_text = ""
for char in text:
if char.isalpha():
shift_amount = 65 if char.isupper() else 97
encrypted_text += chr((ord(char) - shift_amount + shift) % 26 + shift_amount)
else:
encrypted_text += char
return encrypted_text
# Simple Transposition Cipher
def transposition_cipher(text, key):
matrix = ['' for _ in range(key)]
for index, char in enumerate(text):
matrix[index % key] += char
return ''.join(matrix)
# Test
plain_text = "HELLO WORLD"
print("Caesar Cipher Encrypted:", caesar_cipher(plain_text, 3))
print("Transposition Cipher Encrypted:", transposition_cipher(plain_text, 3))
Expected Output:
• Caesar Cipher Encrypted: "KHOOR ZRUOG"
• Transposition Cipher Encrypted: "HOEWR LL D"
Practical 2: Cryptanalysis of Substitution Ciphers
Objective: Use frequency analysis to break a Caesar Cipher.
Procedure:
1. Encrypt a message using a Caesar Cipher.
2. Implement a frequency analysis algorithm to attempt cracking the cipher without knowing the
shift.
Solution:
# Caesar Cipher Encryption
def caesar_encrypt(text, shift):
encrypted = ""
for char in text:
if char.isalpha():
shift_amount = 65 if char.isupper() else 97
encrypted += chr((ord(char) - shift_amount + shift) % 26 + shift_amount)
else:
encrypted += char
return encrypted
# Frequency Analysis Attack
def frequency_attack(cipher_text):
for shift in range(26):
decrypted = caesar_encrypt(cipher_text, -shift)
print(f"Shift {shift}: {decrypted}")
# Test
cipher_text = caesar_encrypt("HELLO WORLD", 5)
print("Encrypted Text:", cipher_text)
frequency_attack(cipher_text)
Expected Output:
• Various attempts of decrypted text for each shift value. The original text will appear at shift = 5.
Practical 3: Implementing Stream Cipher (Vernam Cipher)
Objective: Implement and understand the working of a Vernam cipher (XOR-based stream cipher).
Procedure:
1. Write a function that uses the XOR operation to encrypt and decrypt a message.
2. Use a one-time pad of the same length as the message for encryption.
Solution:
def vernam_cipher(text, key):
encrypted_text = ''.join([chr(ord(t) ^ ord(k)) for t, k in zip(text, key)])
return encrypted_text
# Test
plain_text = "HELLO"
key = "XMCKL"
cipher_text = vernam_cipher(plain_text, key)
print("Encrypted Text:", cipher_text)
decrypted_text = vernam_cipher(cipher_text, key)
print("Decrypted Text:", decrypted_text)
Expected Output:
• Encrypted Text: (garbled text due to XOR)
• Decrypted Text: HELLO
Practical 4: Implementing Block Cipher (Simple DES)
Objective: Understand the basic structure of block ciphers by implementing a simplified version of
DES.
Procedure:
1. Implement a simplified DES algorithm with initial and final permutations.
2. Encrypt and decrypt a message using the algorithm.
Solution:
# Simplified DES example with XOR
def simple_des(text, key):
return ''.join([chr(ord(a) ^ ord(b)) for a, b in zip(text, key)])
# Test
plain_text = "HELLO"
key = "XMCKL"
cipher_text = simple_des(plain_text, key)
print("Encrypted Text:", cipher_text)
decrypted_text = simple_des(cipher_text, key)
print("Decrypted Text:", decrypted_text)
Expected Output:
• Encrypted Text: (garbled text)
• Decrypted Text: HELLO
Practical 5: Understanding and Implementing AES Encryption
Objective: Study AES structure and implement a basic version of the AES algorithm using Python’s
cryptography library.
Solution:
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.backends import default_backend
import os
def aes_encrypt(plain_text, key):
iv = os.urandom(16) # Generate a random IV
cipher = Cipher(algorithms.AES(key), modes.CFB(iv), backend=default_backend())
encryptor = cipher.encryptor()
return iv + encryptor.update(plain_text.encode()) + encryptor.finalize()
def aes_decrypt(cipher_text, key):
iv = cipher_text[:16]
cipher_text = cipher_text[16:]
cipher = Cipher(algorithms.AES(key), modes.CFB(iv), backend=default_backend())
decryptor = cipher.decryptor()
return decryptor.update(cipher_text) + decryptor.finalize()
# Test
key = os.urandom(32) # AES-256
plain_text = "Hello AES!"
cipher_text = aes_encrypt(plain_text, key)
print("Encrypted Text:", cipher_text)
print("Decrypted Text:", aes_decrypt(cipher_text, key).decode())
Expected Output:
• Encrypted Text: (binary encoded string)
• Decrypted Text: Hello AES!
Practical 6: Multiple Encryption Techniques and Triple DES
Objective: Implement and understand the working of multiple encryption and Triple DES using
Python’s pycryptodome library.
Solution:
from Crypto.Cipher import DES3
from Crypto.Random import get_random_bytes
def triple_des_encrypt_decrypt(text):
key = DES3.adjust_key_parity(get_random_bytes(24))
cipher = DES3.new(key, DES3.MODE_ECB)
padded_text = text + (8 - len(text) % 8) * ' '
encrypted_text = cipher.encrypt(padded_text.encode())
decrypted_text = cipher.decrypt(encrypted_text).decode().strip()
return encrypted_text, decrypted_text
# Test
plain_text = "Hello 3DES"
encrypted, decrypted = triple_des_encrypt_decrypt(plain_text)
print("Encrypted Text:", encrypted)
print("Decrypted Text:", decrypted)
Expected Output:
• Encrypted Text: (binary encoded string)
• Decrypted Text: Hello 3DES
Practical 7: Implementing Electronic Code Book (ECB) and
Cipher Block Chaining (CBC) Modes
Objective: Understand and implement ECB and CBC block cipher modes using AES.
Solution:
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
from Crypto.Random import get_random_bytes
def aes_ecb_encrypt_decrypt(text, key):
cipher = AES.new(key, AES.MODE_ECB)
encrypted = cipher.encrypt(pad(text.encode(), AES.block_size))
decrypted = unpad(cipher.decrypt(encrypted), AES.block_size).decode()
return encrypted, decrypted
def aes_cbc_encrypt_decrypt(text, key):
iv = get_random_bytes(AES.block_size)
cipher = AES.new(key, AES.MODE_CBC, iv)
encrypted = iv + cipher.encrypt(pad(text.encode(), AES.block_size))
decrypted = unpad(AES.new(key, AES.MODE_CBC,
encrypted[:AES.block_size]).decrypt(encrypted[AES.block_size:]), AES.block_size).decode()
return encrypted, decrypted
# Test
key = get_random_bytes(16) # AES-128
plain_text = "Hello ECB and CBC"
ecb_encrypted, ecb_decrypted = aes_ecb_encrypt_decrypt(plain_text, key)
cbc_encrypted, cbc_decrypted = aes_cbc_encrypt_decrypt(plain_text, key)
print("ECB Encrypted:", ecb_encrypted)
print("ECB Decrypted:", ecb_decrypted)
print("CBC Encrypted:", cbc_encrypted)
print("CBC Decrypted:", cbc_decrypted)
Expected Output:
• ECB Encrypted: (binary encoded string)
• ECB Decrypted: Hello ECB and CBC
• CBC Encrypted: (binary encoded string)
• CBC Decrypted: Hello ECB and CBC
Practical 8: RSA Cryptosystem Implementation
Objective: Implement RSA encryption and decryption.
Solution:
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_OAEP
def rsa_encrypt_decrypt(message):
key = RSA.generate(2048)
public_key = key.publickey()
encryptor = PKCS1_OAEP.new(public_key)
encrypted = encryptor.encrypt(message.encode())
decryptor = PKCS1_OAEP.new(key)
decrypted = decryptor.decrypt(encrypted).decode()
return encrypted, decrypted
# Test
message = "Hello RSA!"
encrypted_message, decrypted_message = rsa_encrypt_decrypt(message)
print("Encrypted Message:", encrypted_message)
print("Decrypted Message:", decrypted_message)
Expected Output:
• Encrypted Message: (binary encoded string)
• Decrypted Message: Hello RSA!
Practical 9: Implementing Diffie-Hellman Key Exchange
Objective: Demonstrate secure key exchange using Diffie-Hellman.
Solution:
from Crypto.PublicKey import DSA
from Crypto.Random import get_random_bytes
def diffie_hellman_key_exchange():
# Simulate DH Key Exchange
private_key_a = DSA.generate(2048)
public_key_a = private_key_a.publickey()
private_key_b = DSA.generate(2048)
public_key_b = private_key_b.publickey()
shared_secret_a = private_key_a.exchange(public_key_b)
shared_secret_b = private_key_b.exchange(public_key_a)
return shared_secret_a == shared_secret_b
# Test
print("Shared keys match:", diffie_hellman_key_exchange())
Expected Output:
• Shared keys match: True
Practical 10: Hashing with SHA-256
Objective: Implement and test SHA-256 hashing.
Solution:
from hashlib import sha256
def sha256_hash(message):
return sha256(message.encode()).hexdigest()
# Test
message = "Hello SHA-256"
print("SHA-256 Hash:", sha256_hash(message))
Expected Output:
• SHA-256 Hash: (hash output in hex)
Practical 11: Implementing Message Authentication Code (MAC)
Objective: Generate a MAC using HMAC with SHA-256.
Solution:
import hmac
def generate_mac(key, message):
return hmac.new(key.encode(), message.encode(), sha256).hexdigest()
# Test
key = "securekey"
message = "Hello MAC!"
print("MAC:", generate_mac(key, message))
Expected Output:
• MAC: (MAC in hex)
Practical 12: Digital Signatures with RSA
Objective: Sign a message using RSA and verify it.
Solution:
from Crypto.Signature import pkcs1_15
from Crypto.Hash import SHA256
def rsa_sign_verify(message):
key = RSA.generate(2048)
h = SHA256.new(message.encode())
signature = pkcs1_15.new(key).sign(h)
try:
pkcs1_15.new(key.publickey()).verify(h, signature)
return "Signature verified."
except (ValueError, TypeError):
return "Signature verification failed."
# Test
message = "Hello Digital Signature!"
print(rsa_sign_verify(message))
Expected Output:
• Signature verified.
Practical 13: Symmetric Key Distribution using Kerberos
Simulation
Objective: Simulate Kerberos for symmetric key distribution.
Solution: This practical demonstrates the Kerberos authentication concept in a simplified Python
simulation.
1. Setup: Define a Kerberos server, a client, and a ticket-granting server.
2. Key Exchange Simulation: Each component exchanges keys to simulate a real Kerberos
environment.
Python Simulation Code:
import hashlib
def kerberos_simulation(client_secret, server_secret):
# Simulating Kerberos ticket with hashed secret keys
ticket_granting_ticket = hashlib.sha256((client_secret + server_secret).encode()).hexdigest()
client_ticket = hashlib.sha256((ticket_granting_ticket + "session_key").encode()).hexdigest()
return client_ticket
# Test
client_secret = "client_secret"
server_secret = "server_secret"
print("Client Ticket:", kerberos_simulation(client_secret, server_secret))
Expected Output:
• Client Ticket: (Ticket in hexadecimal format)
Practical 14: Creating Self-Signed X.509 Certificates
Objective: Generate and verify a self-signed certificate using Python and OpenSSL.
Steps:
1. Create a Self-Signed Certificate: Use OpenSSL in the terminal to generate a certificate.
2. Verify in Python: Verify the certificate using Python’s cryptography library.
Python Code for Verification:
from cryptography import x509
from cryptography.hazmat.backends import default_backend
def verify_certificate(cert_path):
with open(cert_path, "rb") as cert_file:
cert = x509.load_pem_x509_certificate(cert_file.read(), default_backend())
return cert.subject, cert.issuer
# Test
cert_path = "path/to/self-signed-cert.pem"
print(verify_certificate(cert_path))
Expected Output:
• Outputs the certificate subject and issuer information.
Practical 15: Secure Web Communication with HTTPS (SSL/TLS)
Objective: Demonstrate HTTPS communication using Python’s ssl and socket libraries.
Solution:
import ssl
import socket
def https_request():
context = ssl.create_default_context()
with socket.create_connection(("www.example.com", 443)) as sock:
with context.wrap_socket(sock, server_hostname="www.example.com") as ssock:
print("SSL/TLS Version:", ssock.version())
ssock.sendall(b"GET / HTTP/1.1\r\nHost: www.example.com\r\n\r\n")
print("Received:", ssock.recv(1024).decode())
# Test
https_request()
Expected Output:
• SSL/TLS Version details and part of the HTTP response header.
Practical 16: Exploring Transport Layer Security (TLS) Handshake
Objective: Demonstrate the process of a TLS handshake and understand the steps.
Solution: Use ssl to connect securely to a server and view handshake details.
• Steps:
1. Establish connection to a secure server.
2. Observe TLS handshake through version and certificate details.
Python Code:
def tls_handshake():
context = ssl.create_default_context()
with socket.create_connection(("www.example.com", 443)) as sock:
with context.wrap_socket(sock, server_hostname="www.example.com") as ssock:
print("SSL/TLS Version:", ssock.version())
print("Cipher:", ssock.cipher())
print("Server Certificate:", ssock.getpeercert())
# Test
tls_handshake()
Expected Output:
• TLS version, cipher suite, and server certificate information.
Practical 17: Implementing Simple SSH Connection using
Paramiko
Objective: Establish a secure SSH connection to a remote server using the paramiko library.
Solution:
1. Install paramiko: pip install paramiko
2. Use paramiko to establish an SSH session and execute a remote command.
Python Code:
import paramiko
def ssh_connection(hostname, port, username, password, command):
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect(hostname, port=port, username=username, password=password)
stdin, stdout, stderr = client.exec_command(command)
print("Command Output:", stdout.read().decode())
client.close()
# Test with appropriate server details
# ssh_connection("hostname", 22, "username", "password", "ls")
Expected Output:
• Command output from the remote server.
Practical 18: Elliptic Curve Cryptography (ECC) Implementation
Objective: Implement Elliptic Curve Cryptography for key generation and encryption.
Solution: This code generates ECC keys and encrypts a message using Python's cryptography
library.
1. Generate ECC keys.
2. Perform basic encryption/decryption.
Python Code:
from cryptography.hazmat.primitives.asymmetric import ec
from cryptography.hazmat.primitives import hashes
def ecc_key_pair():
private_key = ec.generate_private_key(ec.SECP384R1())
public_key = private_key.public_key()
return private_key, public_key
# Test
private_key, public_key = ecc_key_pair()
print("Private Key:", private_key)
print("Public Key:", public_key)
Expected Output:
• Generated ECC private and public keys.
Practical 19: Introduction to Firewall Rules and Packet Filtering
Objective: Create a basic packet filter to simulate firewall rules.
Solution: Using Python and scapy, simulate packet filtering by allowing or blocking certain IPs or
ports.
Python Code:
from scapy.all import *
def packet_filter(packet):
if packet.haslayer(IP) and packet[IP].src == "10.0.0.1":
print("Blocked packet from 10.0.0.1")
else:
print("Allowed packet:", packet.summary())
# Test with a sample packet
packet = IP(src="10.0.0.1")/TCP()
packet_filter(packet)
Expected Output:
• "Blocked packet from 10.0.0.1" if the source matches.
Practical 20: Basic Web Application Security with Python Flask
Objective: Develop a simple web application using Flask and implement secure login.
Solution:
1. Create a secure Flask application with session-based login.
2. Protect routes to demonstrate web application security.
Python Code:
from flask import Flask, request, session, redirect, url_for
app = Flask(__name__)
app.secret_key = "super_secret_key"
@app.route("/login", methods=["GET", "POST"])
def login():
if request.method == "POST":
username = request.form["username"]
password = request.form["password"]
if username == "admin" and password == "password":
session["username"] = username
return redirect(url_for("dashboard"))
return "Login Failed!"
@app.route("/dashboard")
def dashboard():
if "username" in session:
return "Welcome to the Dashboard!"
return redirect(url_for("login"))
if __name__ == "__main__":
app.run(debug=True)
Expected Output:
• A web application with a secure login session for authenticated users.