def symbolic_sis(n, alpha, q, m=None, epsilon=None): if epsilon is None: epsilon = var("epsilon") assume(epsilon>0) assume(epsilon<ZZ(1)/2) delta_0 = var("delta_0") assume(delta_0>=1.0) e = alpha*q/sqrt(2*pi) if m is None: m = sqrt(n*log(q)/log(delta_0)) v = e * delta_0**m * q**(n/m) # norm of the vector # epsilon = exp(-pi*(|v|^2/q^2)) f = log(1/epsilon)/pi == (v/q)**2 # solve f = 2* q**2 * m * f * pi f = f.simplify_full() f = f.solve(delta_0**(2*m))[0] f = f.log().canonicalize_radical() f = f.solve(log(delta_0))[0] f = f.simplify_log() return f
def number_of_coefficients_needed(Q, kappa_fe, lambda_fe, max_t): # TODO: This doesn't work. Trouble when computing t0 # We completely mimic what lcalc does when it decides whether # to print a warning. DIGITS = 14 # These are names of lcalc parameters, and we are DIGITS2 = 2 # mimicking them. logger.debug("Start NOC") theta = sum(kappa_fe) c = DIGITS2 * log(10.0) a = len(kappa_fe) c1 = 0.0 for j in range(a): logger.debug("In loop NOC") t0 = kappa_fe[j] * max_t + complex(lambda_fe[j]).imag() logger.debug("In loop 2 NOC") if abs(t0) < 2 * c / (math.pi * a): logger.debug("In loop 3_1 NOC") c1 += kappa_fe[j] * pi / 2.0 else: c1 += kappa_fe[j] * abs(c / (t0 * a)) logger.debug("In loop 3_2 NOC") return int(round(Q * exp(log(2.3 * DIGITS * theta / c1) * theta) + 10))
def symbolic_modulus_switching(n, alpha, q, h, m=None, epsilon=None): if epsilon is None: epsilon = var("epsilon") assume(epsilon>0) assume(epsilon<ZZ(1)/2) delta_0 = var("delta_0") assume(delta_0>=1.0) if m is None: m = sqrt(n*log(q)/log(delta_0)) e = alpha*q/sqrt(2*pi) c = e * sqrt(m-n)/sqrt(h) v = delta_0**m * (q/c)**(n/m) # norm of the vector v_ = v**2/m # variance of each component v_r = (m-n) * e**2 *v_ # noise contribution v_l = h * v_ * c**2 # nose contribution of rounding noise # epsilon = exp(-pi*(|v|^2/q^2)) f = log(1/epsilon)/pi == (v_l + v_r)/q**2 # solve f = 2* q**2 * m * f * pi f = f.simplify_full() f = f.solve(delta_0**(2*m))[0] f = f.log().canonicalize_radical() f = f.solve(log(delta_0))[0] f = f.simplify_log() return f
def get_type_2_bound(K): """The bound in the proof of Theorem 6.4 of Larson/Vaintrob, souped up with Theorem 5.1 of Bach and Sorenson.""" # The Bach and Sorenson parameters A = 4 B = 2.5 C = 5 n_K = K.degree() delta_K = K.discriminant().abs() D = 2 * A * n_K E = 4 * A * log(delta_K) + 2 * A * n_K * log(12) + 4 * B * n_K + C + 1 f = x - (D * log(x) + E)**4 try: bound = find_root(f, 10, GENERIC_UPPER_BOUND) return ceil(bound) except RuntimeError: warning_msg = ("Type 2 bound for quadratic field with " "discriminant {} failed. Returning generic upper bound" ).format(delta_K) logger.warning(warning_msg) return GENERIC_UPPER_BOUND
def symbolic_sis(n, alpha, q, m=None, epsilon=None): if epsilon is None: epsilon = var("epsilon") assume(epsilon > 0) assume(epsilon < ZZ(1) / 2) delta_0 = var("delta_0") assume(delta_0 >= 1.0) e = alpha * q / sqrt(2 * pi) if m is None: m = sqrt(n * log(q) / log(delta_0)) v = e * delta_0**m * q**(n / m) # norm of the vector # epsilon = exp(-pi*(|v|^2/q^2)) f = log(1 / epsilon) / pi == (v / q)**2 # solve f = 2 * q**2 * m * f * pi f = f.simplify_full() f = f.solve(delta_0**(2 * m))[0] f = f.log().canonicalize_radical() f = f.solve(log(delta_0))[0] f = f.simplify_log() return f
def test_manifoldhp(M): qd_equiv, snap_high = 209, 2048 M_hp = M.high_precision() M_snap_low = M.copy() M_snap_high = M.copy() shapes_qd = vector(M_hp.tetrahedra_shapes('rect')) log_shapes_qd = vector(M_hp.tetrahedra_shapes('log')) shapes_snap_low = vector(polished_tetrahedra_shapes(M_snap_low, bits_prec=qd_equiv)) shapes_snap_low = shapes_snap_low.change_ring(CC) log_shapes_snap_low = vector([log(s) for s in polished_tetrahedra_shapes(M_snap_low, bits_prec=qd_equiv)]) shapes_snap_high = vector(polished_tetrahedra_shapes(M_snap_high, bits_prec=snap_high)) log_shapes_snap_high = vector([log(s) for s in polished_tetrahedra_shapes(M_snap_high, bits_prec=snap_high)]) print(" ManifoldHP shape errors:" , log_infinity_norm(shapes_qd - shapes_snap_high)) print(" ManifoldHP log shape errors:" , log_infinity_norm(log_shapes_qd - log_shapes_snap_high)) print(" Snap @ 212 bits shape errors:", log_infinity_norm(shapes_snap_low - shapes_snap_high)) print(" Snap @ 212 bits log_shape errors:", log_infinity_norm(log_shapes_snap_low - log_shapes_snap_high)) fgargs = [False, False, False] G_qd = to_matrix_gens(M_hp.fundamental_group(*fgargs)) G_snap_low = to_matrix_gens(polished_holonomy(M_snap_low, bits_prec=qd_equiv, fundamental_group_args=fgargs)) G_snap_high = to_matrix_gens(polished_holonomy(M_snap_high, bits_prec=snap_high, fundamental_group_args=fgargs)) print(" ManifoldHP matrix errors:", compare_matrices(G_qd, G_snap_high)) print(" Snap @ 212 bits matrix errors:", compare_matrices(G_snap_low, G_snap_high))
def symbolic_modulus_switching(n, alpha, q, h, m=None, epsilon=None): if epsilon is None: epsilon = var("epsilon") assume(epsilon > 0) assume(epsilon < ZZ(1) / 2) delta_0 = var("delta_0") assume(delta_0 >= 1.0) if m is None: m = sqrt(n * log(q) / log(delta_0)) e = alpha * q / sqrt(2 * pi) c = e * sqrt(m - n) / sqrt(h) v = delta_0**m * (q / c)**(n / m) # norm of the vector v_ = v**2 / m # variance of each component v_r = (m - n) * e**2 * v_ # noise contribution v_l = h * v_ * c**2 # nose contribution of rounding noise # epsilon = exp(-pi*(|v|^2/q^2)) f = log(1 / epsilon) / pi == (v_l + v_r) / q**2 # solve f = 2 * q**2 * m * f * pi f = f.simplify_full() f = f.solve(delta_0**(2 * m))[0] f = f.log().canonicalize_radical() f = f.solve(log(delta_0))[0] f = f.simplify_log() return f
def instances(GD, N, MD, p): """ The formula from "Optimizing the oracle under a depth limit". Assuming single-target, t = 1. :params GD: Grover's oracle depth :params N: keyspace size :params MD: MAXDEPTH :params p: target success probability Assuming p = 1 In depth MD can fit j = floor(MD/GD) iterations. These give probability 1 for a search space of size M. p(j) = sin((2j+1)theta)**2 1 = sin((2j+1)theta)**2 1 = sin((2j+1)theta) (2j+1)theta = pi/2 theta = pi/(2(2j+1)) = sqrt(t/M) = 1/sqrt(M). sqrt(M) = 2(2j+1)/pi M = (2(2j+1)/pi)**2 Hence need S = ceil(N/M) machines. S = ceil(N/(2(2*floor(MD/GD)+1)/pi)**2) Else Could either lower each individual computer's success prob, since the target is inside only one computer's state. Then given a requested p, we have p = sin((2j+1)theta)**2 arcsine(sqrt(p)) = (2j+1)theta = (2j+1)/sqrt(M) M = (2j+1)**2/arcsine(sqrt(p))**2 S = ceil(N*(arcsine(sqrt(p))/(2j+1))**2) Or could just run full depth but have less machines. For a target p, one would choose to have ceil(p*S) machines, where S is chosen as in the p = 1 case. Then look at which of both strategies gives lower cost. """ # compute the p=1 case first S1 = ceil(N / (2 * (2 * floor(MD / GD) + 1) / pi)**2) # An alternative reasoning giving the same result for p == 1 (up to a very small difference): # Inner parallelisation gives sqrt(S) speedup without loosing success prob. # Set ceil(sqrt(N) * pi/4) * GD/sqrt(S) = MAXDEPTH # S1 = float(ceil(((pi*sqrt(N)/4) * GD / MD)**2)) if p == 1: return S1 else: Sp = ceil(N * (arcsin(sqrt(R(p))) / (2 * floor(MD / GD) + 1))**2) if ceil(p * S1) == Sp: print( "NOTE: for (GD, log2(N), log2(MD), p) == (%d, %.2f, %.2f, %.2f) naive reduction of parallel machines is not worse!" % (GD, log(N, 2).n(), log(MD, 2).n(), p)) elif ceil(p * S1) < Sp: print( "NOTE: for (GD, log2(N), log2(MD), p) == (%d, %.2f, %.2f, %.2f) naive reduction of parallel machines is better!" % (GD, log(N, 2).n(), log(MD, 2).n(), p)) res = min(Sp, ceil(p * S1)) return res
def realball_to_mid_rad_str(elt, extra_digits=9, max_rad=2**-103): # conversion back and forth from binary to decimal may incur various losses # 9 extra digits seems to make the trick if elt.mid() != 0: digits = ceil(log(elt.mid().abs()/(2*elt.rad()))/log(10)) + extra_digits mid = elt.mid().str(digits=digits) else: mid = '0' rad = elt.rad().str() assert elt in elt.parent()(mid, float(rad)) return mid, rad
def compare_formulas_2(D, k): d1 = old_div(RR(abs(D)), RR(6)) if D < 0: D = -D s1 = RR( sqrt(abs(D)) * sum([ log(d) for d in divisors(D) if is_fundamental_discriminant(-d) and kronecker(-d, old_div(D, d)) == 1 ])) d2 = RR((old_div(2, (sqrt(3) * pi))) * s1) return d1 - d2, d2, RR(2 * sqrt(D) * log(D) / pi)
def estimate(nlen=256, m=85, klen=254, skip=None): """ Estimate the cost of solving HNP for an ECDSA with biased nonces instance. :param nlen: :param m: :param klen: :param compute: :returns: :rtype: EXAMPLES:: sage: estimate(256, m=85, klen=254) sage: estimate(160, m=85, klen=158) """ from usvp import solvers if skip is None: skip = [] ecdsa = ECDSA(nbits=nlen) klen_list = make_klen_list(klen, m) gh = ECDSASolver.ghf(m, ecdsa.n, klen_list, prec=nlen // 2) vol = ECDSASolver.volf(m, ecdsa.n, klen_list, prec=nlen // 2) target_norm = ECDSASolver.evf(m, max(klen_list), prec=nlen // 2) print( ("% {t:s} {h:s}, nlen: {nlen:3d}, m: {m:2d}, klen: {klen:.3f}").format( t=str(datetime.datetime.now()), h=socket.gethostname(), nlen=nlen, m=m, klen=float(mean(klen_list)) ) ) print(" E[|b[0]|]: 2^{v:.2f}".format(v=float(RR(log(gh, 2))))) print(" E[|v|]: 2^{v:.2f}".format(v=float(RR(log(target_norm, 2))))) print(" E[v]/E[b[0]]: %.4f" % float(target_norm / gh)) print("") for solver in solvers: if solver in skip: continue cost, params = solvers[solver].estimate((2 * log(vol), m + 1), target_norm ** 2) if cost is None: print(" {solver:20s} not applicable".format(solver=solver)) continue else: print( " {solver:20s} cost: 2^{c:.1f} cycles ≈ {t:12.4f}h, aux data: {params}".format( solver=solver, c=float(log(cost, 2)), t=cost / (2.0 * 10.0 ** 9 * 3600.0), params=params ) )
def run_instance(L, block_size, tours, evec): from fpylll import BKZ, LLL, GSO, IntegerMatrix from fpylll.algorithms.bkz2 import BKZReduction as BKZ2 from sage.all import e A = IntegerMatrix.from_matrix(L) block_size = ZZ(block_size) par = BKZ.Param(block_size=block_size, strategies=BKZ.DEFAULT_STRATEGY, flags=BKZ.VERBOSE) block_size = ZZ(block_size) delta_0 = (block_size / (2 * pi * e) * (pi * block_size)**(1 / block_size))**(1 / (2 * block_size - 1)) n = ZZ(L.nrows()) alpha = delta_0**(-2 * n / (n - 1)) if len(evec) == n - 1: evec = vector(list(evec) + [1]) LLL.reduction(A) M = GSO.Mat(A) M.update_gso() vol = sqrt(prod([RR(M.get_r(i, i)) for i in range(n)])) norms = [ map(lambda x: RR(log(x, 2)), [(alpha**i * delta_0**n * vol**(1 / n))**2 for i in range(n)]) ] def proj(v, i): return v - vector(RR, M.to_canonical(list(M.from_canonical(v, 0, i)))) # norms += [map(lambda x: RR(log(x,2)), # [(stddev*sqrt(n-i))**2 for i in range(n)])] norms += [ map(lambda x: RR(log(x, 2)), [proj(evec, i).norm()**2 for i in range(1, n - 1)]) ] norms += [[log(RR(M.get_r(i, i)), 2) for i in range(n)]] bkz = BKZ2(M) for i in range(tours): bkz.tour(par) norms += [[log(M.get_r(i, i), 2) for i in range(n)]] return A.to_matrix(matrix(ZZ, n, n)), norms
def helib_find_q(n, target_cost, helib_offset=log(2.33 * 10**9, 2), q=None, step_size=2, sigma=8.0): if q is None: q = n**2 while True: cost = sis(n, sigma / q, q, optimisation_target="lp") if log(cost["lp"], 2.) - helib_offset < target_cost: return q / step_size else: q *= step_size
def compute_kernel(args): if args.seed is not None: set_random_seed(args.seed) FPLLL.set_random_seed(args.seed) ecdsa = ECDSA(nbits=args.nlen) lines, k_list, _ = ecdsa.sample(m=args.m, klen_list=args.klen_list, seed=args.seed, errors=args.e) w_list = [2 ** (klen - 1) for klen in args.klen_list] f_list = [Integer(max(w_list) / wi) for wi in w_list] targetvector = vector([(k - w) * f for k, w, f in zip(k_list, w_list, f_list)] + [max(w_list)]) try: solver = ECDSASolver(ecdsa, lines, m=args.m, d=args.d, threads=args.threads) except KeyError: raise ValueError("Algorithm {alg} unknown".format(alg=args.alg)) expected_length = solver.evf(args.m, max(args.klen_list), prec=args.nlen // 2) gh = solver.ghf(args.m, ecdsa.n, args.klen_list, prec=args.nlen // 2) params = args.params if args.params else {} key, res = solver(solver=args.algorithm, flavor=args.flavor, **params) RR = RealField(args.nlen // 2) logging.info( ( "try: {i:3d}, tag: 0x{tag:016x}, success: {success:1d}, " "|v|: 2^{v:.2f}, |b[0]|: 2^{b0:.2f}, " "|v|/|b[0]|: {b0r:.3f}, " "E|v|/|b[0]|: {eb0r:.3f}, " "|v|/E|b[0]|: {b0er:.3f}, " "cpu: {cpu:10.1f}s, " "wall: {wall:10.1f}s, " "work: {total:d}" ).format( i=args.i, tag=args.tag, success=int(res.success), v=float(log(RR(targetvector.norm()), 2)), b0=float(log(RR(res.b0), 2)), b0r=float(RR(targetvector.norm()) / RR(res.b0)), eb0r=float(RR(expected_length) / RR(res.b0)), b0er=float(RR(targetvector.norm()) / gh), cpu=float(res.cputime), wall=float(res.walltime), total=res.ntests, ) ) return key, res, float(targetvector.norm())
def volf(cls, m, p, klen_list, prec=53): """ Lattice volume. :param m: number of samples :param p: ECDSA modulus :param klen_list: list of lengths of key to recover :param prec: precision to use """ w = 2 ** (max(klen_list) - 1) RR = RealField(prec) f_list = [Integer(w / (2 ** (klen - 1))) for klen in klen_list] return RR(exp(log(p) * (m - 1) + sum(map(log, f_list)) + log(w)))
def fit_to_power_of_log(v): """ INPUT: - v -- a list of (x,y) values, with x increasing. OUTPUT: - number a such that data is "approximated" by b*log(x)^a. """ # ALGORITHM: transform data to (log(log(x)), log(y)) and find the slope # of the best line that fits this transformed data. # This is the right thing to do, since if y = log(x)^a, then log(y) = a*log(log(x)). from math import log, exp w = [(log(log(x)), log(y)) for x, y in v] a, b = least_squares_fit(w) return float(a), exp(float(b))
def delta_rank(f): """Returns the Gamma-rank of the function with LUT f. The Gamma-rank is the rank of the 2^{2n} \times 2^{2n} binary matrix M defined by M[x][y] = 1 if and only if x + y \in \Delta, where \Delta is defined as \Delta = \{ (a, b), DDT_f[a][b] == 2 \} ~. """ n = int(log(len(f), 2)) dim = 2**(2 * n) d = ddt(f) gamma = [(a << n) | b for a, b in itertools.product(xrange(1, 2**n), xrange(0, 2**n)) if d[a][b] == 2] mat_content = [] for x in xrange(0, dim): row = [0 for j in xrange(0, dim)] for y in gamma: row[oplus(x, y)] = 1 mat_content.append(row) mat_gf2 = Matrix(GF(2), dim, dim, mat_content) return mat_gf2.rank()
def central_char_function(self): dim = self.dimension() dfactor = (-1)**dim # doubling insures integers below # we could test for when we need it, but then we carry the "if" # throughout charf = 2*self.character_field() localfactors = self.local_factors_table() bad = [0 if dim+1>len(z) else 1 for z in localfactors] localfactors = [self.from_conjugacy_class_index_to_polynomial(j+1) for j in range(len(localfactors))] localfactors = [z.leading_coefficient()*dfactor for z in localfactors] # Now take logs to figure out what power these are mypi = RealField(100)(pi) localfactors = [charf*log(z)/(2*I*mypi) for z in localfactors] localfactorsa = [z.real().round() % charf for z in localfactors] # Test to see if we are ok? localfactorsa = [localfactorsa[j] if bad[j]>0 else -1 for j in range(len(localfactorsa))] def myfunc(inp, n): fn = list(factor(inp)) pvals = [[localfactorsa[self.any_prime_to_cc_index(z[0])-1], z[1]] for z in fn] # -1 is the marker that the prime divides the conductor for j in range(len(pvals)): if pvals[j][0] < 0: return -1 pvals = sum([z[0]*z[1] for z in pvals]) return (pvals % n) return myfunc
def ea_classes_in_the_ccz_class_of(f, include_start=False): """Returns an iterable that, when iterated over, will yield at least one function from each of the EA-classes constituting the CCZ-class of `f`. Note that several functions in the same EA-class may be returned. Solving this problem is in fact an open *research* problem. If `include_start` is set to False then the ea class of f is hopefully not returned. More precisely, the spaces with thickness 0 are not considered. """ N = int(log(len(f), 2)) mask = sum(int(1 << i) for i in xrange(0, N)) graph_f = [(x << N) | f[x] for x in xrange(0, 2**N)] z = lat_zeroes(f) for b in vector_spaces_bases_iterator(z, N, 2 * N): if include_start or thickness(b, 2 * N) > 0: L_map = FastLinearMapping( get_generating_matrix(b, 2 * N).transpose()) graph_g = [L_map(word) for word in graph_f] g = [-1 for x in xrange(0, 2**N)] for word in graph_g: x, y = word >> N, word & mask g[x] = y if -1 in g: raise Exception("CCZ map is ill defined!") else: yield g
def enumerate_ea_classes(f): """Returns a list containing at least one function from each of the EA-classes constituting the CCZ-class of `f`. Note that several functions in the same EA-class may be returned. Solving this problem is in fact an open *research* problem. """ N = int(log(len(f), 2)) mask = sum(int(1 << i) for i in xrange(0, N)) graph_f = [(x << N) | f[x] for x in xrange(0, 2**N)] bases = get_lat_zeroes_spaces(f) result = [] for b in bases: L_map = FastLinearMapping(get_generating_matrix(b, 2 * N).transpose()) graph_g = [L_map(word) for word in graph_f] g = [-1 for x in xrange(0, 2**N)] for word in graph_g: x, y = word >> N, word & mask g[x] = y if -1 in g: raise Exception("permutation ill defined!") else: result.append(g) return result
def dirichlet_series_coeffs(self, prec, eps=1e-10): """ Return the coefficients of the Dirichlet series representation of self, up to the given precision. INPUT: - prec -- positive integer - eps -- None or a positive real; any coefficient with absolute value less than eps is set to 0. """ # Use multiplicativity to compute the Dirichlet series # coefficients, then make a DirichletSeries object. zero = RDF(0) coeffs = [RDF(0),RDF(1)] + [None]*(prec-2) from sage.all import log, floor # TODO: slow # prime-power indexed coefficients for p in prime_range(2, prec): B = floor(log(prec, p)) + 1 series = self._local_series(p, B) p_pow = p for i in range(1, B): coeffs[p_pow] = series[i] if (eps is None or abs(series[i])>eps) else zero p_pow *= p # non-prime-powers from sage.all import factor for n in range(2, prec): if coeffs[n] is None: a = prod(coeffs[p**e] for p, e in factor(n)) coeffs[n] = a if (eps is None or abs(a) > eps) else zero return coeffs
def central_char_function(self): dim = self.dimension() dfactor = (-1) ** dim # doubling insures integers below # we could test for when we need it, but then we carry the "if" # throughout charf = 2 * self.character_field() localfactors = self.local_factors_table() bad = [0 if dim + 1 > len(z) else 1 for z in localfactors] localfactors = [self.from_conjugacy_class_index_to_polynomial(j + 1) for j in range(len(localfactors))] localfactors = [z.leading_coefficient() * dfactor for z in localfactors] # Now take logs to figure out what power these are mypi = RealField(100)(pi) localfactors = [charf * log(z) / (2 * I * mypi) for z in localfactors] localfactorsa = [z.real().round() % charf for z in localfactors] # Test to see if we are ok? localfactorsa = [localfactorsa[j] if bad[j] > 0 else -1 for j in range(len(localfactorsa))] def myfunc(inp, n): fn = list(factor(inp)) pvals = [[localfactorsa[self.any_prime_to_cc_index(z[0]) - 1], z[1]] for z in fn] # -1 is the marker that the prime divides the conductor for j in range(len(pvals)): if pvals[j][0] < 0: return -1 pvals = sum([z[0] * z[1] for z in pvals]) return pvals % n return myfunc
def dirichlet_series_coeffs(self, prec, eps=1e-10): """ Return the coefficients of the Dirichlet series representation of self, up to the given precision. INPUT: - prec -- positive integer - eps -- None or a positive real; any coefficient with absolute value less than eps is set to 0. """ # Use multiplicativity to compute the Dirichlet series # coefficients, then make a DirichletSeries object. zero = RDF(0) coeffs = [RDF(0), RDF(1)] + [None] * (prec - 2) from sage.all import log, floor # TODO: slow # prime-power indexed coefficients for p in prime_range(2, prec): B = floor(log(prec, p)) + 1 series = self._local_series(p, B) p_pow = p for i in range(1, B): coeffs[p_pow] = series[i] if ( eps is None or abs(series[i]) > eps) else zero p_pow *= p # non-prime-powers from sage.all import factor for n in range(2, prec): if coeffs[n] is None: a = prod(coeffs[p**e] for p, e in factor(n)) coeffs[n] = a if (eps is None or abs(a) > eps) else zero return coeffs
def tu_decomposition(s, v, verbose=False): """Using the knowledge that v is a subspace of Z_s of dimension n, a TU-decomposition (as defined in [Perrin17]) of s is performed and T and U are returned. """ N = int(log(len(s), 2)) # building B basis = extract_basis(v[0], N) t = len(basis) basis = complete_basis(basis, N) B = Matrix(GF(2), N, N, [tobin(x, N) for x in reversed(basis)]) if verbose: print "B= (rank={})\n{}".format(B.rank(), B.str()) # building A basis = complete_basis(extract_basis(v[1], N), N) A = Matrix(GF(2), N, N, [tobin(x, N) for x in reversed(basis)]) if verbose: print "A= (rank={})\n{}".format(A.rank(), A.str()) # building linear equivalent s_prime s_prime = [ apply_bin_mat(s[apply_bin_mat(x, A.inverse())], B) for x in xrange(0, 2**N) ] # TU decomposition of s' T, U = get_tu_open(s_prime, t) if verbose: print "T=[" for i in xrange(0, 2**(N - t)): print " {} {}".format(T[i], is_permutation(T[i])) print "]\nU=[" for i in xrange(0, 2**t): print " {} {}".format(U[i], is_permutation(U[i])) print "]" return T, U
def make_seal_table_2(our_q=False, optimisation_target="sieve"): if our_q: params = [(1024, 47.9), (2048, 89.0), (4096, 170.8), (8192, 331.8), (16384, 652.2)] else: params = [(1024, 47.9), (2048, 94.0), (4096, 190.0), (8192, 383.0), (16384, 767.0)] data = OrderedDict() for param in params: n, q = param q = ceil(2**q) alpha = 8.0 / q res = sis(n, alpha, q, optimisation_target=optimisation_target) data[(n, alpha, q, "dual")] = res print "%6.1f &" % log(res[optimisation_target], 2.0), print for param in params: n, q = param q = ceil(2**q) alpha = 8.0 / q res_lll = sis_small_secret_mod_switch( n, alpha, q, secret_bounds=(-1, 1), h=ceil(2 * n / 3), optimisation_target=optimisation_target, use_lll=True) res = sis_small_secret_mod_switch( n, alpha, q, secret_bounds=(-1, 1), h=ceil(2 * n / 3), optimisation_target=optimisation_target, use_lll=False) if res_lll[optimisation_target] < res[optimisation_target]: res = res_lll data[(n, alpha, q, "sparse")] = res print "%6.1f &" % log(res[optimisation_target], 2.0), print return data
def get_lat_zeroes_spaces(s, n_threads=DEFAULT_N_THREADS): """Returns a list containing the basis of each vector space of dimension n contained in the LAT zeroes of `s`. """ return get_lat_zeroes_spaces_fast(s, int(log(len(s), 2)), int(n_threads))
def compare_formulas_2a(D, k): d1 = dimension_new_cusp_forms(kronecker_character(D), k) if D < 0: D = -D d2 = RR(1 / pi * sqrt(D) * sum([ log(d) * sigma(old_div(D, d), 0) for d in divisors(D) if Zmod(d) (old_div(D, d)).is_square() and is_fundamental_discriminant(-d) ])) return d1 - d2
def printS(P, w, d, N, t, Smax, M): step = (Smax-1)//M for i in range(M+1): Si = 1 + step*i p = p_succ_outer_inv(P, Si) it = iterations(p, N, t) c = cost_out_p(p, Si, w, d, N, t) print ("S = %s, p = %.2f, iter = %.2f, cost = %.2f" % (Si, p, it, log(c, 2)))
def get_ccz_equivalent_function_cartesian(s, v, verbose=False): """Takes as input a vector space v of the set of zeroes in the LAT of s, v being the cartesian product of two spaces, and returns a function CCZ equivalent to s obtained using this CCZ space. """ N = int(log(len(s), 2)) T_inv, U = tu_decomposition(s, v, verbose=verbose) t = int(log(len(T_inv[0]), 2)) T = [inverse(row) for row in T_inv] result = [0 for x in xrange(0, 2**N)] for l in xrange(0, 2**t): for r in xrange(0, 2**(N - t)): x = (l << (N - t)) | r y_r = T[r][l] y_l = U[l][r] result[x] = (y_l << t) | y_r return result
def linear_function_lut_to_matrix(l): """Turns the look up table of a linear function into the corresponding binary matrix.""" n = int(log(len(l), 2)) result = [] for i in xrange(0, n): line = [(int(l[1 << (n - 1 - j)]) >> (n - 1 - i)) & 1 for j in xrange(0, n)] result.append(line) return Matrix(GF(2), n, n, result)
def ghf(cls, m, p, klen_list, prec=53): """ Estimate norm of shortest vector according to Gaussian Heuristic. :param m: number of samples :param p: ECDSA modulus :param klen_list: list of lengths of key to recover :param prec: precision to use """ # NOTE: The Gaussian Heuristic does not hold in small dimensions w = 2 ** (max(klen_list) - 1) RR = RealField(prec) w = RR(w) f_list = [Integer(w / (2 ** (klen - 1))) for klen in klen_list] d = m + 1 log_vol = log(p) * (m - 1) + sum(map(log, f_list)) + log(w) lgh = log_gamma(1 + d / 2.0) * (1.0 / d) - log(sqrt(pi)) + log_vol * (1.0 / d) return RR(exp(lgh))
def _number_of_bits(n): """ Description: Returns the number of bits in the binary representation of n Input: n - integer Output: num_bits - number of bits """ if n == 0: return 1 else: return floor(log(n).n() / log(2).n()) + 1
def _number_of_bits(n): """ Description: Returns the number of bits in the binary representation of n Input: n - integer Output: num_bits - number of bits """ if n == 0: return 1 else: return floor(log(n).n()/log(2).n()) + 1
def prop_int_pretty(n): """ This function should be called whenever displaying an integer in the properties table so that we can keep the formatting consistent """ if abs(n) >= 10**12: e = floor(log(abs(n),10)) return r'$%.3f\times 10^{%d}$' % (n/10**e, e) else: return '$%s$' % n
def _inc_weight(Q): ''' Let D be the differential operator ass. to Q. Let f_1, .., f_t be vector valued modular forms of determinant weights k_1, ..., k_t. If the determinant weight of D(f_1, ..., f_t) is equal to k_1 + ... + k_t + k, this function returns k. ''' S = Q.parent() R = S.base_ring() u1, _ = S.gens() rs = R.gens() rdct = {} for r11, r12, _ in group(rs, 3): rdct[r11] = 4 * r11 rdct[r12] = 2 * r12 t = [t for t, v in Q.dict().iteritems() if v != 0][0] a = Q.map_coefficients(lambda f: f.subs(rdct))[t] / Q.subs({u1: 2 * u1})[t] return int(log(a) / log(2))
def DLMV(K): """Compute the DLMV bound""" # First compute David's C_0 Delta_K = K.discriminant().abs() h_K = K.class_number() R_K = K.regulator() r_K = K.unit_group().rank() delta_K = log(2) / (r_K + 1) C_1_K = r_K**(r_K + 1) * delta_K**(-(r_K - 1)) / 2 C_2_K = exp(24 * C_1_K * R_K) CHEB_DEN_BOUND = (4 * log(Delta_K**h_K) + 5 * h_K + 5)**2 C_0 = ((CHEB_DEN_BOUND**(12 * h_K)) * C_2_K + CHEB_DEN_BOUND**(6 * h_K))**4 # Now the Type 1 and 2 bounds type_1_bound = (1 + 3**(12 * h_K))**2 type_2_bound = get_type_2_bound(K) return max(C_0, type_1_bound, type_2_bound)
def run(num_bits,k): """ Description: Runs the Dupont-Enge-Morain method multiple times until a valid curve is found Input: num_bits - number of bits k - an embedding degree Output: (q,t,r,k,D) - an elliptic curve; if no curve is found, the algorithm returns (0,0,0,k,0) """ j,r,q,t = 0,0,0,0 num_generates = 512 h = num_bits/(euler_phi(k)) tried = [(0,0)] # keep track of random values tried for efficiency for i in range(0,num_generates): D = 0 y = 0 while (D,y) in tried: # find a pair that we have not tried D = -randint(1, 1024) # pick a small D so that the CM method is fast D = fundamental_discriminant(D) m = 0.5*(h - log(-D).n()/(2*log(2)).n()) if m < 1: m = 1 y = randint(floor(2**(m-1)), floor(2**m)) tried.append((D,y)) q,t,r,k,D = method(num_bits,k,D,y) # run DEM if q != 0 and t != 0 and r != 0 and k != 0 and D != 0: # found an answer, so output it assert is_valid_curve(q,t,r,k,D), 'Invalid output' return q,t,r,k,D return 0,0,0,k,0 # found nothing
def list_zeros(N=None, t=None, limit=None, fmt=None, download=None): if N is None: N = request.args.get("N", None, int) if t is None: t = request.args.get("t", 0, float) if limit is None: limit = request.args.get("limit", 100, int) if fmt is None: fmt = request.args.get("format", "plain") if download is None: download = request.args.get("download", "no") if limit < 0: limit = 100 if N is not None: # None is < 0!! WHAT THE WHAT! if N < 0: N = 0 if t < 0: t = 0 if limit > 100000: # limit = 100000 # bread = [("L-functions", url_for("l_functions.l_function_top_page")),("Zeros of $\zeta(s)$", url_for(".zetazeros"))] return render_template('single.html', title="Too many zeros", bread=bread, kid = "dq.zeros.zeta.toomany") if N is not None: zeros = zeros_starting_at_N(N, limit) else: zeros = zeros_starting_at_t(t, limit) if fmt == 'plain': response = flask.Response(("%d %s\n" % (n, nstr(z,31+floor(log(z,10))+1,strip_zeros=False,min_fixed=-inf,max_fixed=+inf)) for (n, z) in zeros)) response.headers['content-type'] = 'text/plain' if download == "yes": response.headers['content-disposition'] = 'attachment; filename=zetazeros' else: response = str(list(zeros)) return response
def make_curve(num_bits, num_curves=1): """ Description: Finds num_curves Barreto-Naehrig curves with a prime order that is at least 2^num_bits. Input: num_bits - number of bits for the prime order of the curve num_curves - number of curves to find Output: curves - list of the first num_curves BN curves each of prime order at least 2^num_bits; each curve is represented as a tuple (q,t,r,k,D) """ def P(y): x = Integer(y) return 36*pow(x,4) + 36*pow(x,3) + 24*pow(x,2) + 6*x + 1 x = Integer(floor(pow(2, (num_bits)/4.0)/(sqrt(6)))) q = 0 r = 0 t = 0 curve_num = 0 curves = [] while curve_num < num_curves or (log(q).n()/log(2).n() < 2*num_bits and not (utils.is_suitable_q(q) and utils.is_suitable_r(r) and utils.is_suitable_curve(q,t,r,12,-3,num_bits))): t = Integer(6*pow(x,2) + 1) q = P(-x) r = q + 1 - t b = utils.is_suitable_q(q) and utils.is_suitable_r(r) and utils.is_suitable_curve(q,t,r,12,-3,num_bits) if b: try: assert floor(log(r)/log(2)) + 1 >= num_bits, 'Subgroup not large enough' curves.append((q,t,r,12,-3)) curve_num += 1 except AssertionError as e: pass if curve_num < num_curves or not b: q = P(x) r = q+1-t if (utils.is_suitable_q(q) and utils.is_suitable_r(r) and utils.is_suitable_curve(q,t,r,12,-3,num_bits)): try: assert floor(log(r)/log(2)) + 1 >= num_bits, 'Subgroup not large enough' curves.append((q,t,r,12,-3)) curve_num += 1 except AssertionError as e: pass x += 1 return curves
def _sage_(self): import sage.all as sage return sage.log(self.args[0]._sage_())
def affine_global_height(affine_point, abs_val=lambda x: x.abs()): """The affine logarithmic height function (works only over the rationals?).""" # use .numerical_approx() if we want a float return log(affine_height(affine_point, abs_val))
def dimension(self,k,ignore=False, debug = 0): if k < 2 and not ignore: raise NotImplementedError("k has to >= 2") s = self._signature if not (2*k in ZZ): raise ValueError("k has to be integral or half-integral") if (2*k+s)%2 != 0: return 0 m = self._m n2 = self._n2 if self._v2.has_key(0): v2 = self._v2[0] else: v2 = 1 if self._g != None: if not self._aniso_formula: vals = self._g.values() #else: #print "using aniso_formula" M = self._g else: vals = self._M.values() M = self._M if (2*k+s)%4 == 0: d = Integer(1)/Integer(2)*(m+n2) # |dimension of the Weil representation on even functions| self._d = d self._alpha4 = 1/Integer(2)*(vals[0]+v2) # the codimension of SkL in MkL else: d = Integer(1)/Integer(2)*(m-n2) # |dimension of the Weil representation on odd functions| self._d = d self._alpha4 = 1/Integer(2)*(vals[0]-v2) # the codimension of SkL in MkL prec = ceil(max(log(M.order(),2),52)+1)+17 #print prec RR = RealField(prec) CC = ComplexField(prec) if debug > 0: print "d, m = {0}, {1}".format(d,m) eps = exp( 2 * CC.pi() * CC(0,1) * (s + 2*k) / Integer(4) ) eps = round(real(eps)) if self._alpha3 is None or self._last_eps != eps: self._last_eps = eps if self._aniso_formula: self._alpha4 = 1 self._alpha3 = -sum([BB(a)*mm for a,mm in self._v2.iteritems() if a != 0]) #print self._alpha3 self._alpha3 += Integer(d) - Integer(1) - self._g.beta_formula() #print self._alpha3, self._g.a5prime_formula() self._alpha3 = self._alpha3/RR(2) else: self._alpha3 = eps*sum([(1-a)*mm for a,mm in self._v2.iteritems() if a != 0]) if debug>0: print "alpha3t = ", self._alpha3 self._alpha3 += sum([(1-a)*mm for a,mm in vals.iteritems() if a != 0]) #print self._alpha3 self._alpha3 = self._alpha3 / Integer(2) alpha3 = self._alpha3 alpha4 = self._alpha4 if debug > 0: print alpha3, alpha4 g1=M.char_invariant(1) g1=CC(g1[0]*g1[1]) #print g1 g2=M.char_invariant(2) g2=CC(g2[0]*g2[1]) if debug > 0: print g2, g2.parent() g3=M.char_invariant(-3) g3=CC(g3[0]*g3[1]) if debug > 0: print "eps = {0}".format(eps) if debug > 0: print "d/4 = {0}, m/4 = {1}, e^(2pi i (2k+s)/8) = {2}".format(RR(d) / RR(4), sqrt(RR(m)) / RR(4), CC(exp(2 * CC.pi() * CC(0,1) * (2 * k + s) / Integer(8)))) if eps == 1: g2_2 = real(g2) else: g2_2 = imag(g2)*CC(0,1) alpha1 = RR(d) / RR(4) - sqrt(RR(m)) / RR(4) * CC(exp(2 * CC.pi() * CC(0,1) * (2 * k + s) / Integer(8)) * g2_2) if debug > 0: print alpha1 alpha2 = RR(d) / RR(3) + sqrt(RR(m)) / (3 * sqrt(RR(3))) * real(exp(CC(2 * CC.pi() * CC(0,1) * (4 * k + 3 * s - 10) / 24)) * (g1 + eps*g3)) if debug > 0: print "alpha1 = {0}, alpha2 = {1}, alpha3 = {2}, g1 = {3}, g2 = {4}, g3 = {5}, d = {6}, k = {7}, s = {8}".format(alpha1, alpha2, alpha3, g1, g2, g3, d, k, s) dim = real(d + (d * k / Integer(12)) - alpha1 - alpha2 - alpha3) if debug > 0: print "dimension:", dim if abs(dim-round(dim)) > 1e-6: raise RuntimeError("Error ({0}) too large in dimension formula for {1} and k={2}".format(abs(dim-round(dim)), self._M if self._M is not None else self._g, k)) dimr = dim dim = Integer(round(dim)) if k >=2 and dim < 0: raise RuntimeError("Negative dimension (= {0}, {1})!".format(dim, dimr)) return dim
def dimension(self,k,ignore=False, debug = 0): if k < 2 and not ignore: raise NotImplementedError("k has to >= 2") s = self._signature if not (2*k in ZZ): raise ValueError("k has to be integral or half-integral") if (2*k+s)%4 != 0 and not ignore: raise NotImplementedError("2k has to be congruent to -signature mod 4") if self._v2.has_key(0): v2 = self._v2[0] else: v2 = 1 if self._g != None: if not self._aniso_formula: vals = self._g.values() #else: #print "using aniso_formula" M = self._g else: vals = self._M.values() M = self._M prec = ceil(max(log(M.order(),2),52)+1)+17 #print prec RR = RealField(prec) CC = ComplexField(prec) d = self._d m = self._m if debug > 0: print d,m if self._alpha3 == None: if self._aniso_formula: self._alpha4 = 1 self._alpha3 = -sum([BB(a)*mm for a,mm in self._v2.iteritems() if a != 0]) #print self._alpha3 self._alpha3 += Integer(d) - Integer(1) - self._g.beta_formula() #print self._alpha3, self._g.a5prime_formula() self._alpha3 = self._alpha3/RR(2) else: self._alpha3 = sum([(1-a)*mm for a,mm in self._v2.iteritems() if a != 0]) #print self._alpha3 self._alpha3 += sum([(1-a)*mm for a,mm in vals.iteritems() if a != 0]) #print self._alpha3 self._alpha3 = self._alpha3 / Integer(2) self._alpha4 = 1/Integer(2)*(vals[0]+v2) # the codimension of SkL in MkL alpha3 = self._alpha3 alpha4 = self._alpha4 if debug > 0: print alpha3, alpha4 g1=M.char_invariant(1) g1=CC(g1[0]*g1[1]) #print g1 g2=M.char_invariant(2) g2=RR(real(g2[0]*g2[1])) if debug > 0: print g2, g2.parent() g3=M.char_invariant(-3) g3=CC(g3[0]*g3[1]) if debug > 0: print RR(d) / RR(4), sqrt(RR(m)) / RR(4), CC(exp(2 * CC.pi() * CC(0,1) * (2 * k + s) / Integer(8))) alpha1 = RR(d) / RR(4) - (sqrt(RR(m)) / RR(4) * CC(exp(2 * CC.pi() * CC(0,1) * (2 * k + s) / Integer(8))) * g2) if debug > 0: print alpha1 alpha2 = RR(d) / RR(3) + sqrt(RR(m)) / (3 * sqrt(RR(3))) * real(exp(CC(2 * CC.pi() * CC(0,1) * (4 * k + 3 * s - 10) / 24)) * (g1+g3)) if debug > 0: print alpha1, alpha2, g1, g2, g3, d, k, s dim = real(d + (d * k / Integer(12)) - alpha1 - alpha2 - alpha3) if debug > 0: print "dimension:", dim if abs(dim-round(dim)) > 1e-6: raise RuntimeError("Error ({0}) too large in dimension formula for {1} and k={2}".format(abs(dim-round(dim)), self._M if self._M is not None else self._g, k)) dimr = dim dim = Integer(round(dim)) if k >=2 and dim < 0: raise RuntimeError("Negative dimension (= {0}, {1})!".format(dim, dimr)) return dim
def silke(A, c, beta, h, m=None, scale=1, float_type="double"): """ :param A: LWE matrix :param c: LWE vector :param beta: BKW block size :param m: number of samples to consider :param scale: scale rhs of lattice by this factor """ from fpylll import BKZ, IntegerMatrix, LLL, GSO from fpylll.algorithms.bkz2 import BKZReduction as BKZ2 if m is None: m = A.nrows() L = dual_instance1(A, scale=scale) L = IntegerMatrix.from_matrix(L) L = LLL.reduction(L, flags=LLL.VERBOSE) M = GSO.Mat(L, float_type=float_type) bkz = BKZ2(M) t = 0.0 param = BKZ.Param(block_size=beta, strategies=BKZ.DEFAULT_STRATEGY, auto_abort=True, max_loops=16, flags=BKZ.VERBOSE|BKZ.AUTO_ABORT|BKZ.MAX_LOOPS) bkz(param) t += bkz.stats.total_time H = copy(L) import pickle pickle.dump(L, open("L-%d-%d.sobj"%(L.nrows, beta), "wb")) E = [] Y = set() V = set() y_i = vector(ZZ, tuple(L[0])) Y.add(tuple(y_i)) E.append(apply_short1(y_i, A, c, scale=scale)[1]) v = L[0].norm() v_ = v/sqrt(L.ncols) v_r = 3.2*sqrt(L.ncols - A.ncols())*v_/scale v_l = sqrt(h)*v_ fmt = u"{\"t\": %5.1fs, \"log(sigma)\": %5.1f, \"log(|y|)\": %5.1f, \"log(E[sigma]):\" %5.1f}" print print fmt%(t, log(abs(E[-1]), 2), log(L[0].norm(), 2), log(sqrt(v_r**2 + v_l**2), 2)) print for i in range(m): t = cputime() M = GSO.Mat(L, float_type=float_type) bkz = BKZ2(M) t = cputime() bkz.randomize_block(0, L.nrows, stats=None, density=3) LLL.reduction(L) y_i = vector(ZZ, tuple(L[0])) l_n = L[0].norm() if L[0].norm() > H[0].norm(): L = copy(H) t = cputime(t) Y.add(tuple(y_i)) V.add(y_i.norm()) E.append(apply_short1(y_i, A, c, scale=scale)[1]) if len(V) >= 2: fmt = u"{\"i\": %4d, \"t\": %5.1fs, \"log(|e_i|)\": %5.1f, \"log(|y_i|)\": %5.1f," fmt += u"\"log(sigma)\": (%5.1f,%5.1f), \"log(|y|)\": (%5.1f,%5.1f), |Y|: %5d}" print fmt%(i+2, t, log(abs(E[-1]), 2), log(l_n, 2), log_mean(E), log_var(E), log_mean(V), log_var(V), len(Y)) return E
def log_var(X): return log(variance(X).sqrt(), 2)
def log_mean(X): return log(mean([abs(x) for x in X]), 2)