1
1
# https://engineering.purdue.edu/kak/compsec/NewLectures/Lecture8.pdf
2
2
# http://www.moserware.com/2009/09/stick-figure-guide-to-advanced.html
3
3
4
- def h2b (msg ):
4
+ def h2b (val ):
5
5
hex_val = {"0" : "0000" , "1" : "0001" , "2" : "0010" , "3" : "0011" ,
6
6
"4" : "0100" , "5" : "0101" , "6" : "0110" , "7" : "0111" ,
7
7
"8" : "1000" , "9" : "1001" , "a" : "1010" , "b" : "1011" ,
8
8
"c" : "1100" , "d" : "1101" , "e" : "1110" , "f" : "1111" }
9
- m_len = len (msg )
9
+ m_len = len (val )
10
10
final = ""
11
11
for i in range (0 , m_len ):
12
- final = final + hex_val [msg [i ]]
12
+ final = final + hex_val [val [i ]]
13
13
return final
14
14
15
15
16
- def b2h (msg ):
16
+ def b2h (val ):
17
17
bin_val = {"0000" : "0" , "0001" : "1" , "0010" : "2" , "0011" : "3" ,
18
18
"0100" : "4" , "0101" : "5" , "0110" : "6" , "0111" : "7" ,
19
19
"1000" : "8" , "1001" : "9" , "1010" : "a" , "1011" : "b" ,
20
20
"1100" : "c" , "1101" : "d" , "1110" : "e" , "1111" : "f" }
21
- m_len = len (msg )
21
+ m_len = len (val )
22
22
lst = []
23
23
final = ""
24
24
count = 0
25
25
i = 0
26
26
while count != m_len :
27
- lst = lst + [msg [count :count + 4 ]]
27
+ lst = lst + [val [count :count + 4 ]]
28
28
final = final + bin_val [lst [i ]]
29
29
i = i + 1
30
30
count = count + 4
31
31
32
32
return final
33
33
34
34
35
- def substitution_box (x ):
35
+ def substitution_box (rc ):
36
36
hex_val = {"0" : "0" , "1" : "1" , "2" : "2" , "3" : "3" ,
37
37
"4" : "4" , "5" : "5" , "6" : "6" , "7" : "7" ,
38
38
"8" : "8" , "9" : "9" , "a" : "10" , "b" : "11" ,
@@ -55,7 +55,7 @@ def substitution_box(x):
55
55
["e1" , "f8" , "98" , "11" , "69" , "d9" , "8e" , "94" , "9b" , "1e" , "87" , "e9" , "ce" , "55" , "28" , "df" ],
56
56
["8c" , "a1" , "89" , "0d" , "bf" , "e6" , "42" , "68" , "41" , "99" , "2d" , "0f" , "b0" , "54" , "bb" , "16" ]]
57
57
58
- substitution = rijndael_s_box [int (hex_val [x [0 ]])][int (hex_val [x [1 ]])]
58
+ substitution = rijndael_s_box [int (hex_val [rc [0 ]])][int (hex_val [rc [1 ]])]
59
59
return substitution
60
60
61
61
@@ -70,88 +70,34 @@ def xor(left, right):
70
70
return final
71
71
72
72
73
- def key (s_key , rnd ):
74
- keys = []
75
-
76
- # Rcon = 128 -> 10, 192 -> 8, 256 -> 7
77
- # Rcon = [01, 02, 04, 08, 10, 20, 40, 80, 1b, 36]
78
- # Rcon(i) = [rc(i), 00(0x), 00(0x), 00(0x)] --> (0x) = hex
79
- # Rcon = [["01", "00", "00", "00"], ["02", "00", "00", "00"], ["04", "00", "00", "00"], ["08", "00", "00", "00"],
80
- # ["10", "00", "00", "00"], ["20", "00", "00", "00"], ["40", "00", "00", "00"], ["80", "00", "00", "00"],
81
- # ["1b", "00", "00", "00"], ["36""00", "00", "00"]]
82
-
83
- for pos in range (0 , 4 ):
84
- if pos == 0 :
85
- first_col = []
86
- tmp = s_key [3 ]
87
- t_len = len (tmp )
88
-
89
- for i in range (1 , t_len ):
90
- first_col = first_col + [tmp [i ]]
91
- first_col = first_col + [tmp [0 ]]
92
- col = []
93
-
94
- f_len = len (first_col )
95
- for i in range (0 , f_len ):
96
- col = col + [substitution_box (first_col [i ])]
97
-
98
- tmp_key = []
99
- for i in range (0 , 4 ):
100
- sub_key = xor (h2b (s_key [0 ][i ]), h2b (rnd [i ]))
101
- sub_key1 = xor (sub_key , h2b (col [i ]))
102
- tmp_key = tmp_key + [str (b2h (sub_key1 ))]
103
-
104
- keys = keys + [tmp_key ]
105
-
106
- elif pos > 0 :
107
- first_col = []
108
-
109
- for i in range (0 , 4 ):
110
- sub_key = xor (h2b (s_key [pos ][i ]), h2b (keys [pos - 1 ][i ]))
111
- first_col = first_col + [str (b2h (sub_key ))]
112
-
113
- keys = keys + [first_col ]
114
- return keys
115
-
116
-
117
- def col_to_row (keys ):
73
+ def col_to_row (val ):
118
74
row = []
119
75
for i in range (0 , 4 ):
120
76
col = []
121
77
for j in range (0 , 4 ):
122
- col = col + [keys [j ][i ]]
78
+ col = col + [val [j ][i ]]
123
79
row = row + [col ]
124
80
return row
125
81
126
82
127
- def row_to_col (keys ):
83
+ def row_to_col (val ):
128
84
col = []
129
85
for i in range (0 , 4 ):
130
86
row = []
131
87
for j in range (0 , 4 ):
132
- row = row + [keys [j ][i ]]
88
+ row = row + [val [j ][i ]]
133
89
col = col + [row ]
134
90
return col
135
91
136
92
137
- def add_round (plaintext , keys ):
138
- row = []
139
- for i in range (0 , 4 ):
140
- col = []
141
- for j in range (0 , 4 ):
142
- tmp = xor (h2b (keys [i ][j ]), h2b (plaintext [i ][j ]))
143
- col = col + [b2h (tmp )]
144
- row = row + [col ]
145
-
146
- return col_to_row (row )
147
-
148
-
149
- def substitute_byte (keys ):
93
+ # it replaces every state element from its respective position in s-box
94
+ # row = first four bits or first value, and col = next four bits or next value
95
+ def substitute_byte (state ):
150
96
row = []
151
97
for i in range (0 , 4 ):
152
98
col = []
153
99
for j in range (0 , 4 ):
154
- col = col + [substitution_box (keys [i ][j ])]
100
+ col = col + [substitution_box (state [i ][j ])]
155
101
row = row + [col ]
156
102
return row
157
103
@@ -164,7 +110,7 @@ def shift_row(sub_bytes):
164
110
first = sub_bytes [0 ]
165
111
state_array = state_array + [first ]
166
112
167
- # row [1 , 2, 3, 4] --> [2, 3, 4, 1]
113
+ # row [1, 2, 3, 4] --> [2, 3, 4, 1]
168
114
second = [sub_bytes [1 ][1 ]] + [sub_bytes [1 ][2 ]] + [sub_bytes [1 ][3 ]] + [sub_bytes [1 ][0 ]]
169
115
state_array = state_array + [second ]
170
116
@@ -179,20 +125,26 @@ def shift_row(sub_bytes):
179
125
return state_array
180
126
181
127
182
- def mix_byte (inp ):
128
+ # implementation of multiplication by 2 in galois field (0x02)
129
+ def multiply_by_02 (inp ):
183
130
bin_val = h2b (inp [0 ]) + h2b (inp [1 ])
184
131
final = ""
185
132
if bin_val [0 ] == '1' :
133
+ # zero fill left shift
186
134
bin_val = bin_val [1 :len (bin_val )] + '0'
135
+ # XORing the result with 0x1b
187
136
final = xor (bin_val , h2b ('1b' ))
188
137
elif bin_val [0 ] == '0' :
189
138
final = bin_val [1 :len (bin_val )] + '0'
190
139
191
140
return final
192
141
193
142
194
- def mix_byte2 (inp ):
195
- mix = mix_byte (inp )
143
+ # implementation of multiplication by 3 in galois field (0x03)
144
+ # example: 0x03 * num = (0x02 + 0x01) * num = num * 0x02 + 0x01 * num
145
+ def multiply_by_03 (inp ):
146
+ mix = multiply_by_02 (inp )
147
+ # addition in galois field is xor
196
148
final = xor (mix , h2b (inp ))
197
149
198
150
return final
@@ -210,7 +162,7 @@ def mix_byte2(inp):
210
162
211
163
# s′0,j = (0x02 × s0,j) ⊗ (0x03 × s1,j ) ⊗ s2,j ⊗ s3,j
212
164
def row0 (row ):
213
- xor01 = xor (mix_byte (row [0 ]), mix_byte2 (row [1 ]))
165
+ xor01 = xor (multiply_by_02 (row [0 ]), multiply_by_03 (row [1 ]))
214
166
xor23 = xor (h2b (row [2 ]), h2b (row [3 ]))
215
167
final_xor = xor (xor01 , xor23 )
216
168
@@ -219,8 +171,8 @@ def row0(row):
219
171
220
172
# s′1,j = s0,j ⊗ (0x02 × s1,j) ⊗ (0x03 × s2,j) ⊗ s3,j
221
173
def row1 (row ):
222
- xor01 = xor (h2b (row [0 ]), mix_byte (row [1 ]))
223
- xor23 = xor (mix_byte2 (row [2 ]), h2b (row [3 ]))
174
+ xor01 = xor (h2b (row [0 ]), multiply_by_02 (row [1 ]))
175
+ xor23 = xor (multiply_by_03 (row [2 ]), h2b (row [3 ]))
224
176
final_xor = xor (xor01 , xor23 )
225
177
226
178
return b2h (final_xor )
@@ -229,16 +181,16 @@ def row1(row):
229
181
# s′2,j = s0,j ⊗ s1,j ⊗ (0x02 × s2,j ) ⊗ (0x03 × s3,j)
230
182
def row2 (row ):
231
183
xor01 = xor (h2b (row [0 ]), h2b (row [1 ]))
232
- xor23 = xor (mix_byte (row [2 ]), mix_byte2 (row [3 ]))
184
+ xor23 = xor (multiply_by_02 (row [2 ]), multiply_by_03 (row [3 ]))
233
185
final_xor = xor (xor01 , xor23 )
234
186
235
187
return b2h (final_xor )
236
188
237
189
238
190
# s′3,j = (0x03 × s0,j) ⊗ s1,j ⊗ s2,j ⊗ (0x02 × s3,j)
239
191
def row3 (row ):
240
- xor01 = xor (mix_byte2 (row [0 ]), h2b (row [1 ]))
241
- xor23 = xor (mix_byte (row [3 ]), h2b (row [2 ]))
192
+ xor01 = xor (multiply_by_03 (row [0 ]), h2b (row [1 ]))
193
+ xor23 = xor (multiply_by_02 (row [3 ]), h2b (row [2 ]))
242
194
final_xor = xor (xor01 , xor23 )
243
195
244
196
return b2h (final_xor )
@@ -253,15 +205,72 @@ def mix_col(s_row):
253
205
return final_row
254
206
255
207
256
- rnd_const = [["01" , "00" , "00" , "00" ], ["02" , "00" , "00" , "00" ], ["04" , "00" , "00" , "00" ], ["08" , "00" , "00" , "00" ],
257
- ["10" , "00" , "00" , "00" ], ["20" , "00" , "00" , "00" ], ["40" , "00" , "00" , "00" ], ["80" , "00" , "00" , "00" ],
258
- ["1b" , "00" , "00" , "00" ], ["36" , "00" , "00" , "00" ]]
208
+ def key_expansion (s_key , rnd ):
209
+ keys = []
210
+
211
+ # Rcon = 128 -> 10, 192 -> 8, 256 -> 7
212
+ # Rcon = [01, 02, 04, 08, 10, 20, 40, 80, 1b, 36]
213
+ # Rcon(i) = [rc(i), 00(0x), 00(0x), 00(0x)]
214
+ # Rcon = [["01", "00", "00", "00"], ["02", "00", "00", "00"], ["04", "00", "00", "00"], ["08", "00", "00", "00"],
215
+ # ["10", "00", "00", "00"], ["20", "00", "00", "00"], ["40", "00", "00", "00"], ["80", "00", "00", "00"],
216
+ # ["1b", "00", "00", "00"], ["36""00", "00", "00"]]
259
217
218
+ for pos in range (0 , 4 ):
219
+ if pos == 0 :
220
+ first_col = []
221
+ tmp = s_key [3 ]
222
+ t_len = len (tmp )
223
+
224
+ for i in range (1 , t_len ):
225
+ first_col = first_col + [tmp [i ]]
226
+ first_col = first_col + [tmp [0 ]]
227
+ col = []
228
+
229
+ f_len = len (first_col )
230
+ for i in range (0 , f_len ):
231
+ col = col + [substitution_box (first_col [i ])]
232
+
233
+ tmp_key = []
234
+ for i in range (0 , 4 ):
235
+ sub_key = xor (h2b (s_key [0 ][i ]), h2b (rnd [i ]))
236
+ sub_key1 = xor (sub_key , h2b (col [i ]))
237
+ tmp_key = tmp_key + [str (b2h (sub_key1 ))]
238
+
239
+ keys = keys + [tmp_key ]
260
240
241
+ elif pos > 0 :
242
+ first_col = []
243
+
244
+ for i in range (0 , 4 ):
245
+ sub_key = xor (h2b (s_key [pos ][i ]), h2b (keys [pos - 1 ][i ]))
246
+ first_col = first_col + [str (b2h (sub_key ))]
247
+
248
+ keys = keys + [first_col ]
249
+ return keys
250
+
251
+
252
+ def add_round (plain_text , keys ):
253
+ row = []
254
+ for i in range (0 , 4 ):
255
+ col = []
256
+ for j in range (0 , 4 ):
257
+ tmp = xor (h2b (keys [i ][j ]), h2b (plain_text [i ][j ]))
258
+ col = col + [b2h (tmp )]
259
+ row = row + [col ]
260
+
261
+ return col_to_row (row )
262
+
263
+
264
+ # checking if entered text is of valid size, and adding fillers
261
265
def valid_block_size (msg ):
262
266
m_len = len (msg )
263
267
final = msg
264
- if m_len % 32 != 0 :
268
+ if m_len > 32 :
269
+ print ("Not a valid size block, Exceeding Block size!" )
270
+ final = final [0 :32 ]
271
+ print ("After filler:" , final )
272
+ return final
273
+ elif m_len % 32 != 0 :
265
274
print ("Not a valid size block" )
266
275
for i in range (abs (32 - (m_len % 32 ))):
267
276
final = final + "0"
@@ -273,7 +282,7 @@ def valid_block_size(msg):
273
282
274
283
275
284
def key_and_text_to_matrix (key_string ):
276
- arr = [["00" for i in range (4 )] for j in range (4 )]
285
+ arr = [["00" for _ in range (4 )] for _ in range (4 )]
277
286
row = 0
278
287
col = 0
279
288
for i in range (0 , len (key_string ), 2 ):
@@ -289,16 +298,21 @@ def key_and_text_to_matrix(key_string):
289
298
return arr
290
299
291
300
292
- def aes_encryption (plaintext , aes_key ):
293
- add_round_key = add_round (plaintext , aes_key )
301
+ rnd_const = [["01" , "00" , "00" , "00" ], ["02" , "00" , "00" , "00" ], ["04" , "00" , "00" , "00" ], ["08" , "00" , "00" , "00" ],
302
+ ["10" , "00" , "00" , "00" ], ["20" , "00" , "00" , "00" ], ["40" , "00" , "00" , "00" ], ["80" , "00" , "00" , "00" ],
303
+ ["1b" , "00" , "00" , "00" ], ["36" , "00" , "00" , "00" ]]
304
+
305
+
306
+ def aes_encryption (plain_text , aes_key ):
307
+ add_round_key = add_round (plain_text , aes_key )
294
308
sub_byte = substitute_byte (add_round_key )
295
309
shift_rows = shift_row (sub_byte )
296
310
mix_column = mix_col (row_to_col (shift_rows ))
297
- add_round_key = add_round (mix_column , key (aes_key , rnd_const [0 ]))
298
- aes_key = key (aes_key , rnd_const [0 ])
311
+ add_round_key = add_round (mix_column , key_expansion (aes_key , rnd_const [0 ]))
312
+ aes_key = key_expansion (aes_key , rnd_const [0 ])
299
313
300
314
for i in range (1 , 9 ):
301
- tmp_key = key (aes_key , rnd_const [i ])
315
+ tmp_key = key_expansion (aes_key , rnd_const [i ])
302
316
aes_key = tmp_key
303
317
sub_byte = substitute_byte (add_round_key )
304
318
shift_rows = shift_row (sub_byte )
@@ -307,7 +321,7 @@ def aes_encryption(plaintext, aes_key):
307
321
308
322
sub_byte = substitute_byte (add_round_key )
309
323
shift_rows = row_to_col (shift_row (sub_byte ))
310
- tmp_key = key (aes_key , rnd_const [9 ])
324
+ tmp_key = key_expansion (aes_key , rnd_const [9 ])
311
325
aes_key = tmp_key
312
326
add_round_key = add_round (shift_rows , aes_key )
313
327
@@ -318,18 +332,18 @@ def aes_encryption(plaintext, aes_key):
318
332
return cipher
319
333
320
334
321
- pt = input ("Enter text: " )
322
- valid_pt_block = valid_block_size (pt )
323
- pt_matrix = key_and_text_to_matrix (pt )
324
- print ("Plaintext Block:" , pt_matrix )
335
+ plaintext = input ("Enter text: " )
336
+ valid_pt_block = valid_block_size (plaintext )
337
+ plaintext_matrix = key_and_text_to_matrix (plaintext )
338
+ print ("Plaintext Block:" , plaintext_matrix )
325
339
print ("---------------------------------------------------------------------------------------------------------------" )
326
340
327
- k = input ("Enter key: " )
328
- valid_k_block = valid_block_size (k )
329
- key_mat = key_and_text_to_matrix (k )
330
- print ("Key Block:" , key_mat )
341
+ key = input ("Enter key: " )
342
+ valid_k_block = valid_block_size (key )
343
+ key_matrix = key_and_text_to_matrix (key )
344
+ print ("Key Block:" , key_matrix )
331
345
print ("---------------------------------------------------------------------------------------------------------------" )
332
346
333
- cipher_text = aes_encryption (pt_matrix , key_mat )
347
+ cipher_text = aes_encryption (plaintext_matrix , key_matrix )
334
348
print ("Encrypted Text: " , cipher_text )
335
349
print ("---------------------------------------------------------------------------------------------------------------" )
0 commit comments