import random
import string
# Function to generate a random substitution cipher key
def generate_substitution_key():
alphabet = string.ascii_lowercase
shuffled = list(alphabet)
random.shuffle(shuffled)
return dict(zip(alphabet, shuffled))
# Substitution cipher
def substitution_encrypt(plaintext, substitution_key):
encrypted_text = ""
for char in plaintext.lower():
if char in substitution_key:
encrypted_text += substitution_key[char]
else:
encrypted_text += char # Non-alphabetic characters remain unchanged
return encrypted_text
# Substitution cipher decryption
def substitution_decrypt(encrypted_text, substitution_key):
reversed_key = {v: k for k, v in substitution_key.items()}
decrypted_text = ""
for char in encrypted_text.lower():
if char in reversed_key:
decrypted_text += reversed_key[char]
else:
decrypted_text += char # Non-alphabetic characters remain unchanged
return decrypted_text
# Function to perform a transposition cipher
def transposition_encrypt(plaintext, key):
# Create a grid with key columns
grid = [''] * key
for i in range(len(plaintext)):
grid[i % key] += plaintext[i]
# Combine the columns into the final encrypted text
encrypted_text = ''.join(grid)
return encrypted_text
# Transposition cipher decryption
def transposition_decrypt(encrypted_text, key):
# Calculate number of rows in the grid
num_rows = len(encrypted_text) // key
num_extra_chars = len(encrypted_text) % key
# Create a list to hold the columns of the grid
grid = [''] * key
index = 0
# Distribute the characters back into the columns
for i in range(key):
for j in range(num_rows):
grid[i] += encrypted_text[index]
index += 1
if i < num_extra_chars:
grid[i] += encrypted_text[index]
index += 1
# Now we read the grid row by row
decrypted_text = ''.join(''.join(row) for row in zip(*grid))
return decrypted_text
# Product Cipher (Substitution + Transposition)
def product_cipher_encrypt(plaintext, substitution_key, transposition_key):
# Step 1: Apply substitution cipher
substituted_text = substitution_encrypt(plaintext, substitution_key)
# Step 2: Apply transposition cipher
encrypted_text = transposition_encrypt(substituted_text, transposition_key)
return encrypted_text
# Product Cipher Decryption (reverse of the encryption process)
def product_cipher_decrypt(encrypted_text, substitution_key, transposition_key):
# Step 1: Apply transposition cipher decryption
decrypted_text = transposition_decrypt(encrypted_text, transposition_key)
# Step 2: Apply substitution cipher decryption
decrypted_text = substitution_decrypt(decrypted_text, substitution_key)
return decrypted_text
# Example usage
if __name__ == "__main__":
# Example plaintext
plaintext = "hello world"
# Generate random substitution cipher key
substitution_key = generate_substitution_key()
# Set a transposition key (number of columns for transposition)
transposition_key = 5
print("Plaintext:", plaintext)
# Encrypt the plaintext using product cipher
encrypted_text = product_cipher_encrypt(plaintext, substitution_key, transposition_key)
print("Encrypted Text:", encrypted_text)
# Decrypt the encrypted text using product cipher
decrypted_text = product_cipher_decrypt(encrypted_text, substitution_key, transposition_key)
print("Decrypted Text:", decrypted_text)
# Verify that the decrypted text matches the original plaintext
assert decrypted_text == plaintext, "Decrypted text does not match plaintext!"
print("Decryption is successful. The decrypted text matches the original plaintext.")