#coding=utf-8
SubBytes = [99, 124, 119, 123, 242, 107, 111, 197, 48, 1, 103, 43, 254, 215, 171, 118, 202, 130, 201, 125, 250, 89, 71,
240, 173, 212, 162, 175, 156, 164, 114, 192, 183, 253, 147, 38, 54, 63, 247, 204, 52, 165, 229, 241, 113,
216, 49, 21, 4, 199, 35, 195, 24, 150, 5, 154, 7, 18, 128, 226, 235, 39, 178, 117, 9, 131, 44, 26, 27, 110,
90, 160, 82, 59, 214, 179, 41, 227, 47, 132, 83, 209, 0, 237, 32, 252, 177, 91, 106, 203, 190, 57, 74, 76,
88, 207, 208, 239, 170, 251, 67, 77, 51, 133, 69, 249, 2, 127, 80, 60, 159, 168, 81, 163, 64, 143, 146, 157,
56, 245, 188, 182, 218, 33, 16, 255, 243, 210, 205, 12, 19, 236, 95, 151, 68, 23, 196, 167, 126, 61, 100,
93, 25, 115, 96, 129, 79, 220, 34, 42, 144, 136, 70, 238, 184, 20, 222, 94, 11, 219, 224, 50, 58, 10, 73,
6, 36, 92, 194, 211, 172, 98, 145, 149, 228, 121, 231, 200, 55, 109, 141, 213, 78, 169, 108, 86, 244, 234,
101, 122, 174, 8, 186, 120, 37, 46, 28, 166, 180, 198, 232, 221, 116, 31, 75, 189, 139, 138, 112, 62, 181,
102, 72, 3, 246, 14, 97, 53, 87, 185, 134, 193, 29, 158, 225, 248, 152, 17, 105, 217, 142, 148, 155, 30,
135, 233, 206, 85, 40, 223, 140, 161, 137, 13, 191, 230, 66, 104, 65, 153, 45, 15, 176, 84, 187, 22]
InvSubBytes = [82, 9, 106, 213, 48, 54, 165, 56, 191, 64, 163, 158, 129, 243, 215, 251, 124, 227, 57, 130, 155, 47, 255,
135, 52, 142, 67, 68, 196, 222, 233, 203, 84, 123, 148, 50, 166, 194, 35, 61, 238, 76, 149, 11, 66, 250,
195, 78, 8, 46, 161, 102, 40, 217, 36, 178, 118, 91, 162, 73, 109, 139, 209, 37, 114, 248, 246, 100, 134,
104, 152, 22, 212, 164, 92, 204, 93, 101, 182, 146, 108, 112, 72, 80, 253, 237, 185, 218, 94, 21, 70, 87,
167, 141, 157, 132, 144, 216, 171, 0, 140, 188, 211, 10, 247, 228, 88, 5, 184, 179, 69, 6, 208, 44, 30,
143, 202, 63, 15, 2, 193, 175, 189, 3, 1, 19, 138, 107, 58, 145, 17, 65, 79, 103, 220, 234, 151, 242,
207, 206, 240, 180, 230, 115, 150, 172, 116, 34, 231, 173, 53, 133, 226, 249, 55, 232, 28, 117, 223, 110,
71, 241, 26, 113, 29, 41, 197, 137, 111, 183, 98, 14, 170, 24, 190, 27, 252, 86, 62, 75, 198, 210, 121,
32, 154, 219, 192, 254, 120, 205, 90, 244, 31, 221, 168, 51, 136, 7, 199, 49, 177, 18, 16, 89, 39, 128,
236, 95, 96, 81, 127, 169, 25, 181, 74, 13, 45, 229, 122, 159, 147, 201, 156, 239, 160, 224, 59, 77, 174,
42, 245, 176, 200, 235, 187, 60, 131, 83, 153, 97, 23, 43, 4, 126, 186, 119, 214, 38, 225, 105, 20, 99,
85, 33, 12, 125]
# Ann-key
key = [34, 50, 39, 46, 63, 52, 43, 48, 49, 36, 62, 44, 0, 52, 49, 45]
cypher_text = [215, 220, 130, 142, 1, 187, 9, 64, 180, 78, 51, 5, 15, 210, 0, 1, 50, 252, 158, 5, 51, 245, 45, 128, 88,
246, 211, 30, 20, 89, 42, 243]
key = [35, 54, 46, 49, 58, 45, 34, 0, 52, 0, 38, 41, 39, 47, 49, 47]
cypher_text = [13, 84, 192, 126, 130, 148, 115, 248, 109, 253, 42, 181, 128, 21, 115, 30,
96, 90, 109, 242, 36, 113, 33, 63, 247, 21, 202, 79, 97, 202, 67, 189]
modul = [8, 4, 3, 1, 0]
poly_const = [[3, 2, 1], [3, 1, 0], [3, 2, 0], [3, 0]]
round_keys = []
empty_char = 0
key_block_len = 16
dec_hex = lambda num: (hex(num)[2:]).zfill(2)
#Убрать можно
int2bin = lambda num: (bin(num)[2:]).zfill(8)
#__________ФУНКЦИИ ВСПОМОГАТЕЛЬНЫЕ
def convert_num_poly(num):
for_print = num
res = []
num = bin(num)[2:]
bin_len = len(num)
for offset, ch in enumerate(num):
if ch == '1':
res.append(bin_len-offset-1)
print "DEC2POLY: %s = %s" % (for_print, res)
return res
def sub_bytes(list_num, table):
res = []
for num in list_num:
res.append(table[num])
return res
def right_rotate(data, shift):
tmp = data[-shift:]
return tmp + data[:-shift]
def left_rotate(data, shift):
tmp = data[shift:]
return tmp + data[:shift]
def xor_lists(f_list, s_list):
res = []
res_len = max(len(f_list), len(s_list))
if len(f_list) != res_len:
f_list = [0, ] * (res_len - len(f_list)) + f_list
if len(s_list) != res_len:
s_list = [0, ] * (res_len - len(s_list)) + s_list
for offset in range(res_len):
res.append(f_list[offset] ^ s_list[offset])
return res
def generate_keys(keyword):
global round_keys
round_keys = keyword[:]
for current in range(4, 16):
if current % 4 == 0:
print "\nw[%s] = SubBytes(left_rotate(w[%s], 1)) ^ 2**%s ^ w[%s]" % (current, current-1,
((current / 4) - 1), current-4)
print "w[%s] = %s" % (current-1, " ".join(map(dec_hex, round_keys[-4:])))
val = left_rotate(round_keys[-4:], 1)
print "l_rot = %s" % (" ".join(map(dec_hex, val)))
val = sub_bytes(val, SubBytes)
print "sub_b = %s" % (" ".join(map(dec_hex, val)))
val = xor_lists(val, [2 ** ((current / 4) - 1), ])
print "xor_2 = %s" % (" ".join(map(dec_hex, val)))
val = xor_lists(val, round_keys[len(round_keys) - 4 * 4:len(round_keys) - 4 * 3])
print "w[%s] = %s" % (current-4, " ".join(map(dec_hex, round_keys[len(round_keys) - 4 * 4:len(round_keys) - 4 * 3])))
print "-"*43
print "reslt = %s" % (" ".join(map(dec_hex, val)))
else:
w_prev1 = round_keys[-4:]
w_prev4 = round_keys[len(round_keys) - 4 * 4:len(round_keys) - 4 * 3]
val = xor_lists(w_prev1, w_prev4)
#ПОШАГОВЫЙ ВЫВОД ПРОЦЕССА ВЫЧИСЛЕНИЯ КЛЮЧЕЙ
print "\nw[%s] = w[%s] ^ w[%s]" % (current, current-1, current-4)
print " ".join(map(int2bin, w_prev1))
print " ".join(map(int2bin, w_prev4))
print "-"*35
print " ".join(map(int2bin, val))
#КОНЕЦ ПРОЦЕССА ВЫВОДВ ВЫЧИСЛЕНИЯ КЛЮЧЕЙ
round_keys += val
def convert_poly(polynom):
for_print = polynom
res = 0
for pw in polynom:
res += 2**pw
#print "...CONVERT: %s -> %s" % (for_print, res)
return res
def polynom_mnoj(f_polynom, s_polynom):
f_prnt = f_polynom
s_prnt = s_polynom
res = []
for f in f_polynom:
for s in s_polynom:
res.append(f + s)
res = polynom_reduce(res)
print "POLY_MUL: %s * %s = %s" % (f_prnt, s_prnt, res)
return res
def polynom_reduce(polynom):
for_print = polynom
res = []
unic = list(set(polynom))
for pw in unic:
if polynom.count(pw) % 2 != 0:
res.append(pw)
#print "POLY_REDUCE: %s ---> %s" % (for_print, res)
return res
def polynom_compare_with_mod(polynom, modul):
if max(polynom) > max(modul):
return False
polynom_dec = convert_poly(polynom)
modul_dec = convert_poly(modul)
return polynom_dec < modul_dec
def polynom_by_modul(polunom):
print "======"
while convert_poly(polunom) > 255:
somnoj = max(polunom) - max(modul)
sh = polynom_mnoj(modul, [somnoj, ])
print "NEED POLY<%s> BY MOD<%s> * %s = %s" % (polunom, modul, somnoj, sh)
temp = polunom
polunom = polynom_reduce(polunom + sh)
print "...POLY_BY_MOD: %s XOR %s = %s" % (temp, sh, polunom)
print "-------\n"
return polunom
#__________ФУНКЦИИ РАБОТЫ С ПОЛИНОМАМИ КОНЕЦ
def print_state(data, column_num = 0):
hex_data = map(dec_hex, data)
if column_num:
for offset in range(0, len(hex_data), column_num):
print " ".join(hex_data[offset:offset+column_num])
else:
print " ".join(hex_data)
#__________ФУНКЦИИ ДЕКОДИРОВАНИЯ
def InvSubBytes_func(state):
res = sub_bytes(state, InvSubBytes)
print_state(res, 4)
return res
def InvShiftRows_func(state):
res = []
for offset in range(4):
tmp = state[offset*4:(offset + 1)*4]
res += right_rotate(tmp, offset)
print_state(res, 4)
return res
def AddRoundKey_func(offset_rkey, state):
res = xor_lists(state, round_keys[offset_rkey * 4: (offset_rkey + 4) * 4])
print_state(res, 4)
return res
def InvMixColumns_func(state):
res_block = []
for line_num in range(4):
tmp = right_rotate(poly_const, line_num)
res = []
for i in range(len(state)):
res.append(polynom_by_modul(polynom_mnoj(convert_num_poly(state[i]), tmp[i / 4])))
for j in range(len(state) / 4):
prnt = convert_poly(polynom_reduce(reduce(lambda a, b: a + b, res[j::4])))
res_block.append(prnt)
print_state(res_block, 4)
return res_block
#__________ФУНКЦИИ ДЕКОДИРОВАНИЯ КОНЕЦ
def main():
global round_keys
generate_keys(key)
print "\n>>>>> ROUND KEYS:"
print_state(round_keys, 4)
for block_num in range(0, len(cypher_text), 16):
print "\n=========== BLOCK OF DATA [%s of %s]: ===========" % (1 + block_num / 16, len(cypher_text) / 16)
print "Step1:"
tmp_block = cypher_text[block_num:block_num + 16]
print_state(tmp_block)
#Xor with round_key_4
print "Step2:"
tmp_block = AddRoundKey_func(12, tmp_block)
#InvShiftRows
print "Step3:"
tmp_block = InvShiftRows_func(tmp_block)
#InvSubBytes
print "Step4:"
tmp_block = InvSubBytes_func(tmp_block)
#Xor with round_key_3
print "Step5:"
tmp_block = AddRoundKey_func(8, tmp_block)
#InvMixColumn
print "Step6:"
tmp_block = InvMixColumns_func(tmp_block)
#InvShiftRows
print "Step7:"
tmp_block = InvShiftRows_func(tmp_block)
#InvSubBytes
print "Step8:"
tmp_block = InvSubBytes_func(tmp_block)
#Xor with round_key_2
print "Step9:"
tmp_block = AddRoundKey_func(4, tmp_block)
#InvMixColumn
print "Step10:"
tmp_block = InvMixColumns_func(tmp_block)
#InvShiftRows
print "Step11:"
tmp_block = InvShiftRows_func(tmp_block)
#InvSubBytes
print "Step12:"
tmp_block = InvSubBytes_func(tmp_block)
#Xor with round_key_1
print "Step13:"
tmp_block = AddRoundKey_func(0, tmp_block)
print "RESULT:"
print tmp_block
print "All right!"
if __name__ == "__main__":
main()