diff --git a/results/results_32_128.txt b/results/results_32_128.txt new file mode 100644 index 000000000..29b1df541 Binary files /dev/null and b/results/results_32_128.txt differ diff --git a/results/results_64_128.txt b/results/results_64_128.txt new file mode 100644 index 000000000..d07c54167 Binary files /dev/null and b/results/results_64_128.txt differ diff --git a/scripts.py b/scripts.py index d208a393a..1314e3559 100644 --- a/scripts.py +++ b/scripts.py @@ -233,21 +233,68 @@ def automated_param_select_n(sd, n=None, q=2 ** 32, reduction_cost_model=BKZ.sie # initial estimate, to determine if we are above or below the target security level - estimate = estimate_lwe(n, alpha, q, secret_distribution=secret_distribution, - reduction_cost_model=reduction_cost_model, m=oo, skip = {"bkw","dec","arora-gb","mitm"}) - security_level = get_security_level(estimate) - z = inequality(security_level, target_security) - - while z * security_level < z * target_security: + print("estimating for n = {}, q, sd".format(n)) + try: estimate = estimate_lwe(n, alpha, q, secret_distribution=secret_distribution, + reduction_cost_model=reduction_cost_model, m=oo, + skip={"bkw", "dec", "arora-gb", "mitm"}) + except Exception as e: + print(e) + estimate = estimate_lwe(n, alpha, q, secret_distribution=secret_distribution, + reduction_cost_model=reduction_cost_model, m=oo, + skip={"bkw", "dec", "arora-gb", "mitm", "dual"}) + print("the estimate is {}".format(estimate)) + security_level = get_security_level(estimate) + print("the security level is: {}".format(security_level)) + z = inequality(security_level, target_security) + print("the result of Z is{}".format(z)) + + while z * security_level < z * target_security and n > 80: + n += z * 8 + print("N = {}".format(n)) + print("SECURITY LEVEL = {}".format(security_level)) + alpha = sqrt(2 * pi) * sd / RR(q) + print("estimating for n = {}, q, sd".format(n)) + try: + estimate = estimate_lwe(n, alpha, q, secret_distribution=secret_distribution, reduction_cost_model=reduction_cost_model, m=oo, skip = {"bkw","dec","arora-gb","mitm"}) + except: + estimate = estimate_lwe(n, alpha, q, secret_distribution=secret_distribution, + reduction_cost_model=reduction_cost_model, m=oo, + skip={"bkw", "dec", "arora-gb", "mitm", "dual"}) security_level = get_security_level(estimate) - n += 1 + if (-1 * sd > log(q, 2)): + print("target security level is unatainable") + break - print("the finalised parameters are {}, {}, with a security level of {}".format(n, q, security_level)) + # final estimate (we went too far in the above loop) + if security_level < target_security: + n -= z * 8 + alpha = sqrt(2 * pi) * sd / RR(q) + print("N = {}".format(n)) + print("SECURITY LEVEL = {}".format(security_level)) + try: + estimate = estimate_lwe(n, alpha, q, secret_distribution=secret_distribution, + reduction_cost_model=reduction_cost_model, m=oo, skip = {"bkw","dec","arora-gb","mitm"}) + except: + estimate = estimate_lwe(n, alpha, q, secret_distribution=secret_distribution, + reduction_cost_model=reduction_cost_model, m=oo, + skip={"bkw", "dec", "arora-gb", "mitm", "dual"}) + security_level = get_security_level(estimate) + + print("the finalised parameters are n = {}, log2(sd) = {}, log2(q) = {}, with a security level of {}-bits".format(n, + sd, + log(q, + 2), + security_level)) + + # final sanity check so we don't return insecure (or inf) parameters + if security_level < target_security or security_level == oo: + n = None + + return n - return ZZ(n) def automated_param_select_sd(n, sd=None, q=2**32, reduction_cost_model=BKZ.sieve, secret_distribution=(0, 1), @@ -357,7 +404,7 @@ def generate_parameter_matrix(n_range, sd=None, q=2**32, reduction_cost_model=BK sd_ = sd - for n in range(n_min, n_max): + for n in range(n_min, n_max + 1): sd = automated_param_select_sd(n, sd=sd_, q=q, reduction_cost_model=reduction_cost_model, secret_distribution=secret_distribution, target_security=target_security) sd_ = sd @@ -366,6 +413,40 @@ def generate_parameter_matrix(n_range, sd=None, q=2**32, reduction_cost_model=BK return RESULTS +def generate_parameter_matrix_sd(sd_range, n=None, q=2**32, reduction_cost_model=BKZ.sieve, + secret_distribution=(0, 1), target_security=128): + """ + :param n_range: a tuple (n_min, n_max) giving the values of n for which to generate parameters + :param sd: the standard deviation of the LWE error + :param q: the LWE modulus (q = 2**32, 2**64 in TFHE) + :param reduction_cost_model: the BKZ cost model considered, BKZ.sieve is default + :param secret_distribution: the LWE secret distribution + :param target_security: the target number of bits of security, 128 is default + + TODO: we should probably parallelise this function for speed + TODO: code seems to fail when the initial estimate is < target_security bits + + EXAMPLE: + sage: X = generate_parameter_matrix([788, 790]) + sage: X + [(788, 4294967296, -20.0), (789, 4294967296, -20.0)] + """ + + RESULTS = [] + + # grab min and max value/s of n + (sd_min, sd_max) = sd_range + + n = n + + for sd in range(sd_min, sd_max + 1): + n = automated_param_select_n(sd, n=n, q=q, reduction_cost_model=reduction_cost_model, + secret_distribution=secret_distribution, target_security=target_security) + RESULTS.append((n, q, sd)) + + return RESULTS + + def generate_parameter_step(results, label = None, torus_sd = True): """ Plot results @@ -473,6 +554,7 @@ def test_params(n, q, sd, secret_distribution): return est + def generate_iso_lines(N = [256, 2048], SD = [0, 32], q = 2**32): RESULTS = [] @@ -491,6 +573,7 @@ def generate_iso_lines(N = [256, 2048], SD = [0, 32], q = 2**32): return RESULTS + def plot_iso_lines(results): x1 = [] @@ -529,10 +612,133 @@ def test_multiple_sd(n, q, secret_distribution, reduction_cost_model, split = 33 return est, Y -def estimate_lwe_sd(n, sd, q, secret_distribution, reduction_cost_model, skip = ("bkw","mitm","dec","arora-gb"), m = oo): +def output_secret_distribution(m): + """ + generate the correct secret_distirbution for the given input + :param m: the number of elements in the secret distribution + """ - alpha = sqrt(2*pi) * sd/q - x = estimate_lwe(n = n, alpha = alpha , q = q, m = m, secret_distribution = secret_distribution, reduction_cost_model = reduction_cost_model, skip = skip) + # the code doesn't work for m < 2 + assert m >= 2 - return x + if m % 2 ==1: + # m is odd + b = (m - 1)/2 + secret_distribution = (-b, b) + else: + # m is even + b = m / 2 - 1 + secret_distribution = (-b, b + 1) + return secret_distribution + +def get_marcs_curves(n_range, q, m_max): + + # the final result will be a list of m_max elements, each containing + # a parameter matrix + RESULTS = [] + + for m in range(2, m_max + 1): + secret_distribution = output_secret_distribution(m) + result_m = generate_parameter_matrix(n_range, sd=None, q=q, reduction_cost_model=BKZ.sieve, + secret_distribution=secret_distribution, target_security=128) + RESULTS.append(result_m) + return RESULTS + + +def get_marcs_curves_n(sd_range, q, m_max): + + # the final result will be a list of m_max elements, each containing + # a parameter matrix + RESULTS = [] + + for m in range(2, m_max + 1): + secret_distribution = output_secret_distribution(m) + result_m = generate_parameter_matrix_sd(n = None, sd_range=sd_range, q=q, reduction_cost_model=BKZ.sieve, + secret_distribution=secret_distribution, target_security=128) + RESULTS.append(result_m) + return RESULTS + + +def tabulate_results(results): + """ Put the results from get_marcs_curves into a LaTeX table + """ + + new_results = [] + num_results = len(results[0]) + num_entries = len(results) + + key = [] + key.append("n") + key.append("q") + for i in range(num_entries): + key.append("m = {}".format(i + 2)) + + new_results.append(key) + + + + + for j in range(num_results): + result_j = [] + result_j.append(results[0][j][0]) + result_j.append(int(log(results[0][0][1],2))) + + for i in range(num_entries): + result_j.append(int(results[i][j][2])) + + new_results.append(result_j) + + return new_results + +def tabulate_results_sd(results): + + new_results = [] + num_results = len(results[0]) + num_entries = len(results) + + key = [] + key.append("sd") + key.append("q") + + for i in range(num_entries): + key.append("m = {}".format(i + 2)) + + new_results.append(key) + + for j in range(num_results): + result_j = [] + result_j.append(results[0][j][2]) + result_j.append(int(log(results[0][0][1],2))) + + for i in range(num_entries): + try: + result_j.append(int(results[i][j][0])) + except: + result_j.append(str(results[i][j][0])) + + new_results.append(result_j) + + return new_results + +# code to cross-check the security levels for marc/pascal results +# sage: with open("results_32_128.txt", "rb") as fp: # Unpickling +# ....: ... X = pickle.load(fp) +# res = [] +# sage: for i in range(len(X)): +# ....: x = X[i] +# ....: m = i + 2 +# ....: secret_distribution = output_secret_distribution(m) +# ....: for (n, q, sd) in x: +# ....: if n is not None: +# ....: sd = 2**(sd) +# ....: alpha = sqrt(2*pi) * sd +# ....: print((n, q, sd)) +# ....: try: +# ....: _ = estimate_lwe(n, alpha, q, secret_distribution = secret_distribution, reduction_cost_model = BKZ.sieve, skip = ("arora-gb", "mitm", "bkw", "dec")) +# ....: except: +# ....: _ = estimate_lwe(n, alpha, q, secret_distribution = secret_distribution, reduction_cost_model = BKZ.sieve, skip = ("arora-gb", "mitm", "bkw", "dec", "dual")) +# ....: else: +# ....: print("None") +# ....: res.append(get_security_level(_)) +# ....:print(min(res)) \ No newline at end of file