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_ijk(ctx): """ Velusqrt parameters 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 sI_list = algo.formula.sI_list sJ_list = algo.formula.sJ_list # --- k = 3 # Number of rows (format of the list) # --- print("#ifndef _IJK_%s_H_" % setting.prime) print("#define _IJK_%s_H_" % setting.prime) print("") assert n == len(L) print("#ifdef _MONT_C_CODE_") print("// The list of the bitlength of each SOP") printl("static uint64_t bL[]", [bitlength(l) for l in L], n // k + 1) print("#endif") print("") print("#ifdef _ISOG_H_") print( "\n// The list of Small Odd Primes (SOPs) is stored such that l_0 < l_1 < ... < l_{n-1}" ) printl("static uint64_t L[]", L, n // k + 1) assert n == len(sI_list) assert n == len(sJ_list) sK_list = [] for i in range(0, n, 1): assert sJ_list[i] <= sI_list[i] sK_list.append(((L[i] - 2 - 4 * sJ_list[i] * sI_list[i] - 1) // 2) + 1) assert sK_list[i] >= 0 print("") print("#ifndef _C_CODE_") print( "// Sizes for the sets I, J, and K required in the new velusqrt formulae" ) printl("static int sizeI[]", sI_list, n // k + 1) printl("static int sizeJ[]", sJ_list, n // k + 1) printl("static int sizeK[]", sK_list, n // k + 1) print("#endif") print("") print("#define sI_max %d" % (max(sI_list))) print("#define sJ_max %d" % (max(sJ_list))) print("#define sK_max %d" % (L[n - 1] // 2 + 1)) print("#endif") print( "\n#endif /* required framework for the #I, #J, and #K, which is used in new velusqrt fomurlae on CSIDH-%s */" % setting.prime[1:]) return attrdict(name='ijk', **locals())
def __pow__(self, e): """ Exponentiation ... Parameters ---------- - self, which is an element of a Prime Field - an integer e Returns ------- - self raised to e ----- Usage: - self.pow(e) - self ** e Notes ----- - This is a constant-time implementation by using the left-to-right method - It allows negative exponents, but any exponent is expected to belong to |[ 0 .. p - 1 ]| """ if e == 0: return FiniteField(1) elif e < 0: return self.inverse()**(-e) else: self.field.fpsqr += (bitlength(e) - 1) self.field.fpmul += (hamming_weight(e) - 1) return FiniteField(pow(self.x, e, self.field.p))
def __pow__(self, e): """ Exponentiation ... Parameters ---------- - self, which is an element of a Prime Field - an integer e Returns ------- - self raised to e ----- Usage: - self.pow(e) - self ** e Notes ----- - This is a constant-time implementation by using the left-to-right method - It allows negative exponents, but any exponent is expected to belong to |[ 0 .. p - 1 ]| """ if e == 0: return FiniteField(1) elif e < 0: return self.inverse()**(-e) elif e == 2: self.field.fp2sqr += 1 # --- additions z0 = (self.re + self.re) z1 = (self.re + self.im) z2 = (self.re - self.im) # --- multiplications b_re = (z1 * z2) b_im = (z0 * self.im) return FiniteField([b_re, b_im]) else: bits_of_e = bitlength(e) bits_of_e -= 1 tmp_a = FiniteField(self) # left-to-right method for computing a^e for j in range(1, bits_of_e + 1): tmp_a = (tmp_a**2) if ((e >> (bits_of_e - j)) & 1) != 0: tmp_a = (tmp_a * self) return tmp_a