|
| 1 | +# Import the needed libraries. |
| 2 | +importstring |
| 3 | +fromcoloramaimportFore,init |
| 4 | + |
| 5 | +# Initialise colorama. |
| 6 | +init() |
| 7 | + |
| 8 | + |
| 9 | +# Function to get Euclidean Algorithm. |
| 10 | +defextended_gcd(a,b): |
| 11 | +""" |
| 12 | + Extended Euclidean Algorithm to find the greatest common divisor |
| 13 | + and coefficients x, y such that ax + by = gcd(a, b). |
| 14 | + """ |
| 15 | +ifa==0: |
| 16 | +return (b,0,1) |
| 17 | +else: |
| 18 | +g,x,y=extended_gcd(b%a,a) |
| 19 | +return (g,y- (b//a)*x,x) |
| 20 | + |
| 21 | + |
| 22 | +# Function to get the modular Inverse |
| 23 | +defmodular_inverse(a,m): |
| 24 | +""" |
| 25 | + Compute the modular multiplicative inverse of a modulo m. |
| 26 | + Raises an exception if the modular inverse does not exist. |
| 27 | + """ |
| 28 | +g,x,y=extended_gcd(a,m) |
| 29 | +ifg!=1: |
| 30 | +raiseException('Modular inverse does not exist') |
| 31 | +else: |
| 32 | +returnx%m |
| 33 | + |
| 34 | + |
| 35 | +# Function to decrypt our message. |
| 36 | +defaffine_decrypt(ciphertext,a,b): |
| 37 | +""" |
| 38 | + Decrypt a message encrypted with the Affine Cipher using |
| 39 | + the given key components a and b. |
| 40 | + """ |
| 41 | +alphabet=string.ascii_uppercase |
| 42 | +m=len(alphabet) |
| 43 | +plaintext='' |
| 44 | + |
| 45 | +# Compute the modular multiplicative inverse of a. |
| 46 | +a_inv=modular_inverse(a,m) |
| 47 | + |
| 48 | +# Iterate through each character in the ciphertext. |
| 49 | +forcharinciphertext: |
| 50 | +# Check if the character is in the alphabet |
| 51 | +ifcharinalphabet: |
| 52 | +# If it's an alphabet letter, decrypt it. |
| 53 | +# Find the index of the character in the alphabet. |
| 54 | +c=alphabet.index(char) |
| 55 | +# Apply the decryption formula: a_inv * (c - b) mod m. |
| 56 | +p= (a_inv* (c-b))%m |
| 57 | +# Append the decrypted character to the plaintext. |
| 58 | +plaintext+=alphabet[p] |
| 59 | +else: |
| 60 | +# If the character is not in the alphabet, keep it unchanged. |
| 61 | +plaintext+=char |
| 62 | + |
| 63 | +# Return the decrypted plaintext. |
| 64 | +returnplaintext |
| 65 | + |
| 66 | + |
| 67 | +# Function to peform brute force attack. |
| 68 | +defaffine_brute_force(ciphertext): |
| 69 | +""" |
| 70 | + Brute-force attack to find possible keys for an Affine Cipher |
| 71 | + and print potential decryptions for manual inspection. |
| 72 | + """ |
| 73 | +alphabet=string.ascii_uppercase |
| 74 | +m=len(alphabet) |
| 75 | + |
| 76 | +# Iterate through possible values for a. |
| 77 | +forainrange(1,m): |
| 78 | +# Ensure a and m are coprime. |
| 79 | +ifextended_gcd(a,m)[0]==1: |
| 80 | +# Iterate through possible values for b. |
| 81 | +forbinrange(0,m): |
| 82 | +# Decrypt using the current key. |
| 83 | +decrypted_text=affine_decrypt(ciphertext,a,b) |
| 84 | + |
| 85 | +# Print potential decryption for manual inspection. |
| 86 | +print(f"Key (a={a}, b={b}):{decrypted_text}") |
| 87 | + |
| 88 | + |
| 89 | +ciphertext=input(f"{Fore.GREEN}[?] Enter Message to decrypt: ") |
| 90 | + |
| 91 | +# Perform a brute-force attack to find potential decrypted message. |
| 92 | +affine_brute_force(ciphertext) |