Ceaser Cipher
plaintext = input("Enter the plaintext: ")
k = int(input("Enter the key value: "))
cipher = {}
initial_ascii_cap = 65
initial_ascii_low = 97
# Create mapping for uppercase letters
for i in range(26):
char = chr(initial_ascii_cap + i)
cipher[char] = i
# Create mapping for lowercase letters
for i in range(26):
char = chr(initial_ascii_low + i)
cipher[char] = i
cip = ''
for j in plaintext:
if j.isalpha():
updatedval = cipher[j] + k
updatedval %= 26
if j.islower():
c = chr(updatedval + initial_ascii_low)
else:
c = chr(updatedval + initial_ascii_cap)
cip += c
else:
cip += j # Non-alphabetic characters remain unchanged
print(cip)
hill cipher
import numpy as np
def mod_inverse(a, m):
for x in range(1, m):
if (a * x) % m == 1:
return x
return None
def ttn(text): # text to numbers
return [ord(char) - ord('A') for char in text.upper() if char.isalpha()]
def ntt(numbers): # numbers to text
return ''.join(chr(num + ord('A')) for num in numbers)
def pad_text(text, size):
padding_length = (size - len(text) % size) % size
return text + 'X' * padding_length
def encryption(pt, key):
n = len(key)
pt = pad_text(pt, n)
pt_n = ttn(pt)
cipher = []
for i in range(0, len(pt_n), n):
block = pt_n[i:i+n]
enc_block = np.dot(key, block) % 26
cipher.extend(enc_block)
return ntt(cipher)
def decryption(c, key):
n = len(key)
det = int(round(np.linalg.det(key)))
det_inv = mod_inverse(det % 26, 26)
if det_inv is None:
raise ValueError("Modular inverse doesn't exist; invalid key matrix.")
key_inverse = (
det_inv * np.round(det * np.linalg.inv(key)).astype(int) % 26
) % 26
cipher = ttn(c)
pt_n = []
for i in range(0, len(cipher), n):
block = cipher[i:i+n]
dec_block = np.dot(key_inverse, block) % 26
pt_n.extend(dec_block)
return ntt(pt_n).rstrip('X')
# Example usage
key_m = np.array([[6, 24, 1], [13, 16, 10], [20, 17, 15]])
pt = "HELLO"
enc = encryption(pt, key_m)
print(f"Encrypted = {enc}")
dec = decryption(enc, key_m)
print(f"Decrypted = {dec}")
Vignete cipher
plaintext = input("Enter the plaintext: ")
key = input("Enter the key value: ")
cipher = {}
initial_ascii_cap = 65
initial_ascii_low = 97
# Create alphabet to index mappings
for i in range(26):
cipher[chr(initial_ascii_cap + i)] = i
cipher[chr(initial_ascii_low + i)] = i
cip = ''
vals = []
vals2 = []
# Convert plaintext to values
for j in plaintext:
if j.isalpha():
val = cipher[j]
vals.append(val)
else:
vals.append(j) # Store non-alphabetic characters as-is
# Extend or repeat the key
extended_key = ''
key_index = 0
for ch in plaintext:
if ch.isalpha():
extended_key += key[key_index % len(key)]
key_index += 1
else:
extended_key += ch
# Convert key to values
for j in extended_key:
if j.isalpha():
val = cipher[j]
vals2.append(val)
else:
vals2.append(j)
# Perform encryption
for i in range(len(vals)):
if isinstance(vals[i], int):
new_val = (vals[i] + vals2[i]) % 26
if plaintext[i].islower():
c = chr(new_val + initial_ascii_low)
else:
c = chr(new_val + initial_ascii_cap)
cip += c
else:
cip += vals[i] # Non-alphabetic characters unchanged
print(cip)
playfair cipher
def generate_playfair_matrix(key):
key = key.upper().replace("J", "I")
matrix = []
seen = set()
for char in key + "ABCDEFGHIKLMNOPQRSTUVWXYZ":
if char not in seen:
seen.add(char)
matrix.append(char)
return [matrix[i:i+5] for i in range(0, 25, 5)]
def find_position(matrix, char):
for i in range(5):
for j in range(5):
if matrix[i][j] == char:
return i, j
return None
def prepare_text(text):
text = text.upper().replace("J", "I")
prepared = ""
i=0
while i < len(text):
char1 = text[i]
char2 = text[i + 1] if i + 1 < len(text) else 'X'
if char1 == char2:
prepared += char1 + 'X'
i += 1
else:
prepared += char1 + char2
i += 2
if len(prepared) % 2 != 0:
prepared += 'X'
return prepared
def playfair_encrypt(text, key):
matrix = generate_playfair_matrix(key)
text = prepare_text(text)
encrypted = ""
for i in range(0, len(text), 2):
row1, col1 = find_position(matrix, text[i])
row2, col2 = find_position(matrix, text[i + 1])
if row1 == row2: # Same row
encrypted += matrix[row1][(col1 + 1) % 5]
encrypted += matrix[row2][(col2 + 1) % 5]
elif col1 == col2: # Same column
encrypted += matrix[(row1 + 1) % 5][col1]
encrypted += matrix[(row2 + 1) % 5][col2]
else: # Rectangle swap
encrypted += matrix[row1][col2]
encrypted += matrix[row2][col1]
return encrypted
def playfair_decrypt(text, key):
matrix = generate_playfair_matrix(key)
decrypted = ""
for i in range(0, len(text), 2):
row1, col1 = find_position(matrix, text[i])
row2, col2 = find_position(matrix, text[i + 1])
if row1 == row2: # Same row
decrypted += matrix[row1][(col1 - 1) % 5]
decrypted += matrix[row2][(col2 - 1) % 5]
elif col1 == col2: # Same column
decrypted += matrix[(row1 - 1) % 5][col1]
decrypted += matrix[(row2 - 1) % 5][col2]
else: # Rectangle swap
decrypted += matrix[row1][col2]
decrypted += matrix[row2][col1]
return decrypted
RSA
import random
def gcd(a, b):
while b != 0:
a, b = b, a % b
return a
def modinv(a, m):
m0, x0, x1 = m, 0, 1
if m == 1:
return 0
while a > 1:
q = a // m
m, a = a % m, m
x0, x1 = x1 - q * x0, x0
if x1 < 0:
x1 += m0
return x1
def is_prime(num):
if num < 2:
return False
for i in range(2, int(num ** 0.5) + 1):
if num % i == 0:
return False
return True
def generate_keypair(p, q):
if not (is_prime(p) and is_prime(q)):
raise ValueError("Both numbers must be prime.")
elif p == q:
raise ValueError("p and q cannot be the same")
n=p*q
phi = (p - 1) * (q - 1)
e = random.randrange(1, phi)
g = gcd(e, phi)
while g != 1:
e = random.randrange(1, phi)
g = gcd(e, phi)
d = modinv(e, phi)
return ((e, n), (d, n))
def encrypt(pk, plaintext):
key, n = pk
cipher = [(ord(char) ** key) % n for char in plaintext]
return cipher
def decrypt(pk, ciphertext):
key, n = pk
plain = [chr((char ** key) % n) for char in ciphertext]
return ''.join(plain)
if __name__ == '__main__':
p = 61
q = 53
public, private = generate_keypair(p, q)
print("Public key:", public)
print("Private key:", private)
message = input("Enter the message you want to encrypt: ")
encrypted_msg = encrypt(public, message)
print("Encrypted message:", encrypted_msg)
decrypted_msg = decrypt(private, encrypted_msg)
print("Decrypted message:", decrypted_msg)
dewie hellman
import random
def gen_keys(p, g):
a = random.randint(1, p - 1)
A = pow(g, a, p)
return a, A
def compute_sk(a, B, p):
return pow(B, a, p)
p = 23
g=5
a, A = gen_keys(p, g)
b, B = gen_keys(p, g)
shared_key_a = compute_sk(a, B, p)
shared_key_b = compute_sk(b, A, p)
print(shared_key_a == shared_key_b)
print("Shared key:", shared_key_a)
Elgamal
import random
def gcd(a, b):
while b != 0:
a, b = b, a % b
return a
def mod_exp(base, exp, mod):
result = 1
while exp > 0:
if exp % 2 == 1:
result = (result * base) % mod
base = (base * base) % mod
exp //= 2
return result
def generate_keys(p):
g = random.randint(2, p - 1)
x = random.randint(1, p - 2)
h = mod_exp(g, x, p)
return (p, g, h), x
def encrypt(public_key, plaintext):
p, g, h = public_key
y = random.randint(1, p - 2)
c1 = mod_exp(g, y, p)
c2 = (plaintext * mod_exp(h, y, p)) % p
return c1, c2
def decrypt(private_key, public_key, ciphertext):
p, g, h = public_key
c1, c2 = ciphertext
s = mod_exp(c1, private_key, p)
s_inv = pow(s, -1, p)
plaintext = (c2 * s_inv) % p
return plaintext
p = 467 # A large prime
public_key, private_key = generate_keys(p)
print("Public Key:", public_key)
print("Private Key:", private_key)
plaintext = 123
ciphertext = encrypt(public_key, plaintext)
print("Ciphertext:", ciphertext)
decrypted_message = decrypt(private_key, public_key, ciphertext)
print("Decrypted Message:", decrypted_message)
RSA question
def gcd(a, b):
while b:
a, b = b, a % b
return a
def modinv(e, phi):
d_old, d = 0, 1
r_old, r = phi, e
while r != 0:
q = r_old // r
r_old, r = r, r_old - q * r
d_old, d = d, d_old - q * d
return d_old % phi
def rsa_encrypt_decrypt(p, q, e, M):
n=p*q
phi = (p - 1) * (q - 1)
d = modinv(e, phi)
C = pow(M, e, n)
decrypted = pow(C, d, n)
return {
"n": n, "phi": phi, "e": e, "d": d,
"Encrypted (C)": C, "Decrypted (M)": decrypted
test_cases = [
(3, 7, 5, 10),
(5, 13, 5, 8),
(7, 17, 11, 11),
(7, 13, 11, 2),
(17, 23, 9, 7)
for i, (p, q, e, M) in enumerate(test_cases, start=1):
result = rsa_encrypt_decrypt(p, q, e, M)
print(f"\nCase {chr(96+i)}) p={p}, q={q}, e={e}, M={M}")
print(f" n = {result['n']}, phi = {result['phi']}, d = {result['d']}")
print(f" Encrypted (C) = {result['Encrypted (C)']}")
print(f" Decrypted (M) = {result['Decrypted (M)']}")
dewie hellman backup
def mod_exp(base, exp, mod):
result = 1
base = base % mod
while exp > 0:
if exp % 2 == 1:
result = (result * base) % mod
base = (base * base) % mod
exp //= 2
return result
# Input
alpha = int(input("Enter alpha (primitive root): "))
q = int(input("Enter prime number q: "))
xa = int(input("Enter private key of Alice (xa): "))
xb = int(input("Enter private key of Bob (xb): "))
# Public keys
ya = mod_exp(alpha, xa, q) # Alice's public key
yb = mod_exp(alpha, xb, q) # Bob's public key
# Secret keys
ka = mod_exp(yb, xa, q) # Secret key calculated by Alice
kb = mod_exp(ya, xb, q) # Secret key calculated by Bob
# Output
print("\n--- Diwie-Hellman Key Exchange ---")
print(f"Alpha = {alpha}")
print(f"q = {q}")
print(f"Private key of Alice = {xa}")
print(f"Public key of Alice = {ya}")
print(f"Private key of Bob = {xb}")
print(f"Public key of Bob = {yb}")
print(f"Secret key computed by Alice = {ka}")
print(f"Secret key computed by Bob = {kb}")
if ka == kb:
print("✅ Both Alice and Bob have the same secret key.")
print("🔐 Key shared securely.")
else:
print("❌ Key is not shared securely.")
SHA
print("Sample Result")
n = int(input("Give the number of bits for the message: "))
multiplier = 1
while multiplier * 1024 < (n + 128):
multiplier += 1
padding_size = (multiplier * 1024) - (n + 128)
print("\nOriginal message length (bits):", n)
print("The size of the padding bits is:", padding_size)
print("The total size of the blocks after including the padding bits is:", padding_size + n +
128)
# Create padding bits string: '1' followed by (padding_size - 1) zeros
paddingBitsString = '1' + '0' * (padding_size - 1)
print("The padding bits are as below, along with the number of bits (excluding the size of the
message {128}):")
print(paddingBitsString)
print("Size of padding bits:", len(paddingBitsString))
print("Total blocks required:", multiplier)
MD5
def itos(n):
return '0' if n == 0 else '1'
def dec_to_binary(n):
res = ""
count = 8
i=n
while i != 0 or count > 0:
if i == 0 and len(res) < 8:
res = res.rjust(8, '0')
return res
res = itos(i % 2) + res
i //= 2
count -= 1
return res
def main():
inp = input("Give the original message to check: ")
n = len(inp)
input_chain = []
padding_chain = []
print("1. Showing the original message in binary:")
for ch in inp:
temp = dec_to_binary(ord(ch))
print(temp, end=" ")
input_chain.append(temp)
total_message_bits = n * 8
print(f"\nThe total message bits size: {total_message_bits}")
i=1
while (512 * i) - 64 - total_message_bits < 0:
i += 1
x = (512 * i) - 64 - total_message_bits
print(f"\n2. The total number of padding bits is: {x}")
message_length = dec_to_binary(total_message_bits)
print("Message length in binary:", message_length)
# Padding: starts with '10000000' (i.e., 0x80) followed by required 0 blocks
padding_chain.append("10000000")
padding_blocks = x // 8
temp = padding_blocks - 1
while temp != 0:
padding_chain.append("00000000")
temp -= 1
print("The number of padding blocks is (without the message size block):",
padding_blocks)
print("3. The padding bits are:")
for b in padding_chain:
print(b, end=" ")
print(f"\nThe Message in bits are below (The size of the message is:
{total_message_bits}):")
for bit_block in input_chain:
print(bit_block, end=" ")
if __name__ == "__main__":
main()
AES KEY EXP
s_box = [
0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7,
0xAB,….
]
rcon = [0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1B, 0x36]
def rot_word(word):
return word[1:] + word[:1]
def sub_word(word):
return [s_box[b] for b in word]
def key_expansion(key):
key_size = len(key)
assert key_size == 16
expanded = []
for i in range(0, 16, 4):
word = list(key[i:i+4])
expanded.append(word)
for i in range(4, 44):
temp = expanded[i - 1].copy()
if i % 4 == 0:
temp = rot_word(temp)
temp = sub_word(temp)
temp[0] ^= rcon[(i // 4) - 1]
new_word = [temp[j] ^ expanded[i - 4][j] for j in range(4)]
expanded.append(new_word)
return expanded
sample_key = bytes.fromhex("4A1A607DD64C444F6B2750E0975FE72E")
expanded_keys = key_expansion(sample_key)
round4_key = expanded_keys[16:20]
round4_key_bytes = bytes([byte for word in round4_key for byte in word])
print("Round4 Key (hex):", round4_key_bytes.hex().upper())
DES simulation
def permutation(input_block, table):
output = 0
for i, pos in enumerate(table):
bit = (input_block >> (64 - pos)) & 1
output |= bit << (64 - (i + 1))
return output
ip_table = [
58, 50, 42, 34, 26, 18, 10, 2, 60, 52, 44, 36, 28, 20, 12, 4,…
fp_table = [
40, 8, 48, 16, 56, 24, 64, 32, 39, 7, 47, 15, 55, 23,…
input_hex = "0001002000000008".replace(" ", "")
input_block = int(input_hex, 16)
ip_result = permutation(input_block, ip_table)
fp_result = permutation(ip_result, fp_table)
print("Input block: " + format(input_block, '016X'))
print("After Initial Perm.: " + format(ip_result, '016X'))
print("After Final Perm.: " + format(fp_result, '016X'))
SHA da
def print_hex_vector(vec):
for i, val in enumerate(vec):
print(f"W{i} = {val:016X}")
def majority(a, b, c):
return (a & b) ^ (a & c) ^ (b & c)
def condition(e, f, g):
return (e & f) ^ (~e & g)
# === (1) User input message ===
message = input("Enter the plaintext message: ")
msg_bytes = message.encode("utf-8")
original_bit_length = len(msg_bytes) * 8
# === (a) Padding bits calculation ===
padding_bits = (1024 - (original_bit_length + 1 + 128) % 1024) % 1024
print(f"\n(a) Padding bits: {padding_bits}")
# === (b) Generate message schedule (W0 to W17) ===
W = [0] * 80
for i in range(len(msg_bytes)):
W[i // 8] |= msg_bytes[i] << ((7 - (i % 8)) * 8)
# Append 1 bit (0x80)
W[len(msg_bytes) // 8] |= 0x80 << ((7 - (len(msg_bytes) % 8)) * 8)
# Append original length to W[15]
W[15] = original_bit_length
# Extend W[16] to W[17]
for i in range(16, 18):
W[i] = W[i - 16] + W[i - 7]
print("\n(b) First 18 words (W0 - W17) in hex:")
print_hex_vector(W[:18])
# === (c) Majority function ===
A = 0x6a09e667f3bcc908
B = 0xbb67ae8584caa73b
C = 0x3c6ef372fe94f82b
majority_result = majority(A, B, C)
print(f"\n(c) Majority function result: {majority_result:016X}")
# === (d) Condition function ===
E = 0x510e527fade682d1
F = 0x9b05688c2b3e6c1f
G = 0x1f83d9abfb41bd6b
condition_result = condition(E, F, G)
print(f"(d) Condition function result: {condition_result:016X}")
Absolutely! Here's a brief algorithmic description for each of the provided code snippets:
1. Caesar Cipher:
• Input: Plaintext string, shift key (integer).
• Process:
o Iterate through each character of the plaintext.
o If the character is alphabetic:
§ Convert the character to its corresponding numerical value (A=0,
B=1, etc.).
§ Add the shift key to the numerical value.
§ Apply modulo 26 to wrap around the alphabet.
§ Convert the resulting numerical value back to a character.
o If the character is not alphabetic, leave it unchanged.
• Output: Ciphertext string.
2. Hill Cipher:
• Input: Plaintext string, key matrix (numpy array).
• Process:
o Pad the plaintext with 'X' characters to make its length a multiple of the
key matrix size.
o Convert the plaintext to numerical values (A=0, B=1, etc.).
o Divide the numerical plaintext into blocks of size equal to the key matrix
size.
o For each block:
§ Multiply the key matrix by the block (vector multiplication).
§ Apply modulo 26 to the result.
o Convert the resulting numerical values back to characters.
• Output: Ciphertext string.
• Decryption:
o Calculate the inverse of the Key Matrix.
o Perform the encryption steps in reverse.
3. Vigenère Cipher:
• Input: Plaintext string, key string.
• Process:
o Extend the key to match the plaintext length (repeating the key).
o Convert both plaintext and extended key to numerical values (A=0, B=1,
etc.).
o For each character:
§ Add the plaintext numerical value to the corresponding key
numerical value.
§ Apply modulo 26 to the result.
§ Convert the resulting numerical value back to a character.
o Non alphabetic characters are not changed.
• Output: Ciphertext string.
4. Playfair Cipher:
• Input: Plaintext string, key string.
• Process:
o Generate a 5x5 key matrix from the key (replacing 'J' with 'I').
o Prepare the plaintext:
§ Replace 'J' with 'I'.
§ Insert 'X' between repeated letters.
§ Pad with 'X' if the plaintext length is odd.
o Divide the plaintext into pairs of characters.
o For each pair:
§ Find the positions of the characters in the key matrix.
§ Apply the Playfair rules (same row, same column, rectangle) to get
the ciphertext pair.
o Convert the ciphertext pairs back to a string.
• Output: Ciphertext string.
• Decryption:
o Reverse the encryption steps.
5. RSA:
• Input: Two prime numbers (p, q), plaintext message.
• Process:
o Generate public and private keys:
§ n=p*q
§ phi = (p-1) * (q-1)
§ Choose public exponent 'e' (relatively prime to phi).
§ Calculate private exponent 'd' (modular inverse of 'e' mod phi).
o Encryption:
§ Convert plaintext characters to numerical values.
§ Ciphertext = (plaintext ^ e) mod n.
o Decryption:
§ Plaintext = (ciphertext ^ d) mod n.
• Output: Ciphertext (numerical list), decrypted plaintext.
6. Diffie-Hellman:
• Input: Prime number (p), generator (g), private keys (a, b).
• Process:
o Calculate public keys:
§ A = g^a mod p
§ B = g^b mod p
o Calculate shared secret keys:
§ ka = B^a mod p
§ kb = A^b mod p
• Output: Shared secret key.
7. ElGamal:
• Input: Prime number (p), plaintext message.
• Process:
o Key generation:
§ Generate a generator g.
§ Generate a private key x.
§ Generate a public key h = g^x mod p.
o Encryption:
§ Generate a random y.
§ c1 = g^y mod p.
§ c2 = plaintext * h^y mod p.
o Decryption:
§ s = c1^x mod p.
§ plaintext = c2 * s^-1 mod p.
• Output: Ciphertext (c1, c2), decrypted plaintext.
8. RSA Question (Encryption/Decryption Function):
• Input: Two prime numbers (p, q), public exponent (e), message (M).
• Process:
o Calculate n = p * q and phi = (p-1) * (q-1).
oCalculate private exponent d (modular inverse of e mod phi).
oEncryption: C = M^e mod n.
oDecryption: M = C^d mod n.
• Output: n, phi, d, encrypted message (C), decrypted message (M).
9. Diffie-Hellman Backup:
• Input: primitive root alpha, prime number q, private keys xa and xb.
• Process:
o calculate public keys ya and yb.
o calculate shared key ka and kb.
• Output: public keys, and shared secret key.
10. SHA:
• Input: Message (string).
• Process:
o Calculate padding bits needed.
o Append the padding bits to the message.
o Append the original message lenght in bits.
o Show the result.
• Output: padded message information.
11. MD5:
• Input: Message string.
• Process:
o Convert message to binary.
o Calculate the number of padding bits.
o Append the padding bits.
o Append message length in bits.
• Output: padded message information.
12. AES Key Expansion:
• Input: 16-byte key.
• Process:
o Expand the key into a 44-word array.
o Use S-box, Rcon, and rotation operations.
• Output: Expanded key array.
13. DES Simulation:
• Input: 64-bit input block.
• Process:
o Apply initial permutation (IP).
o Apply final permutation (FP).
• Output: Permuted blocks.
14. SHA da:
• Input: Message string.
• Process:
o Calculate padding bits.
o Create message schedule (W array).
o Perform majority and condition operations.
• Output: intermediate hash values.