Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 29a6da0

Browse files
committedNov 23, 2024
cipher: add columnar transposition cipher
1 parent e5f35aa commit 29a6da0

File tree

1 file changed

+73
-0
lines changed

1 file changed

+73
-0
lines changed
 
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
import math
2+
3+
def encrypt_columnar_cipher(message: str, key: str) -> str:
4+
"""
5+
Encrypts a message using the Columnar Transposition Cipher.
6+
7+
:param message: Text to encrypt.
8+
:param key: String key used to define column order.
9+
:return: Encrypted message.
10+
"""
11+
# Remove spaces and calculate dimensions
12+
message = message.replace(" ", "")
13+
num_cols = len(key)
14+
num_rows = math.ceil(len(message) / num_cols)
15+
16+
# Fill the grid with characters
17+
grid = [''] * num_cols
18+
for i, char in enumerate(message):
19+
grid[i % num_cols] += char
20+
21+
# Sort columns based on the key order
22+
sorted_key_indices = sorted(range(len(key)), key=lambda k: key[k])
23+
ciphertext = ''.join([grid[i] for i in sorted_key_indices])
24+
25+
return ciphertext
26+
27+
28+
def decrypt_columnar_cipher(ciphertext: str, key: str) -> str:
29+
"""
30+
Decrypts a message encrypted with the Columnar Transposition Cipher.
31+
32+
:param ciphertext: Encrypted text.
33+
:param key: String key used to define column order.
34+
:return: Decrypted message.
35+
"""
36+
num_cols = len(key)
37+
num_rows = math.ceil(len(ciphertext) / num_cols)
38+
num_shaded_boxes = (num_cols * num_rows) - len(ciphertext)
39+
40+
# Sort columns based on the key order
41+
sorted_key_indices = sorted(range(len(key)), key=lambda k: key[k])
42+
col_lengths = [num_rows] * num_cols
43+
for i in range(num_shaded_boxes):
44+
col_lengths[sorted_key_indices[-(i+1)]] -= 1
45+
46+
# Distribute ciphertext into columns based on the sorted key
47+
grid = []
48+
start = 0
49+
for col_length in col_lengths:
50+
grid.append(ciphertext[start:start + col_length])
51+
start += col_length
52+
53+
# Rebuild plaintext row by row
54+
plaintext = ''
55+
for i in range(num_rows):
56+
for j in range(num_cols):
57+
if i < len(grid[sorted_key_indices[j]]):
58+
plaintext += grid[sorted_key_indices[j]][i]
59+
60+
return plaintext
61+
62+
63+
# Example usage
64+
message = "HELLO WORLD FROM COLUMNAR"
65+
key = "3412"
66+
67+
# Encrypt the message
68+
encrypted = encrypt_columnar_cipher(message, key)
69+
print("Encrypted:", encrypted)
70+
71+
# Decrypt the message
72+
decrypted = decrypt_columnar_cipher(encrypted, key)
73+
print("Decrypted:", decrypted)

0 commit comments

Comments
 (0)
Please sign in to comment.