Skip to content

Commit 2915313

Browse files
committed
added a script that runs the lwe-estimator
1 parent 66e1959 commit 2915313

File tree

2 files changed

+119
-0
lines changed

2 files changed

+119
-0
lines changed

misc/README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ suited place in the codebase.
1111
The majority of files contained in `misc` are old code and tests, however some
1212
files and directories of note are
1313

14+
### `estimator`
15+
A script that runs the lwe-estimator (https://bitbucket.org/malb/lwe-estimator) and provides approximations of it via linear functions
16+
1417
### `params1a`
1518
An experimental program used to generate various BGV parameters. This version
1619
only generates `m`s that are products of distinct prime powers.

misc/estimator/lwe-estimator.sage

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
# bootstrapping-lwe-estimator.sage
2+
#
3+
# A script that uses the lwe-estimator to estimate the security levels
4+
# for various bootstrapping parameters. This file prints the results
5+
# to stdout in CSV format, where the columns are:
6+
# m, n, |q|, X=n/log2(1/alpha), Y=security
7+
#
8+
# The script also print *to stderr* the linear regression line for
9+
# all the X,Y values.
10+
#
11+
# The bootsrapping parameters are specified by the ms, ns, and qs
12+
# lists below, where n[i]=phi(m[i]) and q[i] is the bit-length of
13+
# the modulus in the key-switching matrices, namely
14+
# |q| = log2(ctxtPrimes)+log2(specialPrimes).
15+
16+
import sys
17+
import itertools as it
18+
19+
print("Usage: sage", sys.argv[0], "[HammingWeight]\n")
20+
print(" if HammingWeight is not supplied, will use [120,150,180,...,480]")
21+
print(" and dense keys. If HammingWeight='dense' only dense keys are used.\n")
22+
print(" Data is saved in lwe-estimate-<weight>.csv files, and plots")
23+
print(" of the data are saved in lwe-estplot-<weight>.pdf files.")
24+
25+
if len(sys.argv) > 1:
26+
if sys.argv[1].isnumeric() and int(sys.argv[1])>0:
27+
weights = [int(sys.argv[1])]
28+
else:
29+
weights = ['dense']
30+
else:
31+
weights=[120]
32+
# weights=range(120,500,30)
33+
34+
# We have the two estimates sec = 3.8*x -15 and sec=2.53*x +19,
35+
# for dense and sparse(120), respectively, where
36+
# x = n/log_2(1/alpha) = n/log_2(sigma*sqrt(2 pi)/q).
37+
# n/x = log_2(1/alpha) = log_2(q) -log_2(sigma*sqrt(2 pi))
38+
# q = 2^{n/x} * sigma*sqrt(2 pi)
39+
#
40+
# To set the range of |q| values on which to run the estimator, we aim
41+
# at security roughly between 80 and 256, so we roughly parameters that
42+
# give x values between 20 and 80.
43+
44+
# Load the estimator (change the location if it is stored elesewhere)
45+
# load("https://bitbucket.org/malb/lwe-estimator/raw/HEAD/estimator.py")
46+
load("~/opt/lwe-estimator/estimator.py")
47+
48+
# Disable information printouts from the estimator
49+
logging.getLogger("estimator").setLevel(logging.WARNING)
50+
51+
# Remove all the tests except "usvp" and "dual"
52+
toskip=("mitm", "arora-gb", "bkw", "dec")
53+
54+
def estimate_hw(hw):
55+
data = []
56+
minX = 100000
57+
maxX = 0
58+
csvfile = open("lwe-estimate-"+str(hw)+".csv", "w")
59+
print("n,|q|,log2(1/alpha),x=n/log2(1/alpha),security ("+str(hw)+")", file=csvfile)
60+
for n in range(2049, 30000, 2048):
61+
# some data points with sigma*sqrt(2\pi)=8, others with 8*sqrt(n)
62+
fromLogq = int(round(n/80, 0))
63+
toLogq = int(round(n/20, 0))
64+
# Use more q's at the lower range (=higher-security)
65+
qs = it.chain(range(fromLogq+5,fromLogq+50,10),range(fromLogq,toLogq,50))
66+
for logQ in qs:
67+
q = sage.rings.all.RR(2^logQ) +1
68+
for s2p in [8.0, 8.0*math.sqrt(n)]:
69+
alpha = s2p/sage.rings.all.RR(q)
70+
71+
# run the estimator to get the complexity of "usvp" and "dual" attacks
72+
if isinstance(hw, int):
73+
dist=((-1,1),hw) # sparse weight-hw
74+
else:
75+
dist=(-1,1) # dense in {-1,0,1}
76+
77+
est = estimate_lwe(n, alpha, q, reduction_cost_model=BKZ.sieve,secret_distribution=dist,skip=toskip)
78+
79+
# FIXME: can we always assume that "usvp" and "dual" will be there?
80+
sec = min(math.log2(est["usvp"]["rop"]), math.log2(est["dual"]["rop"]))
81+
if sec < 70 or sec > 270:
82+
continue;
83+
84+
# record n/log2(1/alpha) and the security
85+
loga = -log(alpha)/log(2.0)
86+
xx = n / loga
87+
if xx < minX:
88+
minX = xx
89+
if xx > maxX:
90+
maxX = xx
91+
data.append([xx,sec])
92+
93+
# print one line of the CSV file
94+
print(str(n)+','+str(logQ)+','+str(round(loga,1))+','+str(round(xx,1))+','+str(round(sec,1)), file=csvfile)
95+
96+
csvfile.close()
97+
98+
# Fit the data points to an affine line
99+
var('a,b')
100+
model(x)=a*x+b
101+
line=find_fit(data,model,solution_dict=True)
102+
103+
# Plot it so you can see that it makes sense
104+
title = str(hw)+": sec = "+str(round(line[a],1))+"X + "+str(round(line[b],1))
105+
p=points(data)+plot(model(a=line[a],b=line[b]),(x,minX,maxX),color='black',title=title)
106+
p.save('lwe-estplot-'+str(hw)+'.pdf')
107+
108+
# Also print it to the terminal
109+
print(title)
110+
111+
112+
for hw in weights:
113+
estimate_hw(hw)
114+
115+
if len(sys.argv) < 2: # no HW argument, estimate dense as well
116+
estimate_hw('dense')

0 commit comments

Comments
 (0)