BOOGER


Q.) CAESAR CIPHER:

def caesar_encrypt(plaintext: str, shift: int) -> str:
"""
Encrypt text by shifting each letter by 'shift' positions.
Non-alphabetic characters are unchanged.
"""
result = []
for ch in plaintext:
if ch.isalpha():
base = ord('A') if ch.isupper() else ord('a')
# shift within 0–25 then convert back
result.append(chr((ord(ch) - base + shift) % 26 + base))
else:
result.append(ch)
return ''.join(result)

def caesar_decrypt(ciphertext: str, shift: int) -> str:
"""Decrypt by shifting in the opposite direction."""
return caesar_encrypt(ciphertext, -shift)

Example

if name == "main":
text = "Hello, World!"
s = 3
enc = caesar_encrypt(text, s)
print("Encrypted:", enc)
print("Decrypted:", caesar_decrypt(enc, s))

Q.) PLAYFAIR CIPHER:

import string

def generate_key_matrix(key: str) -> list:
"""
Create 5×5 key matrix from a keyword:
- Merge I/J into one cell,
- Remove duplicates, fill remaining alphabet.
"""
key = key.upper().replace('J', 'I')
seen = set()
matrix = []
for ch in key + string.ascii_uppercase:
if ch not in seen and ch in string.ascii_uppercase:
seen.add(ch)
matrix.append(ch)
return [matrix[i*5:(i+1)*5] for i in range(5)]

def preprocess_text(text: str) -> str:
"""
Prepare digraphs, inserting 'X' between repeated letters,
and padding with 'X' if length is odd.
"""
text = text.upper().replace('J','I')
out = ""
i = 0
while i < len(text):
a = text[i]
b = text[i+1] if i+1 < len(text) else 'X'
if a == b:
out += a + 'X'
i += 1
else:
out += a + b
i += 2
if len(out) %2 !=0:
out += 'X'
return out

def find_pos(matrix, ch):
for i,row in enumerate(matrix):
if ch in row:
return i, row.index(ch)

def playfair_encrypt(plaintext, key):
matrix = generate_key_matrix(key)
text = preprocess_text(''.join(filter(str.isalpha, plaintext)))
cipher = ""
for i in range(0, len(text), 2):
r1,c1 = find_pos(matrix, text[i])
r2,c2 = find_pos(matrix, text[i+1])
if r1 == r2:
cipher += matrix[r1][(c1+1)%5] + matrix[r2][(c2+1)%5]
elif c1 == c2:
cipher += matrix[(r1+1)%5][c1] + matrix[(r2+1)%5][c2]
else:
cipher += matrix[r1][c2] + matrix[r2][c1]
return cipher

Example

if name == "main":
print(playfair_encrypt("Hide the gold", "SECRET"))

Q.) COLUMNAR TRANSPOSITION CIPHER:

import math

def columnar_encrypt(plaintext: str, key: str) -> str:
"""
Single-columnar:
- Write text in rows under columns labeled by sorted key.
- Read columns in key order.
"""
key_order = sorted(list(enumerate(key)), key=lambda x: x[1])
cols = len(key)
rows = math.ceil(len(plaintext)/cols)
# pad plaintext
padded = plaintext.ljust(rowscols, 'X')
matrix = [list(padded[i
cols:(i+1)*cols]) for i in range(rows)]
cipher = ""
for idx,_ in key_order:
for r in matrix:
cipher += r[idx]
return cipher

def columnar_decrypt(ciphertext: str, key: str) -> str:
"""
Reverse single-columnar transposition.
"""
key_order = sorted(list(enumerate(key)), key=lambda x: x[1])
cols = len(key)
rows = len(ciphertext)//cols
# fill columns
columns = {}
pos = 0
for idx,_ in key_order:
columns[idx] = list(ciphertext[pos:pos+rows])
pos += rows
# read row-wise
plaintext = ""
for r in range(rows):
for c in range(cols):
plaintext += columns[c][r]
return plaintext.rstrip('X')

Double transposition = apply twice with same/different keys

def double_columnar_encrypt(plaintext: str, key1: str, key2: str) -> str:
return columnar_encrypt(columnar_encrypt(plaintext, key1), key2)

if name == "main":
pt = "WEAREDISCOVEREDFLEEATONCE"
k1,k2 = "ZEBRA", "MANGO"
print("Double:", double_columnar_encrypt(pt, k1, k2))

Q.) HILL CIPHER:

import numpy as np
import string

def mod_inverse_matrix(matrix, m):
"""Compute inverse of matrix mod m."""
det = int(round(np.linalg.det(matrix)))
det_inv = pow(det, -1, m)
adj = np.round(det * np.linalg.inv(matrix)).astype(int)
return (det_inv * adj) % m

def hill_encrypt(plaintext: str, key_matrix: np.ndarray) -> str:
"""
Encrypt blocks of size n (matrix dim).
"""
n = key_matrix.shape[0]
text = plaintext.upper().replace(" ", "")
# pad
while len(text) % n != 0:
text += 'X'
cipher = ""
for i in range(0, len(text), n):
block = [ord(c)-65 for c in text[i:i+n]]
res = key_matrix.dot(block) % 26
cipher += ''.join(chr(int(x)+65) for x in res)
return cipher

Example 2×2 key

if name == "main":
key = np.array([[3,3],[2,5]])
print(hill_encrypt("HELP", key))

Q.) RAIL FENCE CIPHER:

def rail_fence_encrypt(text: str, rails: int) -> str:
"""
Write text in zig-zag across 'rails' rows, then read row-by-row.
"""
fence = [[] for _ in range(rails)]
rail = 0
var = 1
for ch in text:
fence[rail].append(ch)
rail += var
if rail == 0 or rail == rails-1:
var *= -1
return ''.join(''.join(row) for row in fence)

def rail_fence_decrypt(cipher: str, rails: int) -> str:
"""
Reconstruct zig-zag pattern to reverse encryption.
"""
# mark positions
pattern = [['' for _ in cipher] for _ in range(rails)]
rail, var = 0,1
for i in range(len(cipher)):
pattern[rail][i] = '*'
rail += var
if rail==0 or rail==rails-1:
var = -1
# fill letters
idx=0
for r in range(rails):
for c in range(len(cipher)):
if pattern[r][c]=='
':
pattern[r][c]=cipher[idx]
idx+=1
# read zig-zag
res, rail, var = "", 0,1
for i in range(len(cipher)):
res += pattern[rail][i]
rail += var
if rail==0 or rail==rails-1:
var *= -1
return res

if name == "main":
txt = "HELLOWORLD"
e = rail_fence_encrypt(txt, 3)
print(e, rail_fence_decrypt(e,3))

Q.) AES:

from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
from Crypto.Random import get_random_bytes

def aes_encrypt(plaintext: bytes, key: bytes) -> tuple:
"""
AES-CBC encryption:
- key must be 16/24/32 bytes.
- returns (iv, ciphertext).
"""
iv = get_random_bytes(16)
cipher = AES.new(key, AES.MODE_CBC, iv)
ct = cipher.encrypt(pad(plaintext, AES.block_size))
return iv, ct

def aes_decrypt(iv: bytes, ciphertext: bytes, key: bytes) -> bytes:
"""Remove padding after AES-CBC decryption."""
cipher = AES.new(key, AES.MODE_CBC, iv)
return unpad(cipher.decrypt(ciphertext), AES.block_size)

if name == "main":
key = get_random_bytes(16)
iv, ct = aes_encrypt(b"Secret Message", key)
print("Ciphertext:", ct)
print("Plaintext:", aes_decrypt(iv, ct, key))

Q.) DES:

from Crypto.Cipher import DES
from Crypto.Util.Padding import pad, unpad

def des_encrypt(plaintext: bytes, key: bytes) -> tuple:
"""
DES-CBC encryption:
- key must be 8 bytes.
- returns (iv, ciphertext).
"""
cipher = DES.new(key, DES.MODE_CBC)
ct = cipher.encrypt(pad(plaintext, DES.block_size))
return cipher.iv, ct

def des_decrypt(iv: bytes, ciphertext: bytes, key: bytes) -> bytes:
cipher = DES.new(key, DES.MODE_CBC, iv)
return unpad(cipher.decrypt(ciphertext), DES.block_size)

if name == "main":
key = b'8bytekey'
iv, ct = des_encrypt(b"Top Secret!", key)
print("Decrypted:", des_decrypt(iv, ct, key))

Q.) RSA:

from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_OAEP

def generate_rsa_keys(bits: int = 2048) -> tuple:
"""
Generate RSA key pair.
Returns (private_key, public_key) as RSA key objects.
"""
key = RSA.generate(bits)
return key, key.publickey()

def rsa_encrypt(message: bytes, pub_key) -> bytes:
"""Encrypt with public key using OAEP padding."""
cipher = PKCS1_OAEP.new(pub_key)
return cipher.encrypt(message)

def rsa_decrypt(ciphertext: bytes, priv_key) -> bytes:
"""Decrypt with private key."""
cipher = PKCS1_OAEP.new(priv_key)
return cipher.decrypt(ciphertext)

if name == "main":
priv, pub = generate_rsa_keys()
ct = rsa_encrypt(b"Hello RSA", pub)
print(rsa_decrypt(ct, priv))

Q.) GNU PRIVACY GUARD:

import gnupg

Initialize; gnupg must be installed and gpg available on PATH

gpg = gnupg.GPG()

def gpg_generate_key(name_email: str, passphrase: str):
"""Generate a new key pair."""
input_data = gpg.gen_key_input(
name_email=name_email,
passphrase=passphrase,
key_type="RSA",
key_length=2048
)
return gpg.gen_key(input_data)

def gpg_encrypt_file(input_file: str, recipient: str, output_file: str):
"""Encrypt a file for the given recipient."""
with open(input_file, "rb") as f:
status = gpg.encrypt_file(
f, recipients=[recipient],
output=output_file
)
return status.ok

def gpg_decrypt_file(input_file: str, passphrase: str, output_file: str):
"""Decrypt a file with your private key."""
with open(input_file, "rb") as f:
status = gpg.decrypt_file(
f, passphrase=passphrase,
output=output_file
)
return status.ok

if name == "main":
key = gpg_generate_key("[email protected]", "mypassword")
print("Fingerprints:", key.fingerprint)