Exemple #1
0
def full_sieve_kernel(arg0, params=None, seed=None):
    # Pool.map only supports a single parameter
    if params is None and seed is None:
        n, params, seed = arg0
    else:
        n = arg0

    pump_params = pop_prefixed_params("pump", params)
    workout_params = pop_prefixed_params("workout", params)
    verbose = params.pop("verbose")
    load_matrix = params.pop("load_matrix")
    pre_bkz = params.pop("pre_bkz")
    trace = params.pop("trace")

    reserved_n = n
    params = params.new(reserved_n=reserved_n, otf_lift=False)

    if load_matrix is None:
        A, bkz = load_svpchallenge_and_randomize(n, s=0, seed=seed)
        if verbose:
            print("Loaded challenge dim %d" % n)
        if pre_bkz is not None:
            par = BKZ_FPYLLL.Param(pre_bkz,
                                   strategies=BKZ_FPYLLL.DEFAULT_STRATEGY,
                                   max_loops=1)
            bkz(par)

    else:
        A, _ = load_matrix_file(load_matrix, doLLL=False, high_prec=False)
        if verbose:
            print("Loaded file '%s'" % load_matrix)

    g6k = Siever(A, params, seed=seed)
    if trace:
        tracer = SieveTreeTracer(g6k,
                                 root_label=("full-sieve", n),
                                 start_clocks=True)
    else:
        tracer = dummy_tracer

    # Actually runs a workout with very large decrements, so that the basis is kind-of reduced
    # for the final full-sieve
    workout(g6k,
            tracer,
            0,
            n,
            dim4free_min=0,
            dim4free_dec=15,
            pump_params=pump_params,
            verbose=verbose,
            **workout_params)

    g6k.output_bench()

    tracer.exit()

    if hasattr(tracer, "trace"):
        return tracer.trace
    else:
        return None
Exemple #2
0
def test_bkz():
    for d in dimensions:
        # Primal
        A = make_integer_matrix(d)
        g6k = Siever(A)
        bkz(g6k, dummy_tracer, 20)
        bkz(g6k, dummy_tracer, 20)
        bkz(g6k, dummy_tracer, 20)

        # Dual
        A = make_integer_matrix(d)
        g6k = Siever(A)
        with g6k.temp_params(dual_mode=True):
            bkz(g6k, dummy_tracer, 20)
            bkz(g6k, dummy_tracer, 20)
            bkz(g6k, dummy_tracer, 20)

        # Primal then Dual
        A = make_integer_matrix(d)
        g6k = Siever(A)
        bkz(g6k, dummy_tracer, 20)
        bkz(g6k, dummy_tracer, 20)
        bkz(g6k, dummy_tracer, 20)
        with g6k.temp_params(dual_mode=True):
            bkz(g6k, dummy_tracer, 20)
            bkz(g6k, dummy_tracer, 20)
            bkz(g6k, dummy_tracer, 20)

        # Slide
        A = make_integer_matrix(d)
        g6k = Siever(A)
        block_size = 25 if d == 50 else 20
        slide(g6k, dummy_tracer, block_size, overlap=10)
        slide(g6k, dummy_tracer, block_size, overlap=10)
        slide(g6k, dummy_tracer, block_size, overlap=10)
Exemple #3
0
def hkz_kernel(arg0, params=None, seed=None):
    # Pool.map only supports a single parameter
    if params is None and seed is None:
        n, params, seed = arg0
    else:
        n = arg0

    reserved_n = n
    params = params.new(reserved_n=reserved_n, otf_lift=False)
    verbose = params.pop("verbose")

    pump_params = pop_prefixed_params("pump", params)
    workout_params = pop_prefixed_params("workout", params)

    verbose = params.pop("verbose")
    if verbose:
        workout_params["verbose"] = True
    challenge_seed = params.pop("challenge_seed")

    A, _ = load_svpchallenge_and_randomize(n, s=challenge_seed, seed=seed)

    g6k = Siever(A, params, seed=seed)
    tracer = SieveTreeTracer(g6k, root_label=("hkz", n), start_clocks=True)

    # runs a workout woth pump-down down until the end
    workout(g6k, tracer, 0, n, pump_params=pump_params, verbose=verbose, **workout_params)
    #Just making sure
    pump(g6k, tracer, 15, n-15, 0, **pump_params)
    g6k.lll(0, n)

    return tracer.exit()
Exemple #4
0
def test_ntru_gsa(n):

	# read from file
	filename = 'lwe_n'+str(n)+'.txt'
	data = open(filename, 'r').readlines()
	q = int(data[0])
	B = eval(",".join([s_.replace('\n','').replace(" ", ", ") for s_ in data[1:n+1]]))
	B = IntegerMatrix.from_matrix(B)
	c = eval(data[n+1].replace(" ", ','))

	beta, nsamples, prep_rt, GSA = find_beta(n, q, n)
	print('beta, nsamples:', beta, nsamples)
	print('GSA predicted:')
	print(GSA)

	print('beta, nsamples: ', beta, nsamples)
	Basis = primal_lattice_basis(B, c, q, nsamples)

	g6k = Siever(Basis)

	d = g6k.full_n
	g6k.lll(0, g6k.full_n)
	print(g6k.MatGSO)
	slope = basis_quality(g6k.M)["/"]
	print("Intial Slope = %.5f\n" % slope)

	print('GSA input:')
	print([g6k.M.get_r(i, i) for i in range(d)])

	print('d:', d)
	target_norm = ceil( (2./3)*d + 1) + 1
	print("target_norm:", target_norm)
	#
	#   Preprocessing
	#
	if beta < 50:
		print("Starting a fpylll BKZ-%d tour. " % (beta))
		sys.stdout.flush()
		bkz = BKZReduction(g6k.M)
		par = fplll_bkz.Param(beta,
							  strategies=fplll_bkz.DEFAULT_STRATEGY,
							  max_loops=1)
		bkz(par)

	else:
		print("Starting a pnjBKZ-%d tour. " % (beta))
		pump_n_jump_bkz_tour(g6k, tracer, beta, jump=jump,
								 verbose=verbose,
								 extra_dim4free=extra_dim4free,
								 dim4free_fun=dim4free_fun,
								 goal_r0=target_norm,
								 pump_params=pump_params)

			#T_BKZ = time.time() - T0_BKZ

	print('GSA output:')
	print([g6k.M.get_r(i, i) for i in range(d)])

	return 1
Exemple #5
0
def test_bkz():
    for d in dimensions:
        # Primal
        A = make_integer_matrix(d)
        g6k = Siever(A)
        bkz(g6k, dummy_tracer, 20)
        bkz(g6k, dummy_tracer, 20)
        bkz(g6k, dummy_tracer, 20)

        # Dual
        A = make_integer_matrix(d)
        g6k = Siever(A)
        with g6k.temp_params(dual_mode=True):
            bkz(g6k, dummy_tracer, 20)
            bkz(g6k, dummy_tracer, 20)
            bkz(g6k, dummy_tracer, 20)

        # Primal then Dual
        A = make_integer_matrix(d)
        g6k = Siever(A)
        bkz(g6k, dummy_tracer, 20)
        bkz(g6k, dummy_tracer, 20)
        bkz(g6k, dummy_tracer, 20)
        with g6k.temp_params(dual_mode=True):
            bkz(g6k, dummy_tracer, 20)
            bkz(g6k, dummy_tracer, 20)
            bkz(g6k, dummy_tracer, 20)
Exemple #6
0
def svp_kernel_trial(arg0, params=None, seed=None, goal_r0=None):
    # Pool.map only supports a single parameter
    if params is None and seed is None:
        n, params, seed = arg0
    else:
        n = arg0

    params = copy.copy(params)
    dim4free_dec = params.pop("workout/dim4free_dec")
    pump_params = pop_prefixed_params("pump", params)
    challenge_seed = params.pop("challenge_seed")

    A, _ = load_svpchallenge_and_randomize(n, s=challenge_seed, seed=seed)
    g6k = Siever(A, params, seed=seed)
    tracer = SieveTreeTracer(g6k,
                             root_label=("svp-challenge", n),
                             start_clocks=True)

    gh = gaussian_heuristic([g6k.M.get_r(i, i) for i in range(n)])
    ds = list(range(0, n - 40, dim4free_dec))[::-1] + 10 * [0]

    if goal_r0 is None:
        goal_r0 = 1.1 * gh

    for d in ds:
        workout(g6k,
                tracer,
                0,
                n,
                dim4free_dec=dim4free_dec,
                goal_r0=goal_r0 * 1.001,
                pump_params=pump_params)

    tracer.exit()
    return int(g6k.M.get_r(0, 0)), gh
Exemple #7
0
def full_sieve_kernel(arg0, params=None, seed=None):
    # Pool.map only supports a single parameter
    if params is None and seed is None:
        n, params, seed = arg0
    else:
        n = arg0

    pump_params = pop_prefixed_params("pump", params)
    verbose = params.pop("verbose")

    reserved_n = n
    params = params.new(reserved_n=reserved_n, otf_lift=False)

    challenge_seed = params.pop("challenge_seed")
    A, _ = load_svpchallenge_and_randomize(n, s=challenge_seed, seed=seed)

    g6k = Siever(A, params, seed=seed)
    tracer = SieveTreeTracer(g6k,
                             root_label=("full-sieve", n),
                             start_clocks=True)

    # Actually runs a workout with very large decrements, so that the basis is kind-of reduced
    # for the final full-sieve
    workout(
        g6k,
        tracer,
        0,
        n,
        dim4free_min=0,
        dim4free_dec=15,
        pump_params=pump_params,
        verbose=verbose,
    )

    return tracer.exit()
Exemple #8
0
def asvp_kernel(arg0, params=None, seed=None):
    logger = logging.getLogger('asvp')

    # Pool.map only supports a single parameter
    if params is None and seed is None:
        n, params, seed = arg0
    else:
        n = arg0

    params = copy.copy(params)

    load_matrix = params.pop("load_matrix")
    pump_params = pop_prefixed_params("pump", params)
    workout_params = pop_prefixed_params("workout", params)
    verbose = params.pop("verbose")
    if verbose:
        workout_params["verbose"] = True
    challenge_seed = params.pop("challenge_seed")

    if load_matrix is None:
        A, _ = load_svpchallenge_and_randomize(n, s=challenge_seed, seed=seed)
        if verbose:
            print(("Loaded challenge dim %d" % n))
    else:
        A, _ = load_matrix_file(load_matrix)
        if verbose:
            print(("Loaded file '%s'" % load_matrix))

    g6k = Siever(A, params, seed=seed)
    tracer = SieveTreeTracer(g6k,
                             root_label=("svp-challenge", n),
                             start_clocks=True)

    gh = gaussian_heuristic([g6k.M.get_r(i, i) for i in range(n)])
    goal_r0 = (1.05**2) * gh
    if verbose:
        print(("gh = %f, goal_r0/gh = %f, r0/gh = %f" %
               (gh, goal_r0 / gh, sum([x * x for x in A[0]]) / gh)))

    flast = workout(g6k,
                    tracer,
                    0,
                    n,
                    goal_r0=goal_r0,
                    pump_params=pump_params,
                    **workout_params)

    tracer.exit()
    stat = tracer.trace
    stat.data["flast"] = flast

    if verbose:
        logger.info("sol %d, %s" % (n, A[0]))

    norm = sum([x * x for x in A[0]])
    if verbose:
        logger.info("norm %.1f ,hf %.5f" % (norm**.5, (norm / gh)**.5))

    return tracer.trace
Exemple #9
0
def svp_kernel(arg0, params=None, seed=None):
    # Pool.map only supports a single parameter
    if params is None and seed is None:
        n, params, seed = arg0
    else:
        n = arg0

    params = copy.copy(params)
    challenge_seed = params.pop("challenge_seed")
    alg = params.pop("svp/alg")
    workout_params = pop_prefixed_params("workout/", params)
    pump_params = pop_prefixed_params("pump/", params)

    goal_r0 = 1.001 * load_svpchallenge_norm(n, s=challenge_seed)
    A, bkz = load_svpchallenge_and_randomize(n, s=challenge_seed, seed=seed)
    g6k = Siever(A, params, seed=seed)
    tracer = SieveTreeTracer(g6k,
                             root_label=("svp-exact", n),
                             start_clocks=True)

    if alg == "enum":
        assert len(workout_params) + len(pump_params) == 0
        bkz_params = fplll_bkz.Param(
            block_size=n,
            max_loops=1,
            strategies=fplll_bkz.DEFAULT_STRATEGY,
            flags=fplll_bkz.GH_BND,
        )
        svp_enum(bkz, bkz_params, goal_r0)
        flast = 0
    elif alg == "duc18":
        assert len(workout_params) + len(pump_params) == 0
        flast = ducas18(g6k, tracer, goal=goal_r0)
    elif alg == "workout":
        flast = workout(g6k,
                        tracer,
                        0,
                        n,
                        goal_r0=goal_r0,
                        pump_params=pump_params,
                        **workout_params)
    else:
        raise ValueError("Unrecognized algorithm for SVP")

    r0 = bkz.M.get_r(0, 0) if alg == "enum" else g6k.M.get_r(0, 0)
    if r0 > goal_r0:
        raise ValueError("Did not reach the goal")
    if 1.002 * r0 < goal_r0:
        raise ValueError(
            "Found a vector shorter than the goal for n=%d s=%d." %
            (n, challenge_seed))

    tracer.exit()
    stat = tracer.trace
    stat.data["flast"] = flast
    return stat
Exemple #10
0
def plain_sieve_kernel(arg0, params=None, seed=None):
    # Pool.map only supports a single parameter
    if params is None and seed is None:
        n, params, seed = arg0
    else:
        n = arg0

    alg = params.pop("alg")

    reserved_n = n
    params = params.new(reserved_n=reserved_n, otf_lift=False)

    A, _ = load_svpchallenge_and_randomize(n, s=0, seed=seed)
    g6k = Siever(A, params, seed=seed)
    tracer = SieveTreeTracer(g6k, root_label=("plain-sieve", n), start_clocks=True)
    g6k.initialize_local(0, 0, n)
    g6k(alg=alg, tracer=tracer)
    tracer.exit()
    return tracer.trace
Exemple #11
0
def find_norm_kernel_trial(arg0, params=None, seed=None, goal_r0=None):
    # Pool.map only supports a single parameter
    if params is None and seed is None:
        n, params, seed = arg0
    else:
        n = arg0

    params = copy.copy(params)
    dim4free_dec = params.pop("workout/dim4free_dec")
    pump_params = pop_prefixed_params("pump", params)
    load_matrix = params.pop("load_matrix")
    verbose = params.pop("verbose")

    A, _ = load_matrix_file(load_matrix,
                            randomize=True,
                            seed=None,
                            float_type="double")

    if A.nrows != n:
        raise ValueError(
            f"wrong dimension:: Expected dim(A) = {A.nrows}, got n = {n}")

    g6k = Siever(A, params, seed=seed)
    tracer = SieveTreeTracer(g6k,
                             root_label=("svp-challenge", n),
                             start_clocks=True)

    gh = gaussian_heuristic([g6k.M.get_r(i, i) for i in range(n)])
    ds = list(range(0, n - 40, dim4free_dec))[::-1] + 10 * [0]

    if goal_r0 is None:
        goal_r0 = 1.1 * gh

    if verbose and n < 90:
        verbose = False

    for d in ds:
        workout(g6k,
                tracer,
                0,
                n,
                dim4free_dec=dim4free_dec,
                goal_r0=goal_r0 * 1.001,
                pump_params=pump_params,
                verbose=verbose)

    tracer.exit()
    return int(g6k.M.get_r(0, 0)), gh
Exemple #12
0
def asvp_kernel(arg0, params=None, seed=None):
    logger = logging.getLogger('asvp')

    # Pool.map only supports a single parameter
    if params is None and seed is None:
        n, params, seed = arg0
    else:
        n = arg0

    params = copy.copy(params)

    load_matrix = params.pop("load_matrix")
    pump_params = pop_prefixed_params("pump", params)
    workout_params = pop_prefixed_params("workout", params)
    verbose = params.pop("verbose")
    if verbose:
        workout_params["verbose"] = True
    challenge_seed = params.pop("challenge_seed")

    if load_matrix is None:
        A, _ = load_svpchallenge_and_randomize(n, s=challenge_seed, seed=seed)
        if verbose:
            print("Loaded challenge dim %d" % n)
    else:
        A, _ = load_matrix_file(load_matrix)
        if verbose:
            print("Loaded file '%s'" % load_matrix)

    g6k = Siever(A, params, seed=seed)
    tracer = SieveTreeTracer(g6k, root_label=("svp-challenge", n), start_clocks=True)

    gh = gaussian_heuristic([g6k.M.get_r(i, i) for i in range(n)])

    flast = workout(g6k, tracer, 0, n, pump_params=pump_params, **workout_params)

    tracer.exit()
    stat = tracer.trace

    f = workout_params["dim4free_min"]
    gh2 = gaussian_heuristic([g6k.M.get_r(i, i) for i in range(f, n)])
    quality = (gh * (n - f)) / (gh2 * n)

    stat.data["quality"] = quality

    print >> sys.stderr, g6k.M.B

    return tracer.trace
Exemple #13
0
def asvp_kernel(arg0, params=None, seed=None):
    # Pool.map only supports a single parameter
    if params is None and seed is None:
        n, params, seed = arg0
    else:
        n = arg0

    params = copy.copy(params)

    load_matrix = params.pop("load_matrix")
    goal_r0__gh = params.pop('goal_r0__gh')
    pump_params = pop_prefixed_params("pump", params)
    workout_params = pop_prefixed_params("workout", params)
    verbose = params.pop("verbose")
    if verbose:
        workout_params["verbose"] = True

    A, _ = load_matrix_file(load_matrix, randomize=False, seed=None, float_type="double")
    if verbose:
        print(("Loaded file '%s'" % load_matrix))

    g6k = Siever(A, params, seed=seed)
    tracer = SieveTreeTracer(g6k, root_label=("svp-challenge", n), start_clocks=True)

    gh = gaussian_heuristic([g6k.M.get_r(i, i) for i in range(n)])
    goal_r0 = (goal_r0__gh**2) * gh
    if verbose:
        print(("gh = %f, goal_r0/gh = %f, r0/gh = %f" % (gh, goal_r0/gh, sum([x*x for x in A[0]])/gh)))
 
    flast = workout(g6k, tracer, 0, n, goal_r0=goal_r0, **workout_params)

    tracer.exit()
    stat = tracer.trace
    sol = tuple(A[0])
    stat.data["flast"] = flast
    tracer.trace.data['res'] = A

    if verbose:
        print(f"svp: sol {sol}")

    norm = sum([x*x for x in sol])
    if verbose:
        print("svp: norm %.1f ,hf %.5f" % (norm**.5, (norm/gh)**.5))

    return tracer.trace
Exemple #14
0
def bkz_kernel(arg0, params=None, seed=None):
    """
    Run the BKZ algorithm with different parameters.

    :param d: the dimension of the lattices to BKZ reduce
    :param params: parameters for BKZ:

        - bkz/alg: choose the underlying BKZ from
          {fpylll, naive, pump_n_jump, slide}

        - bkz/blocksizes: given as low:high:inc perform BKZ reduction
          with blocksizes in range(low, high, inc) (after some light)
          prereduction

        - bkz/pre_blocksize: prereduce lattice with fpylll BKZ up
          to this blocksize

        - bkz/tours: the number of tours to do for each blocksize

        - bkz/extra_dim4free: lift to indices extra_dim4free earlier in
          the lattice than the currently sieved block

        - bkz/jump: the number of blocks to jump in a BKZ tour after
          each pump

        - bkz/dim4free_fun: in blocksize x, try f(x) dimensions for free,
          give as 'lambda x: f(x)', e.g. 'lambda x: 11.5 + 0.075*x'

        - pump/down_sieve: sieve after each insert in the pump-down
          phase of the pump
        
        - slide/overlap: shift of the dual blocks when running slide reduction

        - challenge_seed: a seed to randomise the generated lattice

        - dummy_tracer: use a dummy tracer which capture less information

        - verbose: print tracer information throughout BKZ run

    """
    # Pool.map only supports a single parameter
    if params is None and seed is None:
        d, params, seed = arg0
    else:
        d = arg0

    # params for underlying BKZ/workout/pump
    dim4free_fun = params.pop("bkz/dim4free_fun")
    extra_dim4free = params.pop("bkz/extra_dim4free")
    jump = params.pop("bkz/jump")
    overlap = params.pop("slide/overlap")
    pump_params = pop_prefixed_params("pump", params)
    workout_params = pop_prefixed_params("workout", params)

    # flow of the bkz experiment
    algbkz = params.pop("bkz/alg")
    blocksizes = params.pop("bkz/blocksizes")
    blocksizes = eval("range(%s)" % re.sub(":", ",", blocksizes))
    pre_blocksize = params.pop("bkz/pre_blocksize")
    tours = params.pop("bkz/tours")

    # misc
    verbose = params.pop("verbose")
    dont_trace = params.pop("dummy_tracer", False)

    if blocksizes[-1] > d:
        print('set a smaller maximum blocksize with --blocksizes')
        return

    challenge_seed = params.pop("challenge_seed")

    A, bkz = load_prebkz(d, s=challenge_seed, blocksize=pre_blocksize)

    MM = GSO.Mat(A,
                 float_type="double",
                 U=IntegerMatrix.identity(A.nrows, int_type=A.int_type),
                 UinvT=IntegerMatrix.identity(A.nrows, int_type=A.int_type))

    g6k = Siever(MM, params, seed=seed)
    if dont_trace:
        tracer = dummy_tracer
    else:
        tracer = SieveTreeTracer(g6k, root_label=("bkz", d), start_clocks=True)

    if algbkz == "fpylll":
        M = bkz.M
    else:
        M = g6k.M

    T0 = time.time()
    for blocksize in blocksizes:

        for t in range(tours):
            with tracer.context("tour", t, dump_gso=True):
                if algbkz == "fpylll":
                    par = BKZ_FPYLLL.Param(
                        blocksize,
                        strategies=BKZ_FPYLLL.DEFAULT_STRATEGY,
                        max_loops=1)
                    bkz(par)

                elif algbkz == "naive":
                    naive_bkz_tour(g6k,
                                   tracer,
                                   blocksize,
                                   extra_dim4free=extra_dim4free,
                                   dim4free_fun=dim4free_fun,
                                   workout_params=workout_params,
                                   pump_params=pump_params)

                elif algbkz == "pump_and_jump":
                    pump_n_jump_bkz_tour(g6k,
                                         tracer,
                                         blocksize,
                                         jump=jump,
                                         dim4free_fun=dim4free_fun,
                                         extra_dim4free=extra_dim4free,
                                         pump_params=pump_params)
                elif algbkz == "slide":
                    slide_tour(g6k,
                               dummy_tracer,
                               blocksize,
                               overlap=overlap,
                               dim4free_fun=dim4free_fun,
                               extra_dim4free=extra_dim4free,
                               workout_params=workout_params,
                               pump_params=pump_params)
                else:
                    raise ValueError("bkz/alg=%s not recognized." % algbkz)

            if verbose:
                slope = basis_quality(M)["/"]
                fmt = "{'alg': '%25s', 'jump':%2d, 'pds':%d, 'extra_d4f': %2d, 'beta': %2d, 'slope': %.5f, 'total walltime': %.3f}"  # noqa
                print(fmt % (algbkz + "+" + ("enum" if algbkz == "fpylll" else
                                             g6k.params.default_sieve), jump,
                             pump_params["down_sieve"], extra_dim4free,
                             blocksize, slope, time.time() - T0))

    tracer.exit()
    slope = basis_quality(M)["/"]
    stat = tracer.trace
    try:
        stat.data["slope"] = np.array(slope)
        return stat
    except AttributeError:
        return None
Exemple #15
0
    def run(self):
        self.thread_name = current_thread().name
        if self.thread_name == "MainThread":
            self.thread_name = " "
        self.thread_start = time.time()
        self.tried = set()

        dim = self.params["dimension"]

        if self.params["bounds"]["type"] in ("known", "knownre"):
            sigs = self.signatures
            self.signatures = []
            blens = []
            for sig in sigs:
                blen = int(self.recompute_nonce(sig)).bit_length()
                i = bisect(blens, blen)
                if i < dim:
                    blens.insert(i, blen)
                    self.signatures.insert(i, sig)
                if len(blens) > dim:
                    blens.pop()
                    self.signatures.pop()

        pairs = [(sig.t, sig.u) for sig in self.signatures[:dim]]
        nonces = []
        for sig in self.signatures[:dim]:
            nonces.append(int(self.recompute_nonce(sig)))
        real_bitlens = [nonce.bit_length() for nonce in nonces]
        real_infos = [
            self.curve.group.n.bit_length() - bitlen for bitlen in real_bitlens
        ]
        real_info = sum(real_infos)

        if self.params["bounds"]["type"] == "constant":
            value = self.const_bound_func(self.params["bounds"])
            self.bounds = [value for _ in range(dim)]
        elif self.params["bounds"]["type"] == "geom":
            self.bounds = [
                self.geom_bound_func(i, dim, self.params["bounds"])
                for i in range(dim)
            ]
        elif self.params["bounds"]["type"] == "geomN":
            self.bounds = [
                self.geomN_bound_func(i, self.params["attack"]["num"],
                                      self.params["bounds"])
                for i in range(dim)
            ]
        elif self.params["bounds"]["type"] == "known" or self.params["bounds"][
                "type"] == "knownre":
            self.bounds = [self.known_bound_func(i, dim) for i in range(dim)]
        elif self.params["bounds"]["type"] == "template":
            self.bounds = [0 for _ in range(dim)]
            templates = copy(self.params["bounds"])
            del templates["type"]
            for k, v in templates.items():
                for i in range(*v):
                    self.bounds[i] = self.curve.group.n.bit_length() - int(k)

        bnds = [self.bounds[i] for i in range(dim)]
        info = sum(bnds)
        overhead = info / self.curve.bit_size()
        self.log(
            "Building lattice with {} bits of information (overhead {:.2f}).".
            format(info, overhead))
        liars = 0
        bad_info = 0
        good_info = 0
        liarpos = []
        for i, real, our in zip(range(dim), real_infos, bnds):
            if real < our:
                liars += 1
                bad_info += real
                liarpos.append(str(i) + "@" + str(our - real))
            else:
                good_info += real
        self.log("Real info: {}".format(real_info))
        self.log("Liars: {}".format(liars))
        self.log("Good info: {}".format(good_info))
        self.log("Bad info: {}".format(bad_info))
        self.log("Liar positions: {}".format(";".join(liarpos)))

        self.svp = self.params["attack"]["method"] == "svp"
        self.sieve = self.params["attack"]["method"] == "sieve"
        self.np = self.params["attack"]["method"] == "np"
        self.round = self.params["attack"]["method"] == "round"

        if self.svp or self.sieve:
            lattice = self.build_svp_lattice(pairs, dim, self.params["bounds"])
        elif self.np or self.round:
            lattice = self.build_cvp_lattice(pairs, dim, self.params["bounds"])
            target = self.build_target(pairs, dim, self.params["bounds"])
        else:
            self.log("Bad method: {}".format(self.params["attack"]["method"]))
            return

        if self.sieve:
            self.reduce_lattice(lattice, None)
            g6k = Siever(lattice)
            self.log("Start SIEVE.")
            g6k.initialize_local(0, 0, dim)
            try:
                g6k()
            except SaturationError as e:
                pass
            short = self.verify_sieve(lattice, g6k.best_lifts())
            if short is not None:
                i, res = short
                self.log("Result row: {}".format(i))
                norm = self.norm(res)
                self.log("Result normdist: {}".format(norm))
            return

        reds = [None] + self.params["betas"]
        for beta in reds:
            lattice = self.reduce_lattice(lattice, beta)
            gso = GSO.Mat(lattice)
            gso.update_gso()
            if self.svp:
                short = self.verify_shortest(lattice, self.pubkey)
                if short is not None:
                    i, res = short
                    self.log("Result row: {}".format(i))
                    norm = self.norm(res)
                    self.log("Result normdist: {}".format(norm))
                    break

            if self.round:
                closest = self.babai_round(lattice, target)
                if self.verify_closest(closest, self.pubkey):
                    dist = self.dist(closest, target)
                    self.log("Result normdist: {}".format(dist))
                    break

            if self.np:
                closest = self.babai_np(lattice, gso, target)
                if self.verify_closest(closest, self.pubkey) is not None:
                    dist = self.dist(closest, target)
                    self.log("Result normdist: {}".format(dist))
                    break
def asvp_kernel(arg0, params=None, seed=None):
    logger = logging.getLogger('asvp')

    # Pool.map only supports a single parameter
    if params is None and seed is None:
        n, params, seed = arg0
    else:
        n = arg0

    params = copy.copy(params)

    load_matrix = params.pop("load_matrix")
    pre_bkz = params.pop("pre_bkz")
    pump_params = pop_prefixed_params("pump", params)
    workout_params = pop_prefixed_params("workout", params)
    verbose = params.pop("verbose")
    if verbose:
        workout_params["verbose"] = True
    challenge_seed = params.pop("challenge_seed")
    high_prec = params.pop("high_prec")
    trace = params.pop("trace")

    if load_matrix is None:
        A, bkz = load_svpchallenge_and_randomize(n,
                                                 s=challenge_seed,
                                                 seed=seed)
        if verbose:
            print("Loaded challenge dim %d" % n)
        if pre_bkz is not None:
            par = BKZ_FPYLLL.Param(pre_bkz,
                                   strategies=BKZ_FPYLLL.DEFAULT_STRATEGY,
                                   max_loops=1)
            bkz(par)

    else:
        A, _ = load_matrix_file(load_matrix, doLLL=False, high_prec=high_prec)
        if verbose:
            print("Loaded file '%s'" % load_matrix)

    g6k = Siever(A, params, seed=seed)

    if trace:
        tracer = SieveTreeTracer(g6k,
                                 root_label=("svp-challenge", n),
                                 start_clocks=True)
    else:
        tracer = dummy_tracer

    gh = gaussian_heuristic([g6k.M.get_r(i, i) for i in range(n)])

    gamma = params.pop("gamma")

    if gamma is None:
        goal_r0 = (1.05**2) * gh
    else:
        goal_r0 = gamma**2 * gh

    if verbose:
        print("gh = %f, goal_r0/gh = %f, r0/gh = %f" %
              (gh, goal_r0 / gh, sum([x * x for x in A[0]]) / gh))

    flast = workout(g6k,
                    tracer,
                    0,
                    n,
                    goal_r0=goal_r0,
                    pump_params=pump_params,
                    **workout_params)
    if verbose:
        logger.info("sol %d, %s" % (n, A[0]))

    norm = sum([x * x for x in A[0]])
    if verbose:
        logger.info("norm %.1f ,hf %.5f" % (norm**.5, (norm / gh)**.5))

    tracer.exit()

    if hasattr(tracer, "trace"):
        stat = tracer.trace
        stat.data["flast"] = flast
        return stat
    else:
        return None
Exemple #17
0
def svp_kernel(arg0, params=None, seed=None):
    # Pool.map only supports a single parameter
    if params is None and seed is None:
        n, params, seed = arg0
    else:
        n = arg0

    params = copy.copy(params)
    load_matrix = params.pop("load_matrix")
    alg = params.pop("svp/alg")
    goal_r0 = 1.001 * params.pop('goal_r0')
    workout_params = pop_prefixed_params("workout/", params)
    pump_params = pop_prefixed_params("pump/", params)
    verbose = params.pop("verbose")
    if verbose and alg == "workout":
        workout_params["verbose"] = True

    A, bkz = load_matrix_file(load_matrix,
                              randomize=True,
                              seed=seed,
                              float_type="double")
    if verbose:
        print(("Loaded file '%s'" % load_matrix))
    g6k = Siever(A, params, seed=seed)
    tracer = SieveTreeTracer(g6k,
                             root_label=("svp-exact", n),
                             start_clocks=True)

    if alg == "enum":
        assert len(workout_params) + len(pump_params) == 0
        bkz_params = fplll_bkz.Param(block_size=n,
                                     max_loops=1,
                                     strategies=fplll_bkz.DEFAULT_STRATEGY,
                                     flags=fplll_bkz.GH_BND)
        svp_enum(bkz, bkz_params, goal_r0)
        flast = -1
    elif alg == "duc18":
        assert len(workout_params) + len(pump_params) == 0
        flast = ducas18(g6k, tracer, goal=goal_r0)
    elif alg == "workout":
        flast = workout(g6k,
                        tracer,
                        0,
                        n,
                        goal_r0=goal_r0,
                        pump_params=pump_params,
                        **workout_params)
    else:
        raise ValueError("Unrecognized algorithm for SVP")

    r0 = bkz.M.get_r(0, 0) if alg == "enum" else g6k.M.get_r(0, 0)
    if r0 > goal_r0:
        raise ValueError('Did not reach the goal')
    if 1.002 * r0 < goal_r0:
        raise ValueError(
            'Found a vector(%d) shorter than the goal(%d) for n=%d.' %
            (r0, goal_r0, n))

    if verbose:
        print("sol %d, %s" % (n, A[0]))

    tracer.exit()
    stat = tracer.trace
    stat.data["flast"] = flast
    tracer.trace.data['res'] = A

    return stat
def lwe_kernel(arg0, params=None, seed=None):
    """
    Run the primal attack against Darmstadt LWE instance (n, alpha).

    :param n: the dimension of the LWE-challenge secret
    :param params: parameters for LWE:

        - lwe/alpha: the noise rate of the LWE-challenge

        - lwe/m: the number of samples to use for the primal attack

        - lwe/goal_margin: accept anything that is
          goal_margin * estimate(length of embedded vector)
          as an lwe solution

        - lwe/svp_bkz_time_factor: if > 0, run a larger pump when
          svp_bkz_time_factor * time(BKZ tours so far) is expected
          to be enough time to find a solution

        - bkz/blocksizes: given as low:high:inc perform BKZ reduction
          with blocksizes in range(low, high, inc) (after some light)
          prereduction

        - bkz/tours: the number of tours to do for each blocksize

        - bkz/jump: the number of blocks to jump in a BKZ tour after
          each pump

        - bkz/extra_dim4free: lift to indices extra_dim4free earlier in
          the lattice than the currently sieved block

        - bkz/fpylll_crossover: use enumeration based BKZ from fpylll
          below this blocksize

        - bkz/dim4free_fun: in blocksize x, try f(x) dimensions for free,
          give as 'lambda x: f(x)', e.g. 'lambda x: 11.5 + 0.075*x'

        - pump/down_sieve: sieve after each insert in the pump-down
          phase of the pump

        - dummy_tracer: use a dummy tracer which captures less information

        - verbose: print information throughout the lwe challenge attempt

    """

    # Pool.map only supports a single parameter
    if params is None and seed is None:
        n, params, seed = arg0
    else:
        n = arg0

    params = copy.copy(params)

    # params for underlying BKZ
    extra_dim4free = params.pop("bkz/extra_dim4free")
    jump = params.pop("bkz/jump")
    dim4free_fun = params.pop("bkz/dim4free_fun")
    pump_params = pop_prefixed_params("pump", params)
    fpylll_crossover = params.pop("bkz/fpylll_crossover")
    blocksizes = params.pop("bkz/blocksizes")
    tours = params.pop("bkz/tours")

    # flow of the lwe solver
    svp_bkz_time_factor = params.pop("lwe/svp_bkz_time_factor")
    goal_margin = params.pop("lwe/goal_margin")

    # generation of lwe instance and Kannan's embedding
    alpha = params.pop("lwe/alpha")
    m = params.pop("lwe/m")
    decouple = svp_bkz_time_factor > 0

    # misc
    dont_trace = params.pop("dummy_tracer")
    verbose = params.pop("verbose")

    A, c, q = load_lwe_challenge(n=n, alpha=alpha)
    print "-------------------------"
    print "Primal attack, LWE challenge n=%d, alpha=%.4f" % (n, alpha)

    if m is None:
        try:
            min_cost_param = gsa_params(n=A.ncols, alpha=alpha, q=q,
                                        samples=A.nrows, decouple=decouple)
            (b, s, m) = min_cost_param
        except TypeError:
            raise TypeError("No winning parameters.")
    else:
        try:
            min_cost_param = gsa_params(n=A.ncols, alpha=alpha, q=q, samples=m,
                                        decouple=decouple)
            (b, s, _) = min_cost_param
        except TypeError:
            raise TypeError("No winning parameters.")
    print "Chose %d samples. Predict solution at bkz-%d + svp-%d" % (m, b, s)
    print

    target_norm = goal_margin * (alpha*q)**2 * m + 1

    if blocksizes is not None:
        blocksizes = range(10, 40) + eval("range(%s)" % re.sub(":", ",", blocksizes)) # noqa
    else:
        blocksizes = range(10, 50) + [b-20, b-17] + range(b - 14, b + 25, 2)

    B = primal_lattice_basis(A, c, q, m=m)

    g6k = Siever(B, params)
    print "GSO precision: ", g6k.M.float_type

    if dont_trace:
        tracer = dummy_tracer
    else:
        tracer = SieveTreeTracer(g6k, root_label=("lwe"), start_clocks=True)

    d = g6k.full_n
    g6k.lll(0, g6k.full_n)
    slope = basis_quality(g6k.M)["/"]
    print "Intial Slope = %.5f\n" % slope

    T0 = time.time()
    T0_BKZ = time.time()
    for blocksize in blocksizes:
        for tt in range(tours):
            # BKZ tours

            if blocksize < fpylll_crossover:
                if verbose:
                    print "Starting a fpylll BKZ-%d tour. " % (blocksize),
                    sys.stdout.flush()
                bkz = BKZReduction(g6k.M)
                par = fplll_bkz.Param(blocksize,
                                      strategies=fplll_bkz.DEFAULT_STRATEGY,
                                      max_loops=1)
                bkz(par)

            else:
                if verbose:
                    print "Starting a pnjBKZ-%d tour. " % (blocksize)

                pump_n_jump_bkz_tour(g6k, tracer, blocksize, jump=jump,
                                     verbose=verbose,
                                     extra_dim4free=extra_dim4free,
                                     dim4free_fun=dim4free_fun,
                                     goal_r0=target_norm,
                                     pump_params=pump_params)

            T_BKZ = time.time() - T0_BKZ

            if verbose:
                slope = basis_quality(g6k.M)["/"]
                fmt = "slope: %.5f, walltime: %.3f sec"
                print fmt % (slope, time.time() - T0)

            g6k.lll(0, g6k.full_n)

            if g6k.M.get_r(0, 0) <= target_norm:
                break

            # overdoing n_max would allocate too much memory, so we are careful
            svp_Tmax = svp_bkz_time_factor * T_BKZ
            n_max = int(58 + 2.85 * log(svp_Tmax * params.threads)/log(2.))

            rr = [g6k.M.get_r(i, i) for i in range(d)]
            for n_expected in range(2, d-2):
                x = (target_norm/goal_margin) * n_expected/(1.*d)
                if 4./3 * gaussian_heuristic(rr[d-n_expected:]) > x:
                    break

            print "Without otf, would expect solution at pump-%d. n_max=%d in the given time." % (n_expected, n_max) # noqa
            if n_expected >= n_max - 1:
                continue

            n_max += 1

            # Larger SVP

            llb = d - blocksize
            while gaussian_heuristic([g6k.M.get_r(i, i) for i in range(llb, d)]) < target_norm * (d - llb)/(1.*d): # noqa
                llb -= 1

            f = d-llb-n_max
            if verbose:
                print "Starting svp pump_{%d, %d, %d}, n_max = %d, Tmax= %.2f sec" % (llb, d-llb, f, n_max, svp_Tmax) # noqa
            pump(g6k, tracer, llb, d-llb, f, verbose=verbose,
                 goal_r0=target_norm * (d - llb)/(1.*d))

            if verbose:
                slope = basis_quality(g6k.M)["/"]
                fmt = "\n slope: %.5f, walltime: %.3f sec"
                print fmt % (slope, time.time() - T0)
                print

            g6k.lll(0, g6k.full_n)
            T0_BKZ = time.time()
            if g6k.M.get_r(0, 0) <= target_norm:
                break

        if g6k.M.get_r(0, 0) <= target_norm:
            print "Finished! TT=%.2f sec" % (time.time() - T0)
            print g6k.M.B[0]
            alpha_ = int(alpha*1000)
            filename = 'lwechallenge/%03d-%03d-solution.txt' % (n, alpha_)
            fn = open(filename, "w")
            fn.write(str(g6k.M.B[0]))
            fn.close()
            return

    raise ValueError("No solution found.")
Exemple #19
0
def ntru_kernel(arg0, params=None, seed=None):
    """
    Run the primal attack against Darmstadt LWE instance (n, alpha).

    :param n: the dimension of the LWE-challenge secret
    :param params: parameters for LWE:

        - lwe/alpha: the noise rate of the LWE-challenge

        - lwe/m: the number of samples to use for the primal attack

        - lwe/goal_margin: accept anything that is
          goal_margin * estimate(length of embedded vector)
          as an lwe solution

        - lwe/svp_bkz_time_factor: if > 0, run a larger pump when
          svp_bkz_time_factor * time(BKZ tours so far) is expected
          to be enough time to find a solution

        - bkz/blocksizes: given as low:high:inc perform BKZ reduction
          with blocksizes in range(low, high, inc) (after some light)
          prereduction

        - bkz/tours: the number of tours to do for each blocksize

        - bkz/jump: the number of blocks to jump in a BKZ tour after
          each pump

        - bkz/extra_dim4free: lift to indices extra_dim4free earlier in
          the lattice than the currently sieved block

        - bkz/fpylll_crossover: use enumeration based BKZ from fpylll
          below this blocksize

        - bkz/dim4free_fun: in blocksize x, try f(x) dimensions for free,
          give as 'lambda x: f(x)', e.g. 'lambda x: 11.5 + 0.075*x'

        - pump/down_sieve: sieve after each insert in the pump-down
          phase of the pump

        - dummy_tracer: use a dummy tracer which captures less information

        - verbose: print information throughout the lwe challenge attempt

    """

    # Pool.map only supports a single parameter
    if params is None and seed is None:
        n, params, seed = arg0
    else:
        n = arg0

    params = copy.copy(params)

    # params for underlying BKZ
    extra_dim4free = params.pop("bkz/extra_dim4free")
    jump = params.pop("bkz/jump")
    dim4free_fun = params.pop("bkz/dim4free_fun")
    pump_params = pop_prefixed_params("pump", params)
    fpylll_crossover = params.pop("bkz/fpylll_crossover")
    blocksizes = params.pop("bkz/blocksizes")
    tours = params.pop("bkz/tours")

    # flow of the lwe solver
    svp_bkz_time_factor = params.pop("lwe/svp_bkz_time_factor")
    goal_margin = params.pop("lwe/goal_margin")

    # generation of lwe instance and Kannan's embedding
    alpha = params.pop("lwe/alpha")
    m = params.pop("lwe/m")
    decouple = svp_bkz_time_factor > 0

    # misc
    dont_trace = params.pop("dummy_tracer")
    verbose = params.pop("verbose")

    filename = 'ntru_n_'+str(n)+'.txt'
    H, q = read_ntru_from_file(filename)

    print("-------------------------")
    print("Hybrid attack on NTRU n=%d" %n)


    # compute the attack parameters
    paramset_NTRU1 = {'n': n, 'q': q, 'w': 2*(n/3)}
    print(paramset_NTRU1)
    beta, g, rt = plain_hybrid_compleixty(paramset_NTRU1, verbose = True)

    B = ntru_plain_hybrid_basis(A, g, q, m=m)

    g6k = Siever(B, params)
    print("GSO precision: ", g6k.M.float_type)

    if dont_trace:
        tracer = dummy_tracer
    else:
        tracer = SieveTreeTracer(g6k, root_label=("ntru"), start_clocks=True)

    d = g6k.full_n
    g6k.lll(0, g6k.full_n)
    slope = basis_quality(g6k.M)["/"]
    print("Intial Slope = %.5f\n" % slope)

    T0 = time.time()
    T0_BKZ = time.time()
    for blocksize in blocksizes:
        for tt in range(tours):
            # BKZ tours

            if blocksize < fpylll_crossover:
                if verbose:
                    print("Starting a fpylll BKZ-%d tour. " % (blocksize), end=' ')
                    sys.stdout.flush()
                bkz = BKZReduction(g6k.M)
                par = fplll_bkz.Param(blocksize,
                                      strategies=fplll_bkz.DEFAULT_STRATEGY,
                                      max_loops=1)
                bkz(par)

            else:
                if verbose:
                    print("Starting a pnjBKZ-%d tour. " % (blocksize))

                pump_n_jump_bkz_tour(g6k, tracer, blocksize, jump=jump,
                                     verbose=verbose,
                                     extra_dim4free=extra_dim4free,
                                     dim4free_fun=dim4free_fun,
                                     goal_r0=target_norm,
                                     pump_params=pump_params)

            T_BKZ = time.time() - T0_BKZ

            if verbose:
                slope = basis_quality(g6k.M)["/"]
                fmt = "slope: %.5f, walltime: %.3f sec"
                print(fmt % (slope, time.time() - T0))

            g6k.lll(0, g6k.full_n)

            if g6k.M.get_r(0, 0) <= target_norm:
                break

            # overdoing n_max would allocate too much memory, so we are careful
            svp_Tmax = svp_bkz_time_factor * T_BKZ
            n_max = int(58 + 2.85 * log(svp_Tmax * params.threads)/log(2.))

            rr = [g6k.M.get_r(i, i) for i in range(d)]
            for n_expected in range(2, d-2):
                x = (target_norm/goal_margin) * n_expected/(1.*d)
                if 4./3 * gaussian_heuristic(rr[d-n_expected:]) > x:
                    break

            print("Without otf, would expect solution at pump-%d. n_max=%d in the given time." % (n_expected, n_max)) # noqa
            if n_expected >= n_max - 1:
                continue

            n_max += 1

            # Larger SVP

            llb = d - blocksize
            while gaussian_heuristic([g6k.M.get_r(i, i) for i in range(llb, d)]) < target_norm * (d - llb)/(1.*d): # noqa
                llb -= 1

            f = d-llb-n_max
            if verbose:
                print("Starting svp pump_{%d, %d, %d}, n_max = %d, Tmax= %.2f sec" % (llb, d-llb, f, n_max, svp_Tmax)) # noqa
            pump(g6k, tracer, llb, d-llb, f, verbose=verbose,
                 goal_r0=target_norm * (d - llb)/(1.*d))

            if verbose:
                slope = basis_quality(g6k.M)["/"]
                fmt = "\n slope: %.5f, walltime: %.3f sec"
                print(fmt % (slope, time.time() - T0))
                print()

            g6k.lll(0, g6k.full_n)
            T0_BKZ = time.time()
            if g6k.M.get_r(0, 0) <= target_norm:
                break

        if g6k.M.get_r(0, 0) <= target_norm:
            print("Finished! TT=%.2f sec" % (time.time() - T0))
            print(g6k.M.B[0])
            alpha_ = int(alpha*1000)
            filename = 'lwechallenge/%03d-%03d-solution.txt' % (n, alpha_)
            fn = open(filename, "w")
            fn.write(str(g6k.M.B[0]))
            fn.close()
            return
	"""
    raise ValueError("No solution found.")

def ntru():
    """
    Attempt to solve an ntru instance.

    """
    description = ntru.__doc__

    args, all_params = parse_args(description,
                                  ntru__m=None,
                                  lwe__goal_margin=1.5,
                                  lwe__svp_bkz_time_factor=1,
                                  bkz__blocksizes=None,
                                  bkz__tours=1,
                                  bkz__jump=1,
                                  bkz__extra_dim4free=12,
                                  bkz__fpylll_crossover=51,
                                  bkz__dim4free_fun="default_dim4free_fun",
                                  pump__down_sieve=True,
                                  dummy_tracer=True,  # set to control memory
                                  verbose=True
                                  )

    stats = run_all(ntru_kernel, list(all_params.values()), # noqa
                    lower_bound=args.lower_bound,
                    upper_bound=args.upper_bound,
                    step_size=args.step_size,
                    trials=args.trials,
                    workers=args.workers,
                    seed=args.seed)
Exemple #20
0
def test_bkz():
    for d in dimensions:
        A = make_integer_matrix(d)
        g6k = Siever(A)
        bkz(g6k, dummy_tracer, 20)