44 lines
		
	
	
	
		
			1.2 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			44 lines
		
	
	
	
		
			1.2 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| def main():
 | |
|     # Affine cipher: E(x) = (ax + b) mod 26
 | |
|     # Given: "ab" -> "GL"
 | |
|     # a=0, b=1 -> G=6, L=11
 | |
| 
 | |
|     ciphertext = "XPALASXYFGFUKPXUSOGEUTKCDGEXANMGNVS"
 | |
| 
 | |
|     for a in range(1, 26):
 | |
|         if gcd(a, 26) != 1:
 | |
|             continue
 | |
|         a_inv = mod_inverse(a, 26)
 | |
|         if a_inv is None:
 | |
|             continue
 | |
| 
 | |
|         for b in range(26):
 | |
|             # check constraint: "ab" -> "GL" (a*0+b=6, a*1+b=11 mod 26)
 | |
|             if (b % 26 == 6) and ((a + b) % 26 == 11):
 | |
|                 decrypted = []
 | |
|                 for ch in ciphertext:
 | |
|                     if ch.isalpha():
 | |
|                         y = ord(ch.upper()) - ord('A')
 | |
|                         x = (a_inv * (y - b)) % 26
 | |
|                         decrypted.append(chr(x + ord('A')))
 | |
|                     else:
 | |
|                         decrypted.append(ch)
 | |
| 
 | |
|                 print(f"Key found: a={a}, b={b}")
 | |
|                 print(f"Ciphertext: {ciphertext}")
 | |
|                 print(f"Decrypted: {''.join(decrypted)}")
 | |
|                 return
 | |
| 
 | |
| def gcd(a, b):
 | |
|     while b:
 | |
|         a, b = b, a % b
 | |
|     return a
 | |
| 
 | |
| def mod_inverse(a, m):
 | |
|     for i in range(1, m):
 | |
|         if (a * i) % m == 1:
 | |
|             return i
 | |
|     return None
 | |
| 
 | |
| if __name__ == '__main__':
 | |
|     main()
 |