-
Notifications
You must be signed in to change notification settings - Fork 1
/
playfair.py
166 lines (131 loc) · 4.79 KB
/
playfair.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
class PlayFair():
### initializing constants
### ie the aplhabet
ALPHABET = ["a","b","c","d","e","f",
"g","h","i","k","l",
"m","n","o","p","q","r",
"s","t","u","v","w","x",
"y","z"
]
@staticmethod
def encrypt(text:str,key:str)->str:
### avoiding errors that could happen
### due to different case letters
text = text.lower().strip()
key_clone = key.lower().strip()
key=""
### removing repeated letters from key
for letter in key_clone:
if letter not in key:
key+=letter
key = list(key)
letter_pairs = list()
pair = list()
### Parsing text into letter pairs for easier encryption
for letter in text:
### checking if current letter has been repeated
### and replacing with x
if len(pair)==1 and pair[len(pair)-1] == letter:
pair.append('x')
letter_pairs.append(pair)
pair = list(letter)
elif len(pair)==1:
pair.append(letter)
letter_pairs.append(pair)
pair = list()
else:
pair.append(letter)
### if there are left over letters from the loop
if len(pair)!=0:
letter_pairs.append(pair)
### checking if last letter is alone
### appending x if it is
last_pair = len(letter_pairs)-1
if len(letter_pairs[last_pair])%2!=0:
letter_pairs[last_pair].append("x")
### removing Key letters in Alphabet to avoid repetition
alphabet = PlayFair.ALPHABET.copy()
for letter in key:
if letter in alphabet:
alphabet.remove(letter)
matrix = list()
alpha_index = 0
j_index_r = 0
j_index_c = 0
for r in range(0,5):
row = list()
for c in range(0,5):
if len(key)>0:
letter = key.pop(0)
if letter == "i":
j_index_c = c
j_index_r = r
row.append(letter)
else:
letter = alphabet[alpha_index]
if letter == "i":
j_index_c = c
j_index_r = r
row.append(letter)
alpha_index+=1
matrix.append(row)
matrix[j_index_r][j_index_c] = [matrix[j_index_r][j_index_c],"j"]
cipher_text = ""
while len(letter_pairs)!=0:
l1,l2= letter_pairs.pop(0)
l1r = l1c = l2r = l2c = None
for r in range(len(matrix)):
for c in range(len(matrix[r])):
letter = matrix[r][c]\
if not isinstance(matrix[r][c],list)\
else matrix[r][c][0]
if letter == l1:
l1r = r
l1c = c
elif letter == l2:
l2r = r
l2c = c
cipher_text += PlayFair.return_match(matrix,l1r,l1c,l2r,l2c)
cipher_text += PlayFair.return_match(matrix,l2r,l2c,l1r,l1c)
for row in matrix:
print(row)
print("*"*20)
return cipher_text.upper()
@staticmethod
def return_match(matrix,l1r,l1c,l2r,l2c):
match=""
if l1r == l2r and l1c!=l2c:
### column less than end
if l1c<4:
match+=matrix[l1r][l1c+1]
### column is end start from begining of row
elif l1c == 4:
match+=matrix[l1r][0]
elif l1r!=l2r and l1c == l2c:
### row less than end
if l1r<4:
match+=matrix[l1r+1][l1c]
### last row resets to go up
elif l1r == 4:
match+=matrix[0][l1c]
### check for intersection
else:
if l1c<l2c:
match+=matrix[l1r][l1c+(l2c-l1c)]\
if not isinstance(matrix[l1r][l1c+(l2c-l1c)],list)\
else matrix[l1r][l1c+(l2c-l1c)][0]
else:
match+=matrix[l1r][l2c]\
if not isinstance(matrix[l1r][l2c],list)\
else matrix[l1r][l2c][0]
return match
@staticmethod
def decrypt(text,key):
text = text.lower().strip()
key = key.lower().strip()
### great observation , Encryption 8 times
### gives the decrypted text
### gat ma3aya bel kofta
for i in range(9):
text = PlayFair.encrypt(text,key)
return text