""" Lilliput TBC """ import random import constant import multiplications BLOCK_BITS = 128 KEY_BITS = 128 TWEAK_BITS = 192 LANE_BITS = 64 LANE_BYTES = LANE_BITS / 8 LANES = int((TWEAK_BITS+KEY_BITS) / LANE_BITS) ROUNDS = 32 BLOCK_BYTES = int(BLOCK_BITS / 8) TWEAKEY_BITS = KEY_BITS + TWEAK_BITS KEY_BYTES = int(KEY_BITS / 8) TWEAK_BYTES = int(TWEAK_BITS / 8) TWEAKEY_BYTES = int(TWEAKEY_BITS / 8) Sbox = constant.Sbox MultiplyM = multiplications.MultiplyM MultiplyM2 = multiplications.MultiplyM2 MultiplyM3 = multiplications.MultiplyM3 MultiplyMR = multiplications.MultiplyMR MultiplyMR2 = multiplications.MultiplyMR2 MultiplyMR3 = multiplications.MultiplyMR3 permutation = [14, 11, 12, 10, 8, 9, 13, 15, 3, 1, 4, 5, 6, 0, 2, 7] permutationInv = [13, 9, 14, 8, 10, 11, 12, 15, 4, 5, 3, 1, 2, 6 ,0 ,7] # Personnal global variables to check better TKs = [[0 for byte in range(0, TWEAKEY_BYTES)] for round in range(0, ROUNDS)] RTKs = [[0 for byte in range(0, 8)] for round in range(0, ROUNDS)] States = [[0 for byte in range(0, BLOCK_BYTES)] for round in range(0, ROUNDS)] ################################################################################ def BuildTweakey(tweak, key) : tweakey = [0 for byte in range(0, TWEAKEY_BYTES)] for byte in range(0, TWEAK_BYTES) : tweakey[byte] = tweak[byte] for byte in range(0, KEY_BYTES) : tweakey[byte + TWEAK_BYTES] = key[byte] return tweakey ############################# def RoundTweakeySchedule(tweakey) : # Multiplication lanes = [tweakey[word * 8:(word+1) * 8] for word in range(0, LANES)] tweakey_multiplied = [] for word in range(0, LANES) : if word == 0 : tweakey_multiplied += list(lanes[0]) elif word == 1 : tweakey_multiplied += MultiplyM(lanes[1]) elif word == 2 : tweakey_multiplied += MultiplyM2(lanes[2]) elif word == 3 : tweakey_multiplied += MultiplyM3(lanes[3]) elif word == 4 : tweakey_multiplied += MultiplyMR(lanes[4]) elif word == 5 : tweakey_multiplied += MultiplyMR2(lanes[5]) elif word == 6 : tweakey_multiplied += MultiplyMR3(lanes[6]) return tweakey_multiplied ; def SubTweakeyExtract(tweakey, round) : subtweakey = [0 for byte in range(0, 8)] for byte in range(0, TWEAKEY_BYTES) : subtweakey[byte % 8] ^= tweakey[byte] subtweakey[0] ^= round return subtweakey def TweakeyScheduleWhole(tweakey) : # store main tweakey in TKs[0] # and corresponding RTKs[0] TKs[0] = tweakey RTKs[0] = SubTweakeyExtract(TKs[0], 0) for round in range(1, ROUNDS) : TKs[round] = RoundTweakeySchedule(TKs[round - 1]) RTKs[round] = SubTweakeyExtract(TKs[round], round) ################################################################################ def NonLinearLayer(state, subtweakey) : variables_xored = [0 for byte in range(0, 8)] for byte in range(0,8) : variables_xored[byte] = state[byte] ^ subtweakey[byte] variables_sboxed = [0 for byte in range(0, 8)] for byte in range(0, 8) : variables_sboxed[byte] = Sbox[variables_xored[byte]] state_output = [0 for byte in range(0, BLOCK_BYTES)] for byte in range(0,BLOCK_BYTES) : state_output[byte] = state[byte] for byte in range(0, 8) : state_output[15 - byte] ^= variables_sboxed[byte] return state_output def LinearLayer(state) : state_output = [0 for byte in range(0, BLOCK_BYTES)] for byte in range(0, BLOCK_BYTES) : state_output[byte] = state[byte] for byte in range(1, 8) : state_output[15] ^= state[byte] for byte in range(9, 15) : state_output[byte] ^= state[7] return state_output def PermutationLayerEnc(state) : state_output = [0 for byte in range(0, BLOCK_BYTES)] for byte in range(0, BLOCK_BYTES) : state_output[byte] = state[permutation[byte]] return state_output def PermutationLayerDec(state) : state_output = [0 for byte in range(0, BLOCK_BYTES)] for byte in range(0, BLOCK_BYTES) : state_output[byte] = state[permutationInv[byte]] return state_output def OneRoundEGFNEnc(state, subtweakey, round) : state_non_linear = NonLinearLayer(state, subtweakey) state_linear = LinearLayer(state_non_linear) state_permutation = PermutationLayerEnc(state_linear) return state_permutation def LastRoundEGFN(state, subtweakey, round) : state_non_linear = NonLinearLayer(state, subtweakey) state_linear = LinearLayer(state_non_linear) return state_linear def OneRoundEGFNDec(state, subtweakey, round) : state_non_linear = NonLinearLayer(state, subtweakey) state_linear = LinearLayer(state_non_linear) state_permutation = PermutationLayerDec(state_linear) return state_permutation ################################################################################ # Lilliput TBC def LilliputTBCEnc(tweak, key, message) : global TKs global RTKs global states TKs = [[0 for byte in range(0, TWEAKEY_BYTES)] for round in range(0, ROUNDS)] RTKs = [[0 for byte in range(0, 8)] for round in range(0, ROUNDS)] States = [[0 for byte in range(0, BLOCK_BYTES)] for round in range(0, ROUNDS)] tweakey = BuildTweakey(tweak, key) TweakeyScheduleWhole(tweakey) state = [0 for byte in range(0, BLOCK_BYTES)] for byte in range(0, BLOCK_BYTES) : state[byte] = message[byte] for round in range(0, ROUNDS - 1) : state_output = OneRoundEGFNEnc(state, RTKs[round], round = round) for byte in range(0, BLOCK_BYTES) : state[byte] = state_output[byte] state_output = LastRoundEGFN(state, RTKs[ROUNDS - 1], round = ROUNDS - 1) return state_output def LilliputTBCDec(tweak, key, cipher) : global TKs global RTKs global states TKs = [[0 for byte in range(0, TWEAKEY_BYTES)] for round in range(0, ROUNDS)] RTKs = [[0 for byte in range(0, 8)] for round in range(0, ROUNDS)] States = [[0 for byte in range(0, BLOCK_BYTES)] for round in range(0, ROUNDS)] tweakey = BuildTweakey(tweak, key) TweakeyScheduleWhole(tweakey) state = [0 for byte in range(0, BLOCK_BYTES)] for byte in range(0, BLOCK_BYTES) : state[byte] = cipher[byte] for round in range(0, ROUNDS - 1) : state_output = OneRoundEGFNDec(state, RTKs[ROUNDS - round - 1], round = round) for byte in range(0, BLOCK_BYTES) : state[byte] = state_output[byte] state_output = LastRoundEGFN(state, RTKs[0], round = ROUNDS - 1) return state_output ################################################################################ # def main() : # # """tweak = [random.randint(0,255) for byte in range(0, number_bytes_tweak)] # key = [random.randint(0,255) for byte in range(0, number_bytes_key)] # message = [random.randint(0,255) for byte in range(0, 16)]""" # #cipher = [204, 93, 118, 73, 153, 116, 241, 228, 56, 160, 234, 207, 42, 199, 19, 147] # null # #cipher = [104, 79, 113, 74, 255, 166, 160, 78, 195, 74, 93, 105, 73, 157, 113, 228] # order # #message = [188, 215, 240, 41, 132, 182, 200, 249, 156, 157, 29, 189, 13, 48, 148, 11] # #cipher = [245, 195, 174, 174, 35, 1, 31, 176, 201, 93, 83, 38, 103, 211, 216, 223] # #tweak = [168, 67, 243, 16, 129, 17, 28, 132, 223, 248, 46, 250, 144, 144, 38, 33, 125, 141, 67, 18, 42, 179, 210, 77] # #key = [193, 150, 198, 10, 2, 115, 145, 104, 127, 244, 35, 77, 61, 213, 249, 155] # global KEY_BITS # global TWEAK_BITS # global LANES # global ROUNDS # global TWEAKEY_BITS # global KEY_BYTES # global TWEAK_BYTES # global TWEAKEY_BYTES # KEY_BITS = 256 # TWEAK_BITS = 128 # TWEAKEY_BITS = KEY_BITS + TWEAK_BITS # LANES = int((TWEAKEY_BITS) / LANE_BITS) # ROUNDS = 42 # KEY_BYTES = int(KEY_BITS / 8) # TWEAK_BYTES = int(TWEAK_BITS / 8) # TWEAKEY_BYTES = int(TWEAKEY_BITS / 8) # # tweak = [byte for byte in range(0, TWEAK_BYTES)] # key = [byte for byte in range(0, KEY_BYTES)] # message = [byte for byte in range(0, BLOCK_BYTES)] # # # # cipher = LilliputTBCEnc(tweak, key, message) # print(message) # print(cipher) # print(tweak) # print(key) # for index,byte in enumerate(cipher) : # print("%02x "%(cipher[15-index]), end="") # print() # #deciphered = LilliputTBCDec(tweak, key, cipher, verbose = 0) # #print(deciphered) # # #main()