nb=4

def mul_by_02(num):

"""The function multiplies by 2 in Galua space"""

if num < 0x80:

res = (num << 1)

else:

res = (num << 1)^0x1b

return res % 0x100

def mul_by_09(num):

#return mul_by_03(num)^mul_by_03(num)^mul_by_03(num) - works wrong, I don't know why

return mul_by_02(mul_by_02(mul_by_02(num)))^num

def mul_by_0b(num):

#return mul_by_09(num)^mul_by_02(num)

return mul_by_02(mul_by_02(mul_by_02(num)))^mul_by_02(num)^num

def mul_by_0d(num):

#return mul_by_0b(num)^mul_by_02(num)

return mul_by_02(mul_by_02(mul_by_02(num)))^mul_by_02(mul_by_02(num))^num

def mul_by_0e(num):

#return mul_by_0d(num)^num

return mul_by_02(mul_by_02(mul_by_02(num)))^mul_by_02(mul_by_02(num))^mul_by_02(num)

def mix_columns(state):

for i in range(nb):

s0 = mul_by_0e(state[0][i])^mul_by_0b(state[1][i])^mul_by_0d(state[2][i])^mul_by_09(state[3][i])

s1 = mul_by_09(state[0][i])^mul_by_0e(state[1][i])^mul_by_0b(state[2][i])^mul_by_0d(state[3][i])

s2 = mul_by_0d(state[0][i])^mul_by_09(state[1][i])^mul_by_0e(state[2][i])^mul_by_0b(state[3][i])

s3 = mul_by_0b(state[0][i])^mul_by_0d(state[1][i])^mul_by_09(state[2][i])^mul_by_0e(state[3][i])

state[0][i] = s0

state[1][i] = s1

state[2][i] = s2

state[3][i] = s3

return state

state = []

mix_columns(state)