def svp_time(seed, params, return_queue=None): """Run SVP reduction of AutoBKZ on ``A`` using ``params``. :param A: a matrix :param params: AutoBKZ parameters :param queue: if not ``None``, the result is put on this queue. """ FPLLL.set_random_seed(seed) FPLLL.set_threads(params["threads"]) q = 33554393 k = params.block_size // 2 A = IntegerMatrix.random(params.block_size, "qary", q=q, k=k, int_type="long") M = GSO.Mat(A) bkz = BKZ2(M) tracer = BKZTreeTracer(bkz, start_clocks=True) with tracer.context(("tour", 0)): bkz.svp_reduction(0, params.block_size, params, tracer) bkz.M.update_gso() tracer.exit() log_delta = (log(A[0].norm()) - log(q) * (k / float(params.block_size))) / float(params.block_size) tracer.trace.data["delta"] = exp(log_delta) if return_queue: return_queue.put(tracer.trace) else: return tracer.trace
def main(n=150, block_size=60, float_type="d", logq=40, verbose=False, seed=0xdeadbeef): print "= n: %3d, β: %2d, bits: %3d, float_type: %s, seed: 0x%08x =" % ( n, block_size, logq, float_type, seed) print set_random_seed(seed) A = IntegerMatrix.random(n, "qary", k=n // 2, bits=logq) A = LLL.reduction(A) params = BKZ.Param(block_size=block_size, max_loops=4, strategies=BKZ.DEFAULT_STRATEGY, flags=BKZ.MAX_LOOPS | BKZ.VERBOSE) bkz = BKZReduction(GSO.Mat(copy.copy(A), float_type=float_type)) bkz(params) print bkz.trace bkz2 = BKZ2(GSO.Mat(copy.copy(A), float_type=float_type)) bkz2(params) print bkz2.trace if verbose: print print bkz.trace.report()
def svp_time(seed, params, return_queue=None): """Run SVP reduction on ``A`` using ``params``. :param seed: random seed for matrix creation :param params: BKZ parameters :param return_queue: if not ``None``, the result is put on this queue. """ from cost import sample_matrix A = sample_matrix(params.block_size, seed=seed) M = GSO.Mat(A) bkz = BKZ2(M) tracer = BKZTreeTracer(bkz, start_clocks=True) with tracer.context(("tour", 0)): bkz.svp_reduction(0, params.block_size, params, tracer) bkz.M.update_gso() tracer.exit() tracer.trace.data["|A_0|"] = A[0].norm() ppbs = params.strategies[params.block_size].preprocessing_block_sizes tracer.trace.data["preprocessing_block_size"] = ppbs[0] if ppbs else 2 if return_queue: return_queue.put(tracer.trace) else: return tracer.trace
def update_until_v_found(M, min_block_size, max_block_size, max_tours, v, prime_modulus): L = fpylll.IntegerMatrix.from_matrix(M) G = fpylll.GSO.Mat(L) G.update_gso() Y = BKZ2(G) block_size = min_block_size v = list(np.array(v) % prime_modulus) trial_v = list(np.array(M[0]) % prime_modulus) print('completed block sizes: ', sep=' ', end=' ', flush=True) while block_size <= max_block_size: o = fpylll.BKZ.Param(block_size, strategies='default.json', min_success_probability=0.5, flags=fpylll.BKZ.AUTO_ABORT) #o = fpylll.BKZ.Param(block_size, min_success_probability=0.5, flags = fpylll.BKZ.AUTO_ABORT) # no preprocessing tour = 1 while (tour < max_tours) & (Y.tour(o) == False): tour += 1 Hold_M = [[0 for i in M] for j in M[0]] L.to_matrix(Hold_M) trial_v = list(np.array(Hold_M[0]) % prime_modulus) neg_trial_v = list(-1 * np.array(Hold_M[0]) % prime_modulus) if (trial_v != v) & (neg_trial_v != v): L.to_matrix(M) else: print('....v found at (tour,block size) = ' + str((tour, block_size))) return M, block_size print(str(block_size), sep=' ', end=' ', flush=True) block_size += 1 print('exhausted... secret not found for block size <= ' + str(max_block_size)) return M, 0
def svp_time(seed, params, return_queue=None): """Run SVP reduction of AutoBKZ on ``A`` using ``params``. :param A: a matrix :param params: AutoBKZ parameters :param queue: if not ``None``, the result is put on this queue. """ FPLLL.set_random_seed(seed) A = IntegerMatrix.random(params.block_size, "qary", bits=30, k=params.block_size//2, int_type="long") M = GSO.Mat(A) bkz = BKZ2(M) tracer = BKZTreeTracer(bkz, start_clocks=True) with tracer.context(("tour", 0)): bkz.svp_reduction(0, params.block_size, params, tracer) bkz.M.update_gso() tracer.exit() tracer.trace.data["|A_0|"] = A[0].norm() if return_queue: return_queue.put(tracer.trace) else: return tracer.trace
def insert_in_IntegerMatrix(self, A, v, kappa, block_size): if (list(A[kappa]) == list(v)): return n = A.nrows l = A.ncols AA = IntegerMatrix(n + 1, l, int_type="long") for i in xrange(kappa): for j in xrange(l): AA[i, j] = A[i, j] for j in xrange(l): AA[kappa, j] = v[j] for i in xrange(kappa + 1, n + 1): for j in xrange(l): AA[i, j] = A[i - 1, j] M = GSO.Mat(AA, float_type=TYPE) M.update_gso() bkz = BKZ2(M) try: bkz.lll_obj(kappa, kappa, kappa + block_size + 1) # longer: 1 more row except: pass index = 0 for i in range(kappa, kappa + block_size + 1): if (AA[i].is_zero()): index = i - kappa break for i in xrange(kappa + index): for j in xrange(l): A[i, j] = AA[i, j] for i in xrange(kappa + index + 1, n + 1): for j in xrange(l): A[i - 1, j] = AA[i, j] """ for i in range(n): bad = 0 for j in range(l): if (A[i][j] == 0): bad = bad + 1 if (bad == n): print " inserting ", v print " <<<<<<<<<<<<<<<<<<<<<< WRONG HERE at ", kappa, block_size, i print A print "old A is " print AA_old print "old A after lll is " print AA sys.exit(1) """ del bkz del AA del M return
def __call__(cls, M, predicate, block_size, invalidate_cache=lambda: None, max_loops=8, threads=1, **kwds): bkz = BKZ2(M) if block_size > STRATEGIES_MAX_DIM: warnings.warn( "reducing block size to {max}".format(max=STRATEGIES_MAX_DIM)) block_size = STRATEGIES_MAX_DIM FPLLL.set_threads(threads) params = BKZ.EasyParam(block_size=block_size, **kwds) auto_abort = BKZ.AutoAbort(M, M.d) tracer = BKZTreeTracer(bkz, root_label="bkz_enum", start_clocks=True) found, ntests, solution = False, 0, None for tour in range(max_loops): bkz.tour(params) if auto_abort.test_abort(): break invalidate_cache() with tracer.context("check"): for i, v in enumerate(bkz.M.B): ntests += 1 if predicate(v, standard_basis=True): found = True solution = tuple([int(v_) for v_ in v]) break if found: break FPLLL.set_threads(1) tracer.exit() b0, b0e = bkz.M.get_r_exp(0, 0) return USVPPredSolverResults( success=found, solution=solution, ntests=ntests, b0=b0**(0.5) * 2**(b0e / 2.0), cputime=tracer.trace.data["cputime"], walltime=tracer.trace.data["walltime"], data=tracer.trace, )
def run_BKZ2(A, block_size=2, verbose=False): """ """ flags = BKZ.DEFAULT | BKZ.AUTO_ABORT if verbose: flags |= BKZ.VERBOSE A = IntegerMatrix.from_matrix(A) _ = BKZ2(A)(BKZ.EasyParam(block_size=block_size, flags=flags)) B = [[A[i, j] for j in range(A.ncols)] for i in range(A.nrows)] return B
def main_pruning(filename, bs, cores): try: with open(filename, "rb") as f: mat = pickle.load(f) #print "len(mat)", len(mat) #if (len(mat) > 1): # mat = mat[0] if isinstance(mat, IntegerMatrix): Ainput = mat else: Ainput = IntegerMatrix.from_matrix(mat) except: Ainput = IntegerMatrix.from_file(filename) Ainput_M = GSO.Mat(Ainput, float_type='double') Ainput_M.update_gso() r = [Ainput_M.get_r(i, i) for i in range(0, Ainput.nrows)] L_Ainput_M = LLL.Reduction(Ainput_M) L_Ainput_M() #print r A = IntegerMatrix.from_matrix(L_Ainput_M.M.B, int_type="long") M = GSO.Mat(A, float_type="double") bkzobj = BKZ2(M) bkzobj.M.update_gso() block_size = bs r = [M.get_r(i, i) for i in range(0, block_size)] radius = r[0] * 0.99 preproc_cost = 5000**(rank + 1) pr0 = Pruning.run(radius, NPS[block_size] * preproc_cost, [r], 0.1, metric="probability", float_type="double", flags=Pruning.GRADIENT | Pruning.NELDER_MEAD) print pr0.coefficients """ pruning = prune(radius, NPS[block_size] * preproc_cost, [r], 0.01, metric="probability", float_type="double", flags=Pruning.GRADIENT|Pruning.NELDER_MEAD) cost = sum(pruning.detailed_cost) / NPS[block_size] print "# [rank %d] cost %.1f, precost %.1f " % (rank, cost, preproc_cost) """ pr0_linear = pr0.LinearPruningParams(block_size, block_size - 2) print pr0_linear.coefficients return
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 run_timing_test(n, block_size=60, bits=30, ncores=8, min_success_probability=0.5, max_loops=4): A = IntegerMatrix.random(n, "qary", k=n // 2, bits=bits) default_strategies = load_strategies_json(BKZ.DEFAULT_STRATEGY) param = BKZ.Param(block_size, strategies=default_strategies, min_success_probability=min_success_probability, max_loops=max_loops, flags=BKZ.VERBOSE | BKZ.MAX_LOOPS) random.seed(1) bkz = ParallelBKZ(copy(A), ncores=ncores) t = time.time() bkz(param) t = time.time() - t trace_p = bkz.trace print "Parallel(%d): %.2fs" % (ncores, t) random.seed(1) param = BKZ.Param(block_size, strategies=default_strategies, min_success_probability=min_success_probability, max_loops=max_loops, flags=BKZ.VERBOSE | BKZ.MAX_LOOPS) t = time.time() bkz = BKZ2(copy(A)) bkz(param) trace_s = bkz.trace t = time.time() - t print " Sequential: %.2fs" % (t, ) return trace_p, trace_s
def dim_error_tradeoff(A, c, u, beta, h, k, alpha=None, tau=None, float_type="mpfr", use_lll=True): """ :param A: LWE matrix :param c: LWE vector :param u: Uniform vector :param beta: BKW block size :param h: Hamming weight of secret :param k: LWE dim after tradeoff :param tau: number of new samples to generate :param use_lll: If True, run BKZ only once and then run LLL If False, run BKZ iteratively * secret vector s is used to see the error term of new LWE(-like) samples. """ from fpylll import BKZ, IntegerMatrix, LLL, GSO from fpylll.algorithms.bkz2 import BKZReduction as BKZ2 n = A.ncols() q = A.base_ring().order() K = GF(q, proof=False) if alpha is None: alpha = 8 / q if tau is None: tau = 30 m = A.nrows() / n scale = round(alpha * q * sqrt(m) / sqrt(2 * pi * h)) scale = ZZ(scale) count = 0 A_k = matrix(ZZ, 1, k) c_k = [] u_k = [] length = 0 while count < tau: r = count * m T = A.matrix_from_rows([i + r for i in range(m)]) ct = c[r:r + m] ut = u[r:r + m] T1 = T.matrix_from_columns([i for i in range(n - k)]) L = dual_instance1(T1, scale=scale) L = IntegerMatrix.from_matrix(L) L = LLL.reduction(L) M = GSO.Mat(L, float_type=float_type) bkz = BKZ2(M) param = BKZ.Param(block_size=beta, strategies=BKZ.DEFAULT_STRATEGY, auto_abort=True, max_loops=16, flags=BKZ.AUTO_ABORT | BKZ.MAX_LOOPS) bkz(param) H = copy(L) y = vector(ZZ, tuple(L[0])) length += y.norm() T2 = T.matrix_from_columns([n - k + i for i in range(k)]) A_kt, c_kt, u_kt = apply_short1(y, T2, ct, ut, scale=scale) if r == 0: A_k[0] = A_kt else: A_k = A_k.stack(A_kt) c_k.append(c_kt) u_k.append(u_kt) count += 1 length = float(length / tau) A_k = A_k.change_ring(K) c_k = vector(K, c_k) u_k = vector(K, u_k) B = float(2 + 1 / sqrt(2 * pi)) * (alpha * q) B = B * B * m / (m + n) B = sqrt(B) * length / scale print '(A_k, c_k) is k-dim LWE samples (with secret s[-k:]) / (A_k, u_k) is uniform samples. ' return A_k, c_k, u_k, B
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 approx_svp_time(seed, params, return_queue=None, progressive=False): """Run Approx-SVP_{1.05} reduction on ``A`` using ``params``. :param seed: random seed for matrix creation :param params: BKZ preprocessing parameters, preprocessing block size is ignored :param return_queue: if not ``None``, the result is put on this queue. :param progressive: run Progressive-BKZ """ from chal import load_svp_challenge from fpylll.algorithms.bkz import BKZReduction as BKZBase FPLLL.set_random_seed(seed) A = load_svp_challenge(params.block_size, seed=seed) M = GSO.Mat(A) M.update_gso() gh = gaussian_heuristic(M.r()) target_norm = 1.05**2 * gh nodes_per_second = 2.0 * 10**9 / 100.0 self = BKZ2(M) tracer = BKZTreeTracer(self, start_clocks=True) rerandomize = False preproc_cost = None with tracer.context(("tour", 0)): while M.get_r(0, 0) > target_norm: with tracer.context("preprocessing"): if rerandomize: self.randomize_block( 1, params.block_size, density=params.rerandomization_density, tracer=tracer) with tracer.context("reduction"): BKZBase.svp_preprocessing(self, 0, params.block_size, params, tracer) # LLL preproc = round(0.9878 * params.block_size - 24.12) # curve fitted to chal.py output prepar = params.__class__(block_size=preproc, strategies=params.strategies, flags=BKZ.GH_BND) self.tour(prepar, 0, params.block_size, tracer=tracer) if preproc_cost is None: preproc_cost = float( tracer.trace.find("preprocessing")["walltime"]) preproc_cost *= nodes_per_second with tracer.context("pruner"): step_target = M.get_r(0, 0) * 0.99 if progressive else target_norm pruner = Pruning.Pruner(step_target, preproc_cost, [M.r()], target=1, metric=Pruning.EXPECTED_SOLUTIONS) coefficients = pruner.optimize_coefficients([1.] * M.d) try: enum_obj = Enumeration(self.M) with tracer.context("enumeration", enum_obj=enum_obj, full=True): max_dist, solution = enum_obj.enumerate( 0, params.block_size, target_norm, 0, pruning=coefficients)[0] with tracer.context("postprocessing"): self.svp_postprocessing(0, params.block_size, solution, tracer=tracer) rerandomize = False except EnumerationError: rerandomize = True self.M.update_gso() logger.debug("r_0: %7.2f, target: %7.2f, preproc: %3d" % (log(M.get_r(0, 0), 2), log(target_norm, 2), preproc)) tracer.exit() tracer.trace.data["|A_0|"] = A[0].norm() tracer.trace.data["preprocessing_block_size"] = preproc if return_queue: return_queue.put(tracer.trace) else: return tracer.trace
# -*- coding: utf-8 -*- import copy from fpylll import IntegerMatrix, BKZ from fpylll.algorithms.bkz import BKZReduction as BKZ1 from fpylll.algorithms.bkz2 import BKZReduction as BKZ2 n = 100 A = IntegerMatrix.random(n, "qary", k=n//2, bits=40) param = BKZ.Param(block_size=40, max_loops=3, strategies=BKZ.DEFAULT_STRATEGY, flags=BKZ.MAX_LOOPS|BKZ.VERBOSE) bkz = BKZ1(copy.copy(A)) bkz(param) print(bkz.trace.report()) bkz = BKZ2(copy.copy(A)) bkz(param) print(bkz.trace.report()) stat = bkz.trace.tour[0].find("enumeration")["%"] print stat.min, stat.max
FPLLL.set_random_seed(1) n, bits = 120, 40 A = IntegerMatrix.random(n, "qary", k=n / 2, bits=bits) beta = 60 tours = 6 par = BKZ.Param(block_size=beta, strategies=BKZ.DEFAULT_STRATEGY) LLL.reduction(A) M = GSO.Mat(A) M.update_gso() norms = [[log(M.get_r(i, i)) for i in range(n)]] bkz = BKZ2(M) for i in range(tours): bkz.tour(par) norms += [[log(M.get_r(i, i)) for i in range(n)]] #CO = ["#4D4D4D", "#5DA5DA", "#FAA43A", "#60BD68", # "#F17CB0", "#B2912F", "#B276B2", "#DECF3F", "#F15854"] Colors = [ "#12035D", "#22107F", "#45349E", "#6F5FBF", "#9587DE", "#B1A5EE", "#DED8FA" ] X = range(n) plt.plot(X, norms[1], color=Colors[0], label="LLL") for i, _norms in enumerate(norms[1:]):
def __call__(cls, M, predicate, squared_target_norm, invalidate_cache=lambda: None, target_prob=None, preproc_offset=20, ph=0, threads=1, **kwds): preproc_time = None ntests = 0 if target_prob is None: target_prob = cls.DEFAULT_TARGET_PROB bkz_res = usvp_pred_bkz_enum_solve(M, predicate, block_size=min( STRATEGIES_MAX_DIM, M.d), invalidate_cache=invalidate_cache, threads=threads) if bkz_res.success: # this might be enough return bkz_res FPLLL.set_threads(threads) M.update_gso() bkz = BKZ2(M) tracer = BKZTreeTracer(bkz, root_label="enum_pred", start_clocks=True) remaining_probability, rerandomize, found, solution = (1.0, False, False, None) while remaining_probability > 1.0 - target_prob: invalidate_cache() with tracer.context("preprocessing"): if rerandomize: with tracer.context("randomization"): bkz.randomize_block(0, M.d, tracer=tracer, density=3) with tracer.context("reduction"): with tracer.context("lll"): bkz.lll_obj() for _ in range(4): bkz.tour( BKZ.EasyParam(min(max(M.d - preproc_offset, 2), STRATEGIES_MAX_DIM), flags=BKZ.GH_BND), tracer=tracer, ) if preproc_time is None: preproc_time = float( tracer.trace.child("preprocessing")["cputime"]) with tracer.context("check"): for v in M.B: ntests += 1 if predicate(v, standard_basis=True): found = True solution = tuple([int(v_) for v_ in v]) break if found: break with tracer.context("pruner"): preproc_cost = threads * preproc_time * 2 * 10**9 / 100 # 100 cycles per node with SuppressStream(): r = [] for i in range(M.d): r_, exp = M.get_r_exp(i, i) r.append(r_ * 2**(exp - ph)) (cost, prob), coeffs = cls.pruning_coefficients( squared_target_norm / 2**ph, r, preproc_cost, target_prob=target_prob) def callbackf(v): nonlocal ntests ntests += 1 return predicate(v, standard_basis=False) enum_obj = Enumeration(M, callbackf=callbackf) with tracer.context("enumeration", enum_obj=enum_obj, probability=prob, full=True): try: solutions = enum_obj.enumerate(0, M.d, squared_target_norm / 2**ph, ph, pruning=coeffs) _, v = solutions[0] found = True solution = tuple([int(v_) for v_ in M.B.multiply_left(v)]) break except EnumerationError: pass rerandomize = True remaining_probability *= 1 - prob tracer.exit() FPLLL.set_threads(1) b0, b0e = bkz.M.get_r_exp(0, 0) return USVPPredSolverResults( success=found, solution=solution, ntests=ntests + bkz_res.ntests, b0=b0**(0.5) * 2**(b0e / 2.0), cputime=tracer.trace.data["cputime"] + bkz_res.cputime, walltime=tracer.trace.data["walltime"] + bkz_res.walltime, data=tracer.trace, )