|
| 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