def gcd(a, b):
while b:
a, b = b, a % b
return a
def modinv(a, m):
# Modular inverse using Extended Euclidean Algorithm
a=a%m
for x in range(1, m):
if (a * x) % m == 1:
return x
raise ValueError(f"No modular inverse for a={a} mod {m}")
def affine_encrypt(plaintext, a, b):
if gcd(a, 26) != 1:
raise ValueError("'a' must be coprime with 26.")
plaintext = plaintext.upper()
ciphertext = ""
for char in plaintext:
if char.isalpha():
x = ord(char) - ord('A')
y = (a * x + b) % 26
ciphertext += chr(y + ord('A'))
else:
ciphertext += char # Keep non-alpha as is
return ciphertext
def affine_decrypt(ciphertext, a, b):
if gcd(a, 26) != 1:
raise ValueError("'a' must be coprime with 26.")
a_inv = modinv(a, 26)
plaintext = ""
for char in ciphertext:
if char.isalpha():
y = ord(char) - ord('A')
x = (a_inv * (y - b)) % 26
plaintext += chr(x + ord('A'))
else:
plaintext += char # Keep non-alpha as is
return plaintext
# === Example usage ===
a=5
b=8
plaintext = "AFFINE CIPHER"
encrypted = affine_encrypt(plaintext, a, b)
decrypted = affine_decrypt(encrypted, a, b)
print(f"Plaintext: {plaintext}")
print(f"Encrypted: {encrypted}")
print(f"Decrypted: {decrypted}")