def linear_layer(self, x_in, x_out): x_in = [ x_in[(8 * shift_rows[i // 8]) + (i % 8)] for i in range(128) ] # variables after ShiftRows and before MixColumns for col, bit in itp(range(4), range(8)): bit_list = [x_in[(32 * row) + (8 * col) + bit] for row in range(4)] + [ x_out[(32 * row) + (8 * col) + bit] for row in range(4) ] self.add_bin_matrix_constr( self.mixcol, bit_list, 0, mode="integer", )
def run(self, T=1000, gamma=1, n_iter=100): self.gamma = gamma self.update_time = [] self.n_iter = n_iter while self.t < T: print("iteration", self.t) # choose next action a = self.policy[self.state] self.arm_sequence.append(a) # Observe reward r = self.reward(ast.literal_eval(self.state), a) self.reward_sequence.append(r) # update self.N.loc[self.state, a] += 1 self.R[self.state, a] += r self.state = self.transition(self.state, a) # next state update_policy = False _conf = np.log(2 * (self.t + 1**self.alpha) * self.cardS * self.cardA) new_conf = deepcopy(self.conf) for s_a in itp(*[self.states, self.actions]): s, a = s_a new_conf[s][a] = self.conf_r(self.t + 1, s, a, _conf) if new_conf[s][a] < self.conf[s][a] / 2: update_policy = True if self.N[s][a] > 0: self.r_hat[s][a] = self.R[s][a] / self.N[s][a] # update policy ? if update_policy: self.round += 1 self.update_time.append(self.t + 1) print('update policy, round=', self.round) self.conf = deepcopy(new_conf) self.policyUpdate(self.r_hat) self.t += 1
Astate = list(np.repeat(0, window)) Bstate = list(np.repeat(1, window)) mnA = data.loc[str( Astate ), 'mn_rewardA'] #0.09166072904895288 # computed from user that have a frequency of A of 1 mnB = data.loc[ str(Bstate), 'mn_rewardB'] # computed from user that have a frequency of A of 0 K = 2 gamma = .99 n_iter = 200 for repeat_ in range(nRepeat): S = list(itp(range(K), repeat=window)) # all possibles states S = list(map(lambda s: str(list(s)), S)) def next_state_(x, a): # x[j] contains the arm that have been played j+1 timesteps ago y = deepcopy(x) y = y[:-1] y = [a] + y return y def Bellman_a(a, gamma, state): # update for one state at random if a == 0: r = deepcopy(data.loc[state, 'mn_rewardA']) else: r = deepcopy(data.loc[state, 'mn_rewardB'])
def differential_trail_search(self, active_sboxes): """ Computes a differential trail with the highest possible probability given a class of truncated differential characteristics """ local_constraints = [] y = dict() idx = 0 for r, i in itp(range(self.nb_rounds), range(self.nb_nibbles)): y[r, i] = self.model.addVar(name="active_({}, {})".format(r, i), vtype=GRB.BINARY) bits = [ self.in_sbox[r, (self.nibble_size * i) + j] for j in range(self.nibble_size) ] + [ self.out_sbox[r, (self.nibble_size * i) + j] for j in range(self.nibble_size) ] lc = self.model.addGenConstrOr(y[r, i], bits) local_constraints.append(lc) lc = self.model.addConstr(y[r, i] == quicksum([ self.Q64[r, i], self.Q48[r, i], self.Q40[r, i], self.Q32[r, i], self.Q28[r, i], self.Q24[r, i], self.Q20[r, i], self.Q16[r, i], self.Q12[r, i], self.Q8[r, i], self.Q6[r, i], self.Q4[r, i], self.Q2[r, i] ])) local_constraints.append(lc) lc = self.model.addConstr(y[r, i] == int(active_sboxes[idx])) local_constraints.append(lc) idx += 1 # We fix at least one active input cell lc = self.model.addConstr( quicksum(y[0, i] for i in range(self.nb_nibbles)) >= 1) local_constraints.append(lc) # Additional constraint to indicate the minimum number of active S-boxes idx = { 2: 2.0, 3: 5.0, 4: 8.0, 5: 12.0, 6: 16.0, 7: 26.0, 8: 36.0, 9: 41.0, 10: 46.0, 11: 51.0, 12: 55.0, 13: 58.0, 14: 61.0 } lc = self.model.addConstr( quicksum( y[r, i] for r, i in itp(range(self.nb_rounds), range(self.nb_nibbles))) >= idx[self.nb_rounds]) local_constraints.append(lc) self.model.optimize() # Parsing results output = "" file = open("SKINNY128_DDT.txt", "r") diff = file.readlines() file.close() probability_index = [] diff = diff[2:] for i in range(len(diff)): temp = diff[i][23:] assert temp[1] == '/' or temp[2] == '/' if temp[1] == '/': probability_index.append(int(temp[0])) else: probability_index.append(int(temp[:2])) diff[i] = diff[i][:8] + diff[i][13:21] output += "Skinny-128, %s rounds\n" % self.nb_rounds output += "Truncated differential characteristics : %s\n" % active_sboxes all_status = {2: "OPTIMAL", 6: "CUTOFF", 9: "TIME_LIMIT"} if self.model.status in all_status and self.model.SolCount > 0: output += "Model status : %s\n" % all_status[self.model.status] total = 0 for r, i in itp(range(self.nb_rounds), range(self.nb_nibbles)): total += y[r, i].x output += "Best probability found : 2^(-%s) | Number of active S-boxes : %s\n" % ( self.model.getObjective().getValue(), total) for r in range(self.nb_rounds): temp = "" temp2 = "" transition_probability = "" for i in range(self.nb_nibbles): if y[r, i].x >= 0.5: current_diff = "" a = [ self.in_sbox[r, (self.nibble_size * i) + j].x for j in range(self.nibble_size) ] for x in a: if x >= 0.5: current_diff = current_diff + "1" else: current_diff = current_diff + "0" temp = temp + "{:02x}".format(int(current_diff, 2)) current_diff2 = "" b = [ self.out_sbox[r, (self.nibble_size * i) + j].x for j in range(self.nibble_size) ] for x in b: if x >= 0.5: current_diff = current_diff + "1" current_diff2 = current_diff2 + "1" else: current_diff = current_diff + "0" current_diff2 = current_diff2 + "0" temp2 = temp2 + "{:02x}".format(int(current_diff2, 2)) transition_probability = transition_probability + str( probability_index[diff.index( current_diff)]) + "/256." else: temp = temp + "00" temp2 = temp2 + "00" output += "Round : %s | Before SB : %s | After SB : %s | Probability : %s\n" \ % (r + 1, utilities.parse_space(temp), utilities.parse_space(temp2), transition_probability) output += "-----------------\n" else: output += "Failure, model status %s\n" % self.model.status # Removing local constraints and variables for lc in local_constraints: self.model.remove(lc) for r, i in itp(range(self.nb_rounds), range(self.nb_nibbles)): self.model.remove(y[r, i]) return output
def __init__(self, state_size, nb_rounds, sbox_file): Primitive.__init__(self, state_size, state_size) self.nb_rounds = nb_rounds self.sbox_name = sbox_file with open(sbox_file, "rb") as f: (in_nibble_size, out_nibble_size, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _) = pickle.load(f) assert in_nibble_size == out_nibble_size nibble_size = in_nibble_size assert state_size % nibble_size == 0 nb_nibbles = state_size // nibble_size self.add_sbox_modeling(sbox_file) self.state_size = state_size # equal to 128 self.nibble_size = nibble_size self.nb_nibbles = nb_nibbles in_sbox = {} # in_sbox for sbox input out_sbox = {} # out_sbox for sbox output Q64 = {} Q48 = {} Q40 = {} Q32 = {} Q28 = {} Q24 = {} Q20 = {} Q16 = {} Q12 = {} Q8 = {} Q6 = {} Q4 = {} Q2 = {} for i, j in itp(range(nb_rounds), range(state_size)): in_sbox[i, j] = self.model.addVar(name="in_sbox_({}, {})".format( i, j), vtype=GRB.BINARY) for i, j in itp(range(nb_rounds), range(state_size)): out_sbox[i, j] = self.model.addVar(name="out_sbox_({}, {})".format( i, j), vtype=GRB.BINARY) for r, i in itp(range(nb_rounds), range(nb_nibbles)): Q64[r, i] = self.model.addVar( name="Q64_({}, {})".format(r, i), vtype=GRB.BINARY, obj=2.00, ) Q48[r, i] = self.model.addVar( name="Q48_({}, {})".format(r, i), vtype=GRB.BINARY, obj=2.42, ) Q40[r, i] = self.model.addVar( name="Q40_({}, {})".format(r, i), vtype=GRB.BINARY, obj=2.68, ) Q32[r, i] = self.model.addVar( name="Q32_({}, {})".format(r, i), vtype=GRB.BINARY, obj=3.00, ) Q28[r, i] = self.model.addVar( name="Q28_({}, {})".format(r, i), vtype=GRB.BINARY, obj=3.20, ) Q24[r, i] = self.model.addVar( name="Q24_({}, {})".format(r, i), vtype=GRB.BINARY, obj=3.42, ) Q20[r, i] = self.model.addVar( name="Q20_({}, {})".format(r, i), vtype=GRB.BINARY, obj=3.68, ) Q16[r, i] = self.model.addVar( name="Q16_({}, {})".format(r, i), vtype=GRB.BINARY, obj=4.00, ) Q12[r, i] = self.model.addVar( name="Q12_({}, {})".format(r, i), vtype=GRB.BINARY, obj=4.42, ) Q8[r, i] = self.model.addVar( name="Q8_({}, {})".format(r, i), vtype=GRB.BINARY, obj=5.00, ) Q6[r, i] = self.model.addVar( name="Q6_({}, {})".format(r, i), vtype=GRB.BINARY, obj=5.42, ) Q4[r, i] = self.model.addVar( name="Q4_({}, {})".format(r, i), vtype=GRB.BINARY, obj=6.00, ) Q2[r, i] = self.model.addVar( name="Q2_({}, {})".format(r, i), vtype=GRB.BINARY, obj=7.00, ) self.Q64 = Q64 self.Q48 = Q48 self.Q40 = Q40 self.Q32 = Q32 self.Q28 = Q28 self.Q24 = Q24 self.Q20 = Q20 self.Q16 = Q16 self.Q12 = Q12 self.Q8 = Q8 self.Q6 = Q6 self.Q4 = Q4 self.Q2 = Q2 for i in range(state_size): self.in_var[i] = in_sbox[0, i] self.out_var[i] = out_sbox[nb_rounds - 1, i] for i in range(nb_rounds): self.subcell( [in_sbox[i, j] for j in range(state_size)], [out_sbox[i, j] for j in range(state_size)], i, ) for i in range(nb_rounds - 1): self.linear_layer( [out_sbox[i, j] for j in range(state_size)], [in_sbox[i + 1, j] for j in range(state_size)], ) self.in_sbox = in_sbox self.out_sbox = out_sbox
K = len(phi) M = K**window print('Space state size:', M) description = ["Decaying arms with :"] description.append("- " + str(K) + " arms ") description.append("- a window of length " + str(window)) for a in range(K): description.append("- arm " + str(a) + ": " + str(phi[a])) mydir = 'README_param' + str(_it) + '.txt' np.savetxt(path + mydir, tuple(description), fmt="%s") V = {} S = itp(range(K), repeat=window) # all possibles states for state in S: state = list(state) V[str(state)] = 0 stops = [1000] #,1000] gamma = 0.99 n_iter = max(stops) policies = dict.fromkeys(stops) for it in range(n_iter): mem = deepcopy(V) # copy old value S = itp(range(K), repeat=window) # all possibles states S = list(S) shuffle(S) for state in S: state = list(state) V[str(state)] = max(