46 lines
		
	
	
		
			No EOL
		
	
	
		
			1.5 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			46 lines
		
	
	
		
			No EOL
		
	
	
		
			1.5 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| def keymat(k):
 | |
|     k = k.upper().replace('J', 'I')
 | |
|     seen = set(); seq = []
 | |
|     for ch in (k + "ABCDEFGHIKLMNOPQRSTUVWXYZ"):
 | |
|         if ch.isalpha() and ch not in seen:
 | |
|             seen.add(ch); seq.append(ch)
 | |
|     return [seq[i:i+5] for i in range(0, 25, 5)]
 | |
| 
 | |
| def pairs(s, prep=True):
 | |
|     s = ''.join(ch for ch in s.upper() if ch.isalpha())
 | |
|     if prep:
 | |
|         s = s.replace('J', 'I')
 | |
|         p = []; i = 0
 | |
|         while i < len(s):
 | |
|             a = s[i]; b = s[i+1] if i+1 < len(s) else 'X'
 | |
|             if a == b:
 | |
|                 p.append(a + 'X'); i += 1
 | |
|             else:
 | |
|                 p.append(a + b); i += 2
 | |
|         return p
 | |
|     return [s[i:i+2] for i in range(0, len(s), 2)]
 | |
| 
 | |
| def playfair(text, key, enc=True):
 | |
|     m = keymat(key)
 | |
|     pos = {m[r][c]: (r, c) for r in range(5) for c in range(5)}
 | |
|     out = []
 | |
|     for a, b in pairs(text, prep=enc):
 | |
|         r1, c1 = pos[a]; r2, c2 = pos[b]
 | |
|         if r1 == r2:
 | |
|             out.append(m[r1][(c1 + (1 if enc else -1)) % 5] +
 | |
|                        m[r2][(c2 + (1 if enc else -1)) % 5])
 | |
|         elif c1 == c2:
 | |
|             out.append(m[(r1 + (1 if enc else -1)) % 5][c1] +
 | |
|                        m[(r2 + (1 if enc else -1)) % 5][c2])
 | |
|         else:
 | |
|             out.append(m[r1][c2] + m[r2][c1])
 | |
|     return ''.join(out)
 | |
| 
 | |
| enc = lambda pt, k: playfair(pt, k, True)
 | |
| dec = lambda ct, k: playfair(ct, k, False)
 | |
| 
 | |
| if __name__ == '__main__':
 | |
|     pt = input("Plaintext: ")
 | |
|     k  = input("Key: ")
 | |
|     ct = enc(pt, k); print("Ciphertext:", ct)
 | |
|     print("Decrypted:", dec(ct, k)) |