def strategy_block_cost(self, L, e): """ Next function computes the expected cost of our approach by assuming we have full torsion points """ elligator_cost = numpy.array([7.0, 3.0, 10.0]) # Elligator cost mul_fp_by_cofactor = (numpy.array([4.0, 2.0, 4.0]) * int(ceil(1.64 * bitlength(self.curve.cofactor))) ) # Cost of computing x([self.curve.cofactor]P) n = len(L) e_prime = [geometric_serie(e[k], L[k]) for k in range(n)] tmp_r, tmp_Ls, tmp_Cs = rounds(e_prime, n) C_e = numpy.array([0.0, 0.0, 0.0]) S_out = [] L_out = [] R_out = [] for j in range(len(tmp_r)): R_out.append([L[k] for k in tmp_Cs[j]]) L_out.append([L[k] for k in tmp_Ls[j]]) bo_C = 1.0 * sum( [self.c_xmul[self.formula.L.index(L[k])] for k in tmp_Cs[j]]) S_tmp, go_C = self.dynamic_programming_algorithm( [L[k] for k in tmp_Ls[j]], len(tmp_Ls[j])) S_out.append(S_tmp) C_e = (C_e + (go_C + bo_C + elligator_cost + 1.0 * mul_fp_by_cofactor) * tmp_r[j]) return C_e, L_out, R_out, S_out, tmp_r
def csidh_precompute_strategy(ctx): """ Precomputation of optimal strategies """ algo = ctx.meta['sibc.kwargs']['algo'] setting = ctx.meta['sibc.kwargs'] coeff = algo.curve.coeff p = algo.params.p L = algo.params.L m = algo.params.m n = algo.params.n SQR, ADD = algo.curve.SQR, algo.curve.ADD init_runtime = algo.field.init_runtime validate = algo.curve.issupersingular measure = algo.curve.measure GAE_at_0 = algo.gae.GAE_at_0 GAE_at_A = algo.gae.GAE_at_A strategy_block_cost = algo.gae.strategy_block_cost random_exponents = algo.gae.random_exponents print_exponents = algo.gae.print_exponents assert setting.uninitialized, 'option -u (--uninitialized) is required!' if algo.formula.name != 'tvelu': set_parameters_velu = algo.formula.set_parameters_velu temporal_m = list(set(m)) if len(temporal_m) > 1: # Maximum number of degree-(l_i) isogeny constructions is m_i (different for each l_i) bounds = '-diffbounds' else: # Maximum number of degree-(l_i) isogeny constructions is m (the same for each l_i) bounds = '-samebounds' tuned = {True: '-tuned', False: ''}[setting.tuned] multievaluation = { True: 'scaled', False: 'unscaled' }[setting.multievaluation] # List of Small Odd Primes, L := [l_0, ..., l_{n-1}] m_prime = [geometric_serie(m[k], L[k]) for k in range(n)] r_out, L_out, R_out = rounds(m_prime[::-1], n) for j in range(0, len(r_out), 1): R_out[j] = list([L[::-1][k] for k in R_out[j]]) L_out[j] = list([L[::-1][k] for k in L_out[j]]) file_path = ("data/strategies/" + algo.curve.model + '/csidh/' + 'csidh' + '-' + setting.prime + '-' + setting.style + '-e' + setting.exponent + bounds + '-' + setting.formula + '-' + multievaluation + tuned) file_path = resource_filename('sibc', file_path) print("// Strategies to be computed") C_out, L_out, R_out, S_out, r_out = strategy_block_cost(L[::-1], m[::-1]) f = open(file_path, 'w') for i in range(0, len(r_out)): f.writelines(' '.join([str(tmp) for tmp in S_out[i]]) + '\n') f.close() return attrdict(name='csidh-precompute-strategy', **locals())
def csidh_header(ctx): """ Optimal strategies as C-code headers files """ algo = ctx.meta['sibc.kwargs']['algo'] setting = ctx.meta['sibc.kwargs'] L = algo.params.L n = algo.params.n m = algo.params.m strategy_block_cost = algo.gae.strategy_block_cost basis = numpy.eye(n, dtype=int) measure = algo.curve.measure # ========================================================================== if algo.formula.name != 'tvelu': set_parameters_velu = algo.formula.set_parameters_velu temporal_m = list(set(m)) if len(temporal_m) > 1: # Maximum number of degree-(l_i) isogeny constructions is m_i (different for each l_i) bounds = '-diffbounds' else: # Maximum number of degree-(l_i) isogeny constructions is m (the same for each l_i) bounds = '-samebounds' # List of Small Odd Primes, L := [l_0, ..., l_{n-1}] m_prime = [geometric_serie(m[k], L[k]) for k in range(n)] r_out, L_out, R_out = rounds(m_prime[::-1], n) for j in range(0, len(r_out), 1): R_out[j] = list([L[::-1][k] for k in R_out[j]]) L_out[j] = list([L[::-1][k] for k in L_out[j]]) file_path = ("data/strategies/" + algo.curve.model + '/' + 'csidh/csidh' + '-' + setting.prime + '-' + setting.style + '-e' + setting.exponent + bounds + '-' + setting.formula + '-' + algo.formula.multievaluation_name + algo.formula.tuned_name) file_path = resource_filename('sibc', file_path) f = open(file_path) S_out = [] for i in range(0, len(r_out), 1): tmp = f.readline() tmp = [int(b) for b in tmp.split()] S_out.append(tmp) f.close() if (len(set(m)) == 1) or ((len(set(m)) == 2) and (0 in set(m))): L_out = list([L_out[0]]) R_out = list([R_out[0]]) S_out = list([S_out[0]]) r_out = list([r_out[0]]) # --- k = 3 # Number of rows (format of the list) # --- print("#ifndef _STRATEGIES_H_") print("#define _STRATEGIES_H_\n") print("#include <inttypes.h>\n\n") print( "// This script assumes the C-code implementation has the list of Small Odd Primes (SOPs) stored such that l_0 < l_1 < ... < l_{n-1}" ) print("// Recall, the strategies process from small SOPs to large SOPs.\n") for i in range(len(r_out)): print( "// -----------------------------------------------------------------------------------------------------------------------------------" ) print("// Strategy number %d\n" % (i)) L_string = "static uint32_t L%d[] " % (i) R_string = "static uint32_t W%d[] " % (i) S_string = "static uint32_t S%d[] " % (i) printl( L_string, [L.index(l_i) for l_i in L_out[i]], len(L_out[i]) // k + 1, ) if R_out[i] != []: printl( R_string, [L.index(r_i) for r_i in R_out[i]], len(R_out[i]) // k + 1, ) else: print("static uint32_t W%d[1];" % i) if S_out[i] != []: printl(S_string, S_out[i], len(S_out[i]) // k + 1) else: print("static uint32_t S%d[1];" % i) print("\n") print( "// -----------------------------------------------------------------------------------------------------------------------------------" ) print( "// -----------------------------------------------------------------------------------------------------------------------------------" ) print("#define NUMBER_OF_DIFFERENT_STRATEGIES %d" % len(L_out)) print("") L_string = ( "static uint32_t *L_STRATEGY[NUMBER_OF_DIFFERENT_STRATEGIES] = {\n\t") R_string = ( "static uint32_t *W_STRATEGY[NUMBER_OF_DIFFERENT_STRATEGIES] = {\n\t") S_string = "static uint32_t *S[NUMBER_OF_DIFFERENT_STRATEGIES] = {\n\t" tmp_sizes = "static uint32_t NUMBER_OF_PRIMES[] = {\n\t" tmp_round = "static uint8_t ROUNDS[] = {\n\t" for i in range(len(L_out) - 1): L_string = L_string + "L%d, " % (i) R_string = R_string + "W%d, " % (i) S_string = S_string + "S%d, " % (i) tmp_sizes = tmp_sizes + "%3d," % (len(L_out[i])) tmp_round = tmp_round + "%3d," % (r_out[i]) L_string = L_string + "L%d\n\t};" % (len(L_out) - 1) R_string = R_string + "W%d\n\t};" % (len(L_out) - 1) S_string = S_string + "S%d\n\t};" % (len(L_out) - 1) tmp_sizes = tmp_sizes + "%3d\n\t};" % (len(L_out[len(L_out) - 1])) tmp_round = tmp_round + "%3d\n\t};" % (r_out[len(L_out) - 1]) print( "// L_STRATEGY[i] determines the small odd primes l_i per each strategy" ) print(L_string) print("\n// W_STRATEGY[i] determines L - L_STRATEGY[i]") print(R_string) print( "\n// S_STRATEGY[i] determines the optimal strategy for L_STRATEGY[i]") print(S_string) print("\n// Number of primes for each strategy") print(tmp_sizes) print("") print("// Number of rounds per each different strategy") print(tmp_round) print("") print("// Maximum number of degree-(l_i) isogeny constructions") printl("static uint8_t M[]", m, n // k + 1) STYLE_NAME = { 'wd2': 'OAYT-style', 'wd1': 'MCR-style', 'df': 'dummy-free-style', }[setting.style] print( "\n#endif /* required framework for the strategies to be used in CSIDH-%s using %s */" % (setting.prime[1:], STYLE_NAME)) # Need empty line at EOF for -Wnewline-eof print("") return attrdict(name='header', **locals())
def plot_strategy(ctx): """ draw strategy graphs as a subgraph Discrete Right Triangle (DRT) """ algo = ctx.meta['sibc.kwargs']['algo'] setting = ctx.meta['sibc.kwargs'] if setting.algorithm == 'csidh': L = algo.params.L m = algo.params.m n = algo.params.n temporal_m = list(set(m)) if len(temporal_m) > 1: # Maximum number of degree-(l_i) isogeny constructions is m_i (different for each l_i) bounds = '-diffbounds' else: # Maximum number of degree-(l_i) isogeny constructions is m (the same for each l_i) bounds = '-samebounds' # List of Small Odd Primes, L := [l_0, ..., l_{n-1}] m_prime = [geometric_serie(m[k], L[k]) for k in range(n)] r_out, L_out, R_out = rounds(m_prime[::-1], n) for j in range(0, len(r_out), 1): R_out[j] = list([L[::-1][k] for k in R_out[j]]) L_out[j] = list([L[::-1][k] for k in L_out[j]]) file_path = ("data/strategies/" + algo.curve.model + '/' + 'csidh' + '-' + setting.prime + '-' + setting.style + '-e' + setting.exponent + bounds + '-' + setting.formula + '-' + algo.formula.multievaluation_name + algo.formula.tuned_name) file_path = resource_filename('sibc', file_path) f = open(file_path) S_out = [] for i in range(0, len(r_out), 1): tmp = f.readline() tmp = [int(b) for b in tmp.split()] S_out.append(tmp) f.close() file_path = ('csidh' + '-' + setting.prime + '-' + setting.style + '-e' + setting.exponent + bounds + '-' + setting.formula + '-' + algo.formula.multievaluation_name + algo.formula.tuned_name + '-' + algo.curve.model) elif setting.algorithm == 'bsidh': file_path = ("data/strategies/" + algo.curve.model + '/' + 'bsidh' + '-' + setting.prime + '-' + setting.formula + '-' + algo.formula.multievaluation_name + algo.formula.tuned_name) file_path = resource_filename('sibc', file_path) f = open(file_path) S_out = [] # Corresponding to the list of Small Isogeny Degree, Lp := [l_0, ..., # l_{n-1}] [We need to include case l=2 and l=4] tmp = f.readline() tmp = [int(b) for b in tmp.split()] S_out.append(list(tmp)) # Corresponding to the list of Small Isogeny Degree, Lm := [l_0, ..., # l_{n-1}] tmp = f.readline() tmp = [int(b) for b in tmp.split()] S_out.append(list(tmp)) f.close() file_path = ('bsidh' + '-' + setting.prime + '-' + setting.style + '-' + setting.formula + '-' + algo.formula.multievaluation_name + algo.formula.tuned_name + '-' + algo.curve.model) else: print("only csidh and bsidh are implemented") click.Exit(1) # ---- for idx in range(0, len(S_out), 1): S = S_out[idx] n = len(S) + 1 # Strategy written as a graph vertexes, vertex_colors, edges, edge_colors = strategy_evaluation(S, n) # Simba method written as a graph # vertexes, vertex_colors, edges, edge_colors = simba(n, 3) # All the Discrete Right Triangle # vertexes, vertex_colors, edges, edge_colors = DRT(n) G = nx.Graph() # Adding nodes in specific positions G.add_nodes_from(list(range(len(vertexes)))) nx.set_node_attributes(G, vertexes, 'pos') # Adding edges with specific colors for i in range(len(edges)): G.add_edge(edges[i][0], edges[i][1], color=edge_colors[i]) # Setting variables for a pretty plot of the graph edges = G.edges() edge_colors = [G[u][v]['color'] for u, v in edges] weights = [6 for u, v in edges] vertex_sizes = [24] * len(vertexes) # Finally, the graph will be plotted plt.figure(1, figsize=(17, 17)) nx.draw( G, vertexes, node_color=['black'] * len(vertexes), node_size=vertex_sizes, edge_color=edge_colors, width=weights, edge_labels=True, ) # Saving the graph as a .PNG figure file_name = file_path + '-id' + str(idx) + '.png' plt.savefig(file_name) print("saving graph: " + file_name) # plt.show() plt.close() print( "// The strategies have been plotted and stored in the current directory" ) def DRT(n): vertexes = dict() # list of the position of each node vertex_colors = ( [] ) # color of each node: red for the leaves, otherwise color is set to white acc = 0 # Different shape of the isogeny graph for i in range(n): for j in range(n - 1 - i): vertex_colors.append('black') vertexes[acc] = (i, -j) acc += 1 return vertexes, vertex_colors, [], [] return attrdict(name='plot-strategy', **locals())