def inv(column): fixedmatrix = bytearray([0x0e, 0x0b, 0x0d, 0x09]) mixcolumnmatrix = bytearray() for i in range(0, 4): resultinglist = [] rijndael = gf.makeblist(0x11b) for j in range(0, 4): fixedbitlist = gf.makeblist(fixedmatrix[j]) columnvector = gf.makeblist(column[j]) resultingbyte = gf.mul(fixedbitlist, columnvector) while gf.value(resultingbyte) > 255: # note the inverted division function! resultingbyte = gf.div(rijndael, resultingbyte)[1] resultinglist.append(resultingbyte) finalvalue = gf.add(resultinglist[0], resultinglist[1]) finalvalue = gf.add(finalvalue, resultinglist[2]) finalvalue = gf.add(finalvalue, resultinglist[3]) mixcolumnmatrix.append(gf.value(finalvalue)) fixedmatrix = gf.circrotateright(fixedmatrix) return mixcolumnmatrix
def mix(column): fixedmatrix = bytearray([0x02, 0x03, 0x01, 0x01]) mixcolumnmatrix = bytearray() for i in range(4): resultinglist = [] rijndael = gf.makeblist(0x11b) for j in range(4): fixedbytelist = gf.makeblist(fixedmatrix[j]) columnvector = gf.makeblist(column[j]) resultingbyte = gf.mul(fixedbytelist, columnvector) if gf.value(resultingbyte) > 255: resultingbyte = gf.div(resultingbyte, rijndael)[1] resultinglist.append(resultingbyte) finalvalue = gf.add(resultinglist[0], resultinglist[1]) finalvalue = gf.add(finalvalue, resultinglist[2]) finalvalue = gf.add(finalvalue, resultinglist[3]) mixcolumnmatrix.append(gf.value(finalvalue)) fixedmatrix = gf.circrotateright(fixedmatrix) return mixcolumnmatrix
def make(): table = [] for i in range(0, 256): bitlist = gf.makeblist(int(i)) table.append(gf.inverse(bitlist)) affmatrix = aff.makematrix() sbox = [] for i in range(0, 256): sbox.append(aff.transform(table[i], affmatrix)) for i in range(0, 256): sbox[i] = bytes([gf.value(sbox[i])]) return sbox
def maketable(): rcontable = [] rcontable.append([1, 0, 0, 0, 1, 1, 0, 1]) # rcon[0] rcon = gf.makeblist(0x01) rijn = gf.makeblist(0x11b) for i in range(52): rcontable.append(rcon) # this is actually a leftwise shift, multiply by 2 rcon = gf.mul(rcon, [0, 0, 0, 0, 0, 0, 1, 0]) if gf.value(rcon) > 255: # take the remainder from division operation (modulus) rcon = gf.div(rcon, rijn)[1] return rcontable
def makeroundkey(previouskey, round, rcontable, subbox): # Split the key to 4 byte slices: w0 = bytearray(previouskey[0:4]) w1 = bytearray(previouskey[4:8]) w2 = bytearray(previouskey[8:12]) w3 = bytearray(previouskey[-4:]) # Perform a circular byte left shift to w3: [0,1,2,3] -> [1,2,3,0] gw3 = bytearray(w3[1:] + w3[:1]) # Apply Rijndael S-box to gw3 bytes (substitution): for i in range(len(gw3)): gw3[i] = int.from_bytes(subbox[gw3[i]], byteorder='big') # Add round constant to the leftmost byte in gw3 # Adding is in GF rconbyte = gf.makeblist(gw3[0]) gw3[0] = gf.value(gf.add(rcontable[round], rconbyte)) # Build the roundkey: w4 = bytearray(4) w5 = bytearray(4) w6 = bytearray(4) w7 = bytearray(4) for i in range(4): w4[i] = gw3[i] ^ w0[i] for i in range(4): w5[i] = w4[i] ^ w1[i] for i in range(4): w6[i] = w5[i] ^ w2[i] for i in range(4): w7[i] = w6[i] ^ w3[i] roundkey = w4 + w5 + w6 + w7 return roundkey
def makeinverse(): sbox = [] for i in range(0, 256): bitlist = gf.makeblist(int(i)) gf.removeleadingzero(bitlist) sbox.append(bitlist) affmatrix = aff.makeinversematrix() for i in range(0, 256): sbox[i] = aff.inversetransform(sbox[i], affmatrix) sbox[i] = gf.inverse(sbox[i]) for i in range(0, 256): sbox[i] = bytes([gf.value(sbox[i])]) #aff.printmatrix(sbox) return sbox
def printmatrix(m): for i in range(len(m)): print(m[i], hex(gf.value(m[i])))
def blhex(bitlist): print(hex(gf.value(bitlist)))