| 
 | 1 | +# Import the needed libraries.  | 
 | 2 | +import string  | 
 | 3 | +from colorama import Fore, init  | 
 | 4 | + | 
 | 5 | +# Initialise colorama.  | 
 | 6 | +init()  | 
 | 7 | + | 
 | 8 | + | 
 | 9 | +# Function to get Euclidean Algorithm.  | 
 | 10 | +def extended_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 | +    if a == 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 | +def modular_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 | +    if g != 1:  | 
 | 30 | +        raise Exception('Modular inverse does not exist')  | 
 | 31 | +    else:  | 
 | 32 | +        return x % m  | 
 | 33 | + | 
 | 34 | + | 
 | 35 | +# Function to decrypt our message.  | 
 | 36 | +def affine_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 | +    for char in ciphertext:  | 
 | 50 | +        # Check if the character is in the alphabet  | 
 | 51 | +        if char in alphabet:  | 
 | 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 | +    return plaintext  | 
 | 65 | + | 
 | 66 | + | 
 | 67 | +# Function to peform brute force attack.  | 
 | 68 | +def affine_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 | +    for a in range(1, m):  | 
 | 78 | +        # Ensure a and m are coprime.  | 
 | 79 | +        if extended_gcd(a, m)[0] == 1:  | 
 | 80 | +            # Iterate through possible values for b.  | 
 | 81 | +            for b in range(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)  | 
0 commit comments