├── README.md
├── LICENSE
├── proving_mlwe_sample.sage
├── ver_enc_param_set_2.sage
├── ver_enc_param_set_1.sage
└── group_signature.sage
/README.md:
--------------------------------------------------------------------------------
1 | # Lattice-Based Zero-Knowledge Proofs and Applications: Shorter, Simpler, and More General
2 |
3 | We provide SAGE [SAGE] scripts which compute parameters for examples specified in [LyuNguPla22]:
4 | * Proving Knowledge of a Module-LWE Secret (Section 6.2) -- proving_mlwe_sample.sage
5 | * Verifiable Encryption (Section 6.3), parameter set I -- ver_enc_param_set_1.sage
6 | * Verifiable Encryption (Section 6.3), parameter set II -- ver_enc_param_set_2.sage
7 | * Group Signature (Section 6.4) -- group_signature.sage
8 |
9 | References:
10 | [LyuNguPla22] Lattice-Based Zero-Knowledge Proofs and Applications: Shorter, Simpler, and More General.
11 | Vadim Lyubashevsky, Ngoc Khanh Nguyen, Maxime Plancon. https://eprint.iacr.org/2022/284
12 | [SAGE] https://www.sagemath.org/
13 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 khalvador
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/proving_mlwe_sample.sage:
--------------------------------------------------------------------------------
1 | # This is the script for computing the non-interactive proof size
2 | # of proving knowledge of a MLWE sample described in Section 6.2.
3 | # Concretely, we want to prove knowledge of a vector s such that
4 | # norm of ||(s,As-u)|| is at most B.
5 |
6 |
7 | # Function for estimating the MSIS hardness given parameters:
8 | # a (n x m) matrix in \Rq along with the solution bound B. It returns the
9 | # root Hermite factor \delta. We use the methodology presented by
10 | # [GamNgu08, Mic08] and hence m is irrelevant.
11 |
12 | def findMSISdelta(B, n, d, logq):
13 | logC = log(B, 2)
14 | logdelta = logC^2 / (4*n*d*logq)
15 | return 2^logdelta
16 |
17 | # Function for estimating the MLWE hardness for a (m x n) matrix in \Rq and
18 | # secret coefficients sampled uniformly at random between -nu and nu.
19 | # We use the LWE-Estimator by [AlbPlaSco15] as a black-box.
20 |
21 | def findMLWEdelta(nu, n, d, logq):
22 | load("https://bitbucket.org/malb/lwe-estimator/raw/HEAD/estimator.py")
23 | n = n * d
24 | q = 2^logq
25 | stddev = sqrt(((2*nu+1)^2 - 1)/12)
26 | alpha = alphaf(sigmaf(stddev),q)
27 | set_verbose(1)
28 | L = estimate_lwe(n, alpha, q, reduction_cost_model=BKZ.enum)
29 | delta_enum1 = L['usvp']['delta_0']
30 | delta_enum2 = L['dec']['delta_0']
31 | delta_enum3 = L['dual']['delta_0']
32 | L = estimate_lwe(n, alpha, q, reduction_cost_model=BKZ.sieve)
33 | delta_sieve1 = L['usvp']['delta_0']
34 | delta_sieve2 = L['dec']['delta_0']
35 | delta_sieve3 = L['dual']['delta_0']
36 | return max(delta_enum1,delta_enum2,delta_enum3,delta_sieve1,delta_sieve2,delta_sieve3)
37 |
38 |
39 |
40 |
41 | # Security parameter, ring dimension of \R and challenge space
42 | secpam = 128 # security parameter
43 | d = 128 # dimension of R = Z[X]/(X^d + 1)
44 | l = 2 # number of irreducible factors of X^d + 1 modulo each q_i, we assume each q_i = 2l+1 (mod 4l)
45 | kappa = 2 # maximum coefficient of a challenge. We want |\chal| = (2*kappa+1)^(d/2) >= 2^secpam
46 | eta = 59 # the heuristic bound on \sqrt[2k](|| \sigma_{-1}(c^k)*c^k ||_1) for k = 32
47 |
48 | # Defining the log of the proof system modulus -- finding true values will come later
49 | nbofdiv = 1 # number of prime divisors of q, usually 1 or 2
50 | logq1 = 32 # log of the smallest prime divisor of q
51 | logq = 32 # log of the proof system modulus q
52 | lmbda = 2 * ceil( secpam/(2*logq1) ) # number of repetitions for boosting soundness, we assume lambda is even
53 |
54 | # Length and size of the committed messages
55 | m1 = 8 # length of s1
56 | m2 = 0 # length of s2, to be determined
57 | ell = 0 # length of m
58 | alpha = sqrt(1024) # norm of s1
59 |
60 | # Parameters for proving norm bounds
61 | ve = 1 # number of exact norm proofs
62 | BoundsToProve = [sqrt(2048)] # exact bounds beta_i to prove for i=1,2,...,ve
63 | k_bin = 0 # length of a vector to prove binary coefficients
64 | alphae = sqrt(2048 + ve*d) # bound alpha^(e) on the vector e^(e) = (s,As - u, bin. decomp. of B^2 - ||(s,As-u)||^2)
65 | ce = 16 + ve # length of the vector e^(e)
66 | approximate_norm_proof = 0 # boolean to indicate if we perform approximate norm proofs
67 | alphad = 1 # bound alpha^(d) on the vector e^(d), we set it to be 1 if the boolean is zero
68 |
69 | # Parameters for rejection sampling
70 | gamma1 = 19 # rejection sampling for s1
71 | gamma2 = 2 # rejection sampling for s2
72 | gammae = 2 # rejection sampling for Rs^(e)
73 | gammad = 1 # rejection sampling for R's^(d) -- ignore if approximate_norm_proof = 0
74 |
75 | # Setting the standard deviations, apart from stdev2
76 | stdev1 = gamma1 * eta * sqrt(alpha^2 + ve *d)
77 | stdev2 = 0
78 | stdeve = gammae * sqrt(337) * alphae
79 | stdevd = gammad * sqrt(337) * alphad
80 |
81 | # Finding MLWE dimension
82 | print("Computing the Module-LWE dimension...")
83 | nu = 1 # randomness vector s2 with coefficients between -nu and nu
84 | mlwe = 9 # dimension of the Module-LWE problem
85 | mlwe_hardness = 2
86 | while mlwe_hardness > 1.0045: # increasing the mlwe dimension until MLWE provides ~ 128-bit security
87 | mlwe += 1
88 | mlwe_hardness = findMLWEdelta(nu,mlwe,d, logq)
89 |
90 |
91 |
92 |
93 | # Finding an appropriate Module-SIS dimension n
94 | print("Computing the Module-SIS dimension...")
95 | n = 0 # dimension of the Module-SIS problem
96 | D = 0 # dropping low-order bits of t_A
97 | gamma = 0 # dropping low-order bits of w
98 | value_n_found = false # Boolean for finding n
99 | while value_n_found == false: # searching for n
100 | n += 1
101 | m2 = mlwe + n + ell + lmbda/2 + 256/d + 1 + approximate_norm_proof * 256/d + 1 # we use the packing optimisation from Section 5.3
102 | stdev2 = gamma2 * eta * nu * sqrt(m2 * d) # set stdev2 with the current candidate for n
103 | Bound1 = 2 * stdev1 * sqrt(2 * (m1 + ve) * d) # bound on bar{z}_1
104 | Bound2 = 2 * stdev2 * sqrt(2 * m2 * d) + 2^D * eta * sqrt(n*d) + gamma * sqrt(n*d) # bound on bar{z}_2 = (bar{z}_{2,1},bar{z}_{2,2})
105 | Bound = 4 * eta * sqrt(Bound1^2 + Bound2^2) # bound on the extracted MSIS solution
106 | if findMSISdelta(Bound,n,d,logq) < 1.0045 and Bound < 2^logq: # until we reach ~ 128-bit security
107 | value_n_found = true # it is secure
108 |
109 |
110 |
111 |
112 | # Given n, find the largest possible gamma which makes the MSIS solution still small
113 | print("Computing the parameter gamma...")
114 | gamma = 2^logq # initialisation
115 | value_gamma_found = false # Boolean for finding gamma
116 | while value_gamma_found == false: # searching for right gamma
117 | gamma /= 2 # decrease the value of gamma
118 | Bound1 = 2 * stdev1 * sqrt(2 * (m1 + ve) * d) # bound on bar{z}_1
119 | Bound2 = 2 * stdev2 * sqrt(2 * m2 * d) + 2^D * eta * sqrt(n*d) + gamma * sqrt(n*d) # bound on bar{z}_2
120 | Bound = 4 * eta * sqrt(Bound1^2 + Bound2^2) # bound on the extracted MSIS solution
121 | if findMSISdelta(Bound,n,d,logq) < 1.0045 and Bound < 2^logq: # until we reach ~ 128-bit security
122 | value_gamma_found = true # it is secure
123 |
124 |
125 | # Finding exact values for q, q1 and gamma:
126 | print("Computing moduli q1, q etc. ...")
127 | true_gamma_found = false # Boolean for finding correct gamma
128 | q1 = 2^(logq1) + (2*l + 1) # we need q1 to be congruent to 2l+1 modulo 4l
129 | while true_gamma_found == false:
130 | q1 = q1 - 4*l # find the next candidate for q1
131 | while is_prime(q1) == False : # we need q1 to be prime
132 | q1 -= 4*l
133 | if nbofdiv == 1: # if number of divisors of q is 1, then q = q1
134 | q = q1
135 | else:
136 | q2 = 4*l * int(2^(logq)/(4*l*q1)) + 2*l + 1 # we need q2 to be congruent to 2l+1 modulo 4l
137 | while is_prime(q2) == False : # we need q2 to be prime
138 | q2 -= 4*l
139 | q = q1 * q2 # if number of divisors of q is 2, then q = q1*q2
140 | Div_q = divisors(q-1) # consider divisors of q-1
141 | for i in Div_q:
142 | if gamma*4/5 < i and i <= gamma and is_even(i): # find a divisor which is close to gamma
143 | gamma = i # we found a good candidate for gamma
144 | true_gamma_found = true
145 |
146 |
147 | # Given n and gamma, find the largest possible D which makes the MSIS solution small
148 | print("Computing the parameter D...")
149 | D = logq # initialisation
150 | value_D_found = false # Boolean for finding D
151 | while value_D_found == false: # searching for right D
152 | D -= 1 # decrease the value of D
153 | Bound1 = 2 * stdev1 * sqrt(2 * (m1 + ve) * d) # bound on bar{z}_1
154 | Bound2 = 2 * stdev2 * sqrt(2 * m2 * d) + 2^D * eta * sqrt(n*d) + gamma * sqrt(n*d) # bound on bar{z}_2
155 | Bound = 4 * eta * sqrt(Bound1^2 + Bound2^2) # bound on the extracted MSIS solution
156 | if findMSISdelta(Bound,n,d,logq) < 1.0045 and Bound < 2^logq and 2^(D-1)*kappa*d < gamma: # until we reach ~ 128-bit security
157 | value_D_found = true # it is secure
158 |
159 |
160 |
161 | # Checking knowledge soundness conditions from Theorem 5.3
162 | print("Checking knowledge soundness conditions...")
163 | t = 1.64
164 | Be = 2 * sqrt(256/26) * t * stdeve
165 |
166 | if q < 41 * ce * d * Be:
167 | print("ERROR: can't use Lemma 2.9")
168 |
169 | if q <= Be^2 + Be*sqrt(k_bin*d):
170 | print("ERROR: can't prove E_bin*s + v_bin has binary coefficients")
171 |
172 | if q <= Be^2 + Be*sqrt(ve*d):
173 | print("ERROR: can't prove all x_i have binary coefficients")
174 |
175 | for bound in BoundsToProve:
176 | if q <= 3 * bound^2 + Be^2:
177 | print("ERROR: can't prove || E_i*s - v_i || <= beta_i")
178 |
179 |
180 |
181 | # Output computed parameters
182 | print("---------- computed parameters ----------")
183 | print("The smallest prime divisor q1 of q: ", q1)
184 | print("Proof system modulus q: ", q)
185 | print("Parameter gamma for dropping low-order bits of w: ", gamma)
186 | print("Parameter D for dropping low-order bits of t_A : ", D)
187 | print("Module-SIS dimension: ", n)
188 | print("Module-LWE dimension: ", mlwe)
189 | print("Length of the randomness vector s2: ", m2)
190 | print("Log2 of the standard deviation stdev1: ",round(log(stdev1,2),2))
191 | print("Log2 of the standard deviation stdev2: ",round(log(stdev2,2),2))
192 | print("Log2 of the standard deviation stdeve: ",round(log(stdeve,2),2))
193 |
194 |
195 | # Output security analysis
196 | print("---------- security analysis ------------")
197 |
198 | # Repetition rate
199 | rep_rate = 2*exp(14/gamma1 + 1/(2*gamma1^2)) * exp(1/(2*gamma2^2)) * exp(1/(2*gammae^2)) * ((1-approximate_norm_proof) + approximate_norm_proof*exp(1/(2*gammad^2)))
200 | print("Repetition rate: ", round(rep_rate ,2 ))
201 |
202 | # Knowledge soundness error from Theorem 5.3
203 | soundness_error = 2 * 1/(2*kappa+1)^(d/2) + q1^(-d/l) + q1^(-lmbda) + 2^(-128) + approximate_norm_proof*2^(-256)
204 | print("Log of the knowledge soundness error: ", ceil(log(soundness_error, 2)) )
205 |
206 | # Exact Module-SIS and Module-LWE hardness
207 | Bound1 = 2 * stdev1 * sqrt(2 * (m1 + ve) * d)
208 | Bound2 = 2 * stdev2 * sqrt(2 * m2 * d) + 2^D * eta * sqrt(n*d) + gamma * sqrt(n*d)
209 | Bound = 4 * eta * sqrt(Bound1^2 + Bound2^2)
210 | print("Root Hermite factor for MSIS: ", round( findMSISdelta(Bound,n,d,logq) ,6))
211 | print("Root Hermite factor for MLWE: ", round(mlwe_hardness,6))
212 |
213 |
214 |
215 | # Proof size
216 | print("---------- proof size -------------------")
217 | full_size = n * d * (logq - D) + (ell + 256/d + 1 + approximate_norm_proof * 256/d + lmbda + 1) * d * logq
218 | challenge = ceil(log(2*kappa+1,2)) * d
219 | short_size1 = (m1 + ve) * d * (ceil(log(stdev1,2) + 2.57)) + (m2 - n) * d * (ceil(log(stdev2,2) + 2.57))
220 | short_size2 = 256 * (ceil(log(stdeve,2) + 2.57)) + approximate_norm_proof * 256 * (ceil(log(stdevd,2) + 2.57))
221 | hint = 2.25 * n * d
222 |
223 | print("Total proof size in KB: ", round((full_size + challenge + short_size1 + short_size2 + hint)/(2^13) , 2))
224 | print("full-sized polynomials in KB: ", round(full_size/(2^13) , 2))
225 | print("challenge c in KB: ", round(challenge/(2^13) , 2))
226 | print("short-sized polynomials in KB: ", round((short_size1 + short_size2 + hint)/(2^13) , 2))
--------------------------------------------------------------------------------
/ver_enc_param_set_2.sage:
--------------------------------------------------------------------------------
1 | # This is the script for computing the non-interactive proof size
2 | # for verifiable encryption in Section 6.3 for prime p which divides q.
3 | # We apply the strategy as in Section 6.2, i.e. we write the matrix A = [A' I]
4 | # and only commit to the randomness part r multiplied by A.
5 |
6 | # Function for estimating the MSIS hardness given parameters:
7 | # a (n x m) matrix in \Rq along with the solution bound B. It returns the
8 | # root Hermite factor \delta. We use the methodology presented by
9 | # [GamNgu08, Mic08] and hence m is irrelevant.
10 |
11 | def findMSISdelta(B, n, d, logq):
12 | logC = log(B, 2)
13 | logdelta = logC^2 / (4*n*d*logq)
14 | return 2^logdelta
15 |
16 | # Function for estimating the MLWE hardness for a (m x n) matrix in \Rq and
17 | # secret coefficients sampled uniformly at random between -nu and nu.
18 | # We use the LWE-Estimator by [AlbPlaSco15] as a black-box.
19 |
20 | def findMLWEdelta(nu, n, d, logq):
21 | load("https://bitbucket.org/malb/lwe-estimator/raw/HEAD/estimator.py")
22 | n = n * d
23 | q = 2^logq
24 | stddev = sqrt(((2*nu+1)^2 - 1)/12)
25 | alpha = alphaf(sigmaf(stddev),q)
26 | set_verbose(1)
27 | L = estimate_lwe(n, alpha, q, reduction_cost_model=BKZ.enum)
28 | delta_enum1 = L['usvp']['delta_0']
29 | delta_enum2 = L['dec']['delta_0']
30 | delta_enum3 = L['dual']['delta_0']
31 | L = estimate_lwe(n, alpha, q, reduction_cost_model=BKZ.sieve)
32 | delta_sieve1 = L['usvp']['delta_0']
33 | delta_sieve2 = L['dec']['delta_0']
34 | delta_sieve3 = L['dual']['delta_0']
35 | return max(delta_enum1,delta_enum2,delta_enum3,delta_sieve1,delta_sieve2,delta_sieve3)
36 |
37 | # Parameters for the encryption scheme
38 | logp = 12 # Log of the prime for encryption scheme
39 | N = 4 # height of the matrix A
40 | K = 9 # width of the matrix A
41 | rand_coeff = 2 # coefficients of the randomness vectors, between -rand_coeff and rand_coeff
42 |
43 | # Security parameter, ring dimension of \R and challenge space
44 | secpam = 128 # security parameter
45 | d = 128 # dimension of R = Z[X]/(X^d + 1)
46 | l = 2 # number of irreducible factors of X^d + 1 modulo each q_i, we assume each q_i = 2l+1 (mod 4l)
47 | kappa = 2 # maximum coefficient of a challenge. We want |\chal| = (2*kappa+1)^(d/2) >= 2^secpam
48 | eta = 59 # the heuristic bound on \sqrt[2k](|| \sigma_{-1}(c^k)*c^k ||_1) for k = 32
49 |
50 | # Defining the log of the proof system modulus -- finding true values will come later
51 | nbofdiv = 2 # number of prime divisors of q, usually 1 or 2
52 | logq1 = logp # log of the smallest prime divisor of q, we want to have a prime close to 3329
53 | logq = 31 # log of the proof system modulus q
54 | lmbda = 2 * ceil( secpam/(2*logq1) ) # number of repetitions for boosting soundness, we assume lambda is even
55 |
56 | # Length and size of the committed messages
57 | m1 = K - N + 1 # length of s1 = (randomness of length K - N = 5, message)
58 | m2 = 0 # length of s2, to be determined
59 | ell = 0 # length of m
60 | alpha = sqrt(rand_coeff^2*(K-N)*d + d) # norm of s1
61 |
62 | # Parameters for proving norm bounds
63 | ve = 1 # number of exact norm proofs
64 | BoundsToProve = [ rand_coeff*sqrt(K*d) ] # exact bounds beta_i to prove for i=1,2,...,ve
65 | k_bin = 1 # length of a vector to prove binary coefficients
66 | alphae = sqrt(rand_coeff^2*K*d + (k_bin + ve)*d)# bound alpha^(e) on the vector e^(e) = (r,m, bin. decomp. of B^2 - ||r||^2)
67 | ce = K + k_bin + ve # length of the vector e^(e)
68 | approximate_norm_proof = 0 # boolean to indicate if we perform approximate norm proofs
69 | alphad = 1 # bound alpha^(d) on the vector e^(d), we set it to be 1 if the boolean is zero
70 |
71 | # Parameters for rejection sampling
72 | gamma1 = 16 # rejection sampling for s1
73 | gamma2 = 1.5 # rejection sampling for s2
74 | gammae = 1.8 # rejection sampling for Rs^(e)
75 | gammad = 1 # rejection sampling for R's^(d) -- ignore if approximate_norm_proof = 0
76 |
77 | # Setting the standard deviations, apart from stdev2
78 | stdev1 = gamma1 * eta * sqrt(alpha^2 + ve * d)
79 | stdev2 = 0
80 | stdeve = gammae * sqrt(337) * alphae
81 | stdevd = gammad * sqrt(337) * alphad
82 |
83 | # Finding MLWE dimension
84 | print("Computing the Module-LWE dimension...")
85 | nu = 1 # randomness vector s2 with coefficients between -nu and nu
86 | mlwe = 0 # dimension of the Module-LWE problem
87 | mlwe_hardness = 2
88 | while mlwe_hardness > 1.0045: # increasing the mlwe dimension until MLWE provides ~ 128-bit security
89 | mlwe += 1
90 | mlwe_hardness = findMLWEdelta(nu,mlwe,d, logq)
91 |
92 |
93 |
94 |
95 | # Finding an appropriate Module-SIS dimension n
96 | print("Computing the Module-SIS dimension...")
97 | n = 0 # dimension of the Module-SIS problem
98 | D = 0 # dropping low-order bits of t_A
99 | gamma = 0 # dropping low-order bits of w
100 | value_n_found = false # Boolean for finding n
101 | while value_n_found == false: # searching for n
102 | n += 1
103 | m2 = mlwe + n + ell + lmbda/2 + 256/d + 1 + approximate_norm_proof * 256/d + 1 # we use the packing optimisation from Section 5.3
104 | stdev2 = gamma2 * eta * nu * sqrt(m2 * d) # set stdev2 with the current candidate for n
105 | Bound1 = 2 * stdev1 * sqrt(2 * (m1 + ve) * d) # bound on bar{z}_1
106 | Bound2 = 2 * stdev2 * sqrt(2 * m2 * d) + 2^D * eta * sqrt(n*d) + gamma * sqrt(n*d) # bound on bar{z}_2 = (bar{z}_{2,1},bar{z}_{2,2})
107 | Bound = 4 * eta * sqrt(Bound1^2 + Bound2^2) # bound on the extracted MSIS solution
108 | if findMSISdelta(Bound,n,d,logq) < 1.0045 and Bound < 2^logq: # until we reach ~ 128-bit security
109 | value_n_found = true # it is secure
110 |
111 |
112 |
113 |
114 | # Given n, find the largest possible gamma which makes the MSIS solution still small
115 | print("Computing the parameter gamma...")
116 | gamma = 2^logq # initialisation
117 | value_gamma_found = false # Boolean for finding gamma
118 | while value_gamma_found == false: # searching for right gamma
119 | gamma /= 2 # decrease the value of gamma
120 | Bound1 = 2 * stdev1 * sqrt(2 * (m1 + ve) * d) # bound on bar{z}_1
121 | Bound2 = 2 * stdev2 * sqrt(2 * m2 * d) + 2^D * eta * sqrt(n*d) + gamma * sqrt(n*d) # bound on bar{z}_2
122 | Bound = 4 * eta * sqrt(Bound1^2 + Bound2^2) # bound on the extracted MSIS solution
123 | if findMSISdelta(Bound,n,d,logq) < 1.0045 and Bound < 2^logq: # until we reach ~ 128-bit security
124 | value_gamma_found = true # it is secure
125 |
126 |
127 | # Finding exact values for q, q1 and gamma:
128 | print("Computing moduli q1, q etc. ...")
129 | true_gamma_found = false # Boolean for finding correct gamma
130 | q1 = 4*l*int(3329/(4*l)) + (2*l + 1) # we need q1 to be congruent to 2l+1 modulo 4l
131 | while true_gamma_found == false:
132 | q1 = q1 - 4*l # find the next candidate for q1, close to 3329
133 | while is_prime(q1) == False : # we need q1 to be prime
134 | q1 -= 4*l
135 | if nbofdiv == 1: # if number of divisors of q is 1, then q = q1
136 | q = q1
137 | else:
138 | q2 = 4*l * int(2^(logq)/(4*l*q1)) + (2*l + 1) - 4*l # we need q2 to be congruent to 2l+1 modulo 4l
139 | while is_prime(q2) == False : # we need q2 to be prime
140 | q2 -= 4*l
141 | q = q1 * q2 # if number of divisors of q is 2, then q = q1*q2
142 | Div_q = divisors(q-1) # consider divisors of q-1
143 | for i in Div_q:
144 | if gamma*4/5 < i and i <= gamma and is_even(i): # find a divisor which is close to gamma
145 | gamma = i # we found a good candidate for gamma
146 | true_gamma_found = true
147 |
148 |
149 | # Given n and gamma, find the largest possible D which makes the MSIS solution small
150 | print("Computing the parameter D...")
151 | D = logq # initialisation
152 | value_D_found = false # Boolean for finding D
153 | while value_D_found == false: # searching for right D
154 | D -= 1 # decrease the value of D
155 | Bound1 = 2 * stdev1 * sqrt(2 * (m1 + ve) * d) # bound on bar{z}_1
156 | Bound2 = 2 * stdev2 * sqrt(2 * m2 * d) + 2^D * eta * sqrt(n*d) + gamma * sqrt(n*d) # bound on bar{z}_2
157 | Bound = 4 * eta * sqrt(Bound1^2 + Bound2^2) # bound on the extracted MSIS solution
158 | if findMSISdelta(Bound,n,d,logq) < 1.0045 and Bound < 2^logq and 2^(D-1)*kappa*d < gamma: # until we reach ~ 128-bit security
159 | value_D_found = true # it is secure
160 |
161 |
162 |
163 | # Checking knowledge soundness conditions from Theorem 5.3
164 | print("Checking knowledge soundness conditions...")
165 | t = 1.64
166 | Be = 2 * sqrt(256/26) * t * stdeve
167 |
168 | if q < 41 * ce * d * Be:
169 | print("ERROR: can't use Lemma 2.9")
170 |
171 | if q <= Be^2 + Be*sqrt(k_bin*d):
172 | print("ERROR: can't prove E_bin*s + v_bin has binary coefficients")
173 |
174 | if q <= Be^2 + Be*sqrt(ve*d):
175 | print("ERROR: can't prove all x_i have binary coefficients")
176 |
177 | for bound in BoundsToProve:
178 | if q <= 3 * bound^2 + Be^2:
179 | print("ERROR: can't prove || E_i*s - v_i || <= beta_i")
180 |
181 |
182 |
183 | # Output computed parameters
184 | print("---------- computed parameters ----------")
185 | print("The smallest prime divisor q1 of q: ", q1)
186 | print("Proof system modulus q: ", q)
187 | print("Parameter gamma for dropping low-order bits of w: ", gamma)
188 | print("Parameter D for dropping low-order bits of t_A : ", D)
189 | print("Module-SIS dimension: ", n)
190 | print("Module-LWE dimension: ", mlwe)
191 | print("Length of the randomness vector s2: ", m2)
192 | print("Log2 of the standard deviation stdev1: ",round(log(stdev1,2),2))
193 | print("Log2 of the standard deviation stdev2: ",round(log(stdev2,2),2))
194 | print("Log2 of the standard deviation stdeve: ",round(log(stdeve,2),2))
195 |
196 |
197 |
198 | # Output security analysis
199 | print("---------- security analysis ------------")
200 |
201 | # Repetition rate
202 | rep_rate = 2*exp(14/gamma1 + 1/(2*gamma1^2)) * exp(1/(2*gamma2^2)) * exp(1/(2*gammae^2)) * ((1-approximate_norm_proof) + approximate_norm_proof*exp(1/(2*gammad^2)))
203 | print("Repetition rate: ", round(rep_rate ,2 ))
204 |
205 | # Knowledge soundness error from Theorem 5.3
206 | soundness_error = 2 * 1/(2*kappa+1)^(d/2) + q1^(-d/l) + q1^(-lmbda) + 2^(-128) + approximate_norm_proof*2^(-256)
207 | print("Log of the knowledge soundness error: ", ceil(log(soundness_error, 2)) )
208 |
209 | # Exact Module-SIS and Module-LWE hardness
210 | Bound1 = 2 * stdev1 * sqrt(2 * (m1 + ve) * d)
211 | Bound2 = 2 * stdev2 * sqrt(2 * m2 * d) + 2^D * eta * sqrt(n*d) + gamma * sqrt(n*d)
212 | Bound = 4 * eta * sqrt(Bound1^2 + Bound2^2)
213 | print("Root Hermite factor for MSIS: ", round( findMSISdelta(Bound,n,d,logq) ,6))
214 | print("Root Hermite factor for MLWE: ", round(mlwe_hardness,6))
215 |
216 |
217 |
218 | # Proof size
219 | print("---------- proof size -------------------")
220 | full_size = n * d * (logq - D) + (ell + 256/d + 1 + approximate_norm_proof * 256/d + lmbda + 1) * d * logq
221 | challenge = ceil(log(2*kappa+1,2)) * d
222 | short_size1 = (m1 + ve) * d * (ceil(log(stdev1,2) + 2.57)) + (m2 - n) * d * (ceil(log(stdev2,2) + 2.57))
223 | short_size2 = 256 * (ceil(log(stdeve,2) + 2.57)) + approximate_norm_proof * 256 * (ceil(log(stdevd,2) + 2.57))
224 | hint = 2.25 * n * d
225 |
226 | print("Total proof size in KB: ", round((full_size + challenge + short_size1 + short_size2 + hint)/(2^13) , 2))
227 | print("full-sized polynomials in KB: ", round(full_size/(2^13) , 2))
228 | print("challenge c in KB: ", round(challenge/(2^13) , 2))
229 | print("short-sized polynomials in KB: ", round((short_size1 + short_size2 + hint)/(2^13) , 2))
--------------------------------------------------------------------------------
/ver_enc_param_set_1.sage:
--------------------------------------------------------------------------------
1 | # This is the script for computing the non-interactive proof size
2 | # for verifiable encryption in Section 6.3 for prime p which is coprime to q.
3 |
4 |
5 | # Function for estimating the MSIS hardness given parameters:
6 | # a (n x m) matrix in \Rq along with the solution bound B. It returns the
7 | # root Hermite factor \delta. We use the methodology presented by
8 | # [GamNgu08, Mic08] and hence m is irrelevant.
9 |
10 | def findMSISdelta(B, n, d, logq):
11 | logC = log(B, 2)
12 | logdelta = logC^2 / (4*n*d*logq)
13 | return 2^logdelta
14 |
15 | # Function for estimating the MLWE hardness for a (m x n) matrix in \Rq and
16 | # secret coefficients sampled uniformly at random between -nu and nu.
17 | # We use the LWE-Estimator by [AlbPlaSco15] as a black-box.
18 |
19 | def findMLWEdelta(nu, n, d, logq):
20 | load("https://bitbucket.org/malb/lwe-estimator/raw/HEAD/estimator.py")
21 | n = n * d
22 | q = 2^logq
23 | stddev = sqrt(((2*nu+1)^2 - 1)/12)
24 | alpha = alphaf(sigmaf(stddev),q)
25 | set_verbose(1)
26 | L = estimate_lwe(n, alpha, q, reduction_cost_model=BKZ.enum)
27 | delta_enum1 = L['usvp']['delta_0']
28 | delta_enum2 = L['dec']['delta_0']
29 | delta_enum3 = L['dual']['delta_0']
30 | L = estimate_lwe(n, alpha, q, reduction_cost_model=BKZ.sieve)
31 | delta_sieve1 = L['usvp']['delta_0']
32 | delta_sieve2 = L['dec']['delta_0']
33 | delta_sieve3 = L['dual']['delta_0']
34 | return max(delta_enum1,delta_enum2,delta_enum3,delta_sieve1,delta_sieve2,delta_sieve3)
35 |
36 | # Parameters for the encryption scheme
37 | p = 3329 # prime for encryption scheme
38 | N = 4 # height of the matrix A
39 | K = 9 # width of the matrix A
40 | rand_coeff = 2 # coefficients of the randomness vectors, between -rand_coeff and rand_coeff
41 |
42 | # Security parameter, ring dimension of \R and challenge space
43 | secpam = 128 # security parameter
44 | d = 128 # dimension of R = Z[X]/(X^d + 1)
45 | l = 2 # number of irreducible factors of X^d + 1 modulo each q_i, we assume each q_i = 2l+1 (mod 4l)
46 | kappa = 2 # maximum coefficient of a challenge. We want |\chal| = (2*kappa+1)^(d/2) >= 2^secpam
47 | eta = 59 # the heuristic bound on \sqrt[2k](|| \sigma_{-1}(c^k)*c^k ||_1) for k = 32
48 |
49 | # Defining the log of the proof system modulus -- finding true values will come later
50 | nbofdiv = 1 # number of prime divisors of q, usually 1 or 2
51 | logq1 = 36 # log of the smallest prime divisor of q, we want to have a prime close to 3329
52 | logq = 36 # log of the proof system modulus q
53 | lmbda = 2 * ceil( secpam/(2*logq1) ) # number of repetitions for boosting soundness, we assume lambda is even
54 |
55 | # Length and size of the committed messages
56 | m1 = K + 1 # length of s1 = (randomness of length K, message)
57 | m2 = 0 # length of s2, to be determined
58 | ell = 0 # length of m
59 | alpha = sqrt(rand_coeff^2*K*d + d) # norm of s1
60 |
61 | # Parameters for proving norm bounds
62 | ve = 1 # number of exact norm proofs
63 | BoundsToProve = [ rand_coeff*sqrt(K*d) ] # exact bounds beta_i to prove for i=1,2,...,ve
64 | k_bin = 1 # length of a vector to prove binary coefficients
65 | alphae = sqrt(rand_coeff^2*K*d + (k_bin + ve)*d)# bound alpha^(e) on the vector e^(e) = (r,m, bin. decomp. of B^2 - ||r||^2)
66 | ce = K + k_bin + ve # length of the vector e^(e)
67 | approximate_norm_proof = 1 # boolean to indicate if we perform approximate norm proofs
68 | alphad = rand_coeff*(K*d/2+1)*sqrt((N+1)*d) # bound alpha^(d) on the vector e^(d) = v from Equation 74.
69 |
70 | # Parameters for rejection sampling
71 | gamma1 = 41 # rejection sampling for s1
72 | gamma2 = 1.1 # rejection sampling for s2
73 | gammae = 16 # rejection sampling for Rs^(e)
74 | gammad = 1 # rejection sampling for R's^(d) -- ignore if approximate_norm_proof = 0
75 |
76 | # Setting the standard deviations, apart from stdev2
77 | stdev1 = gamma1 * eta * sqrt(alpha^2 + ve * d)
78 | stdev2 = 0
79 | stdeve = gammae * sqrt(337) * alphae
80 | stdevd = gammad * sqrt(337) * alphad
81 |
82 | # Finding MLWE dimension
83 | print("Computing the Module-LWE dimension...")
84 | nu = 1 # randomness vector s2 with coefficients between -nu and nu
85 | mlwe = 0 # dimension of the Module-LWE problem
86 | mlwe_hardness = 2
87 | while mlwe_hardness > 1.0045: # increasing the mlwe dimension until MLWE provides ~ 128-bit security
88 | mlwe += 1
89 | mlwe_hardness = findMLWEdelta(nu,mlwe,d, logq)
90 |
91 |
92 |
93 |
94 | # Finding an appropriate Module-SIS dimension n
95 | print("Computing the Module-SIS dimension...")
96 | n = 0 # dimension of the Module-SIS problem
97 | D = 0 # dropping low-order bits of t_A
98 | gamma = 0 # dropping low-order bits of w
99 | value_n_found = false # Boolean for finding n
100 | while value_n_found == false: # searching for n
101 | n += 1
102 | m2 = mlwe + n + ell + lmbda/2 + 256/d + 1 + approximate_norm_proof * 256/d + 1 # we use the packing optimisation from Section 5.3
103 | stdev2 = gamma2 * eta * nu * sqrt(m2 * d) # set stdev2 with the current candidate for n
104 | Bound1 = 2 * stdev1 * sqrt(2 * (m1 + ve) * d) # bound on bar{z}_1
105 | Bound2 = 2 * stdev2 * sqrt(2 * m2 * d) + 2^D * eta * sqrt(n*d) + gamma * sqrt(n*d) # bound on bar{z}_2 = (bar{z}_{2,1},bar{z}_{2,2})
106 | Bound = 4 * eta * sqrt(Bound1^2 + Bound2^2) # bound on the extracted MSIS solution
107 | if findMSISdelta(Bound,n,d,logq) < 1.0045 and Bound < 2^logq: # until we reach ~ 128-bit security
108 | value_n_found = true # it is secure
109 |
110 |
111 |
112 |
113 | # Given n, find the largest possible gamma which makes the MSIS solution still small
114 | print("Computing the parameter gamma...")
115 | gamma = 2^logq # initialisation
116 | value_gamma_found = false # Boolean for finding gamma
117 | while value_gamma_found == false: # searching for right gamma
118 | gamma /= 2 # decrease the value of gamma
119 | Bound1 = 2 * stdev1 * sqrt(2 * (m1 + ve) * d) # bound on bar{z}_1
120 | Bound2 = 2 * stdev2 * sqrt(2 * m2 * d) + 2^D * eta * sqrt(n*d) + gamma * sqrt(n*d) # bound on bar{z}_2
121 | Bound = 4 * eta * sqrt(Bound1^2 + Bound2^2) # bound on the extracted MSIS solution
122 | if findMSISdelta(Bound,n,d,logq) < 1.0045 and Bound < 2^logq: # until we reach ~ 128-bit security
123 | value_gamma_found = true # it is secure
124 |
125 |
126 | # Finding exact values for q, q1 and gamma:
127 | print("Computing moduli q1, q etc. ...")
128 | true_gamma_found = false # Boolean for finding correct gamma
129 | q1 = 4*l*int(2^logq1/(4*l)) + (2*l + 1) # we need q1 to be congruent to 2l+1 modulo 4l
130 | while true_gamma_found == false:
131 | q1 = q1 - 4*l
132 | while is_prime(q1) == False : # we need q1 to be prime
133 | q1 -= 4*l
134 | if nbofdiv == 1: # if number of divisors of q is 1, then q = q1
135 | q = q1
136 | else:
137 | q2 = 4*l * int(2^(logq)/(4*l*q1)) + 2*l + 1 # we need q2 to be congruent to 2l+1 modulo 4l
138 | while is_prime(q2) == False : # we need q2 to be prime
139 | q2 -= 4*l
140 | q = q1 * q2 # if number of divisors of q is 2, then q = q1*q2
141 | Div_q = divisors(q-1) # consider divisors of q-1
142 | for i in Div_q:
143 | if gamma*4/5 < i and i <= gamma and is_even(i): # find a divisor which is close to gamma
144 | gamma = i # we found a good candidate for gamma
145 | true_gamma_found = true
146 |
147 |
148 | # Given n and gamma, find the largest possible D which makes the MSIS solution small
149 | print("Computing the parameter D...")
150 | D = logq # initialisation
151 | value_D_found = false # Boolean for finding D
152 | while value_D_found == false: # searching for right D
153 | D -= 1 # decrease the value of D
154 | Bound1 = 2 * stdev1 * sqrt(2 * (m1 + ve) * d) # bound on bar{z}_1
155 | Bound2 = 2 * stdev2 * sqrt(2 * m2 * d) + 2^D * eta * sqrt(n*d) + gamma * sqrt(n*d) # bound on bar{z}_2
156 | Bound = 4 * eta * sqrt(Bound1^2 + Bound2^2) # bound on the extracted MSIS solution
157 | if findMSISdelta(Bound,n,d,logq) < 1.0045 and Bound < 2^logq and 2^(D-1)*kappa*d < gamma: # until we reach ~ 128-bit security
158 | value_D_found = true # it is secure
159 |
160 |
161 |
162 | # Checking knowledge soundness conditions from Theorem 5.3
163 | print("Checking knowledge soundness conditions...")
164 | t = 1.64
165 | Be = 2 * sqrt(256/26) * t * stdeve
166 |
167 | if q < 41 * ce * d * Be:
168 | print("ERROR: can't use Lemma 2.9")
169 |
170 | if q <= Be^2 + Be*sqrt(k_bin*d):
171 | print("ERROR: can't prove E_bin*s + v_bin has binary coefficients")
172 |
173 | if q <= Be^2 + Be*sqrt(ve*d):
174 | print("ERROR: can't prove all x_i have binary coefficients")
175 |
176 | for bound in BoundsToProve:
177 | if q <= 3 * bound^2 + Be^2:
178 | print("ERROR: can't prove || E_i*s - v_i || <= beta_i")
179 |
180 | # Checking whether there is no modulo overflow
181 | print("Checking modulo overflow conditions...")
182 | Bd = 2 * 14 * stdevd
183 |
184 | if q <= p * (rand_coeff*sqrt(K*d)/2 + 1 + Bd):
185 | print("ERROR: modulo overflow")
186 |
187 |
188 | # Output computed parameters
189 | print("---------- computed parameters ----------")
190 | print("The smallest prime divisor q1 of q: ", q1)
191 | print("Proof system modulus q: ", q)
192 | print("Parameter gamma for dropping low-order bits of w: ", gamma)
193 | print("Parameter D for dropping low-order bits of t_A : ", D)
194 | print("Module-SIS dimension: ", n)
195 | print("Module-LWE dimension: ", mlwe)
196 | print("Length of the randomness vector s2: ", m2)
197 | print("Log2 of the standard deviation stdev1: ",round(log(stdev1,2),2))
198 | print("Log2 of the standard deviation stdev2: ",round(log(stdev2,2),2))
199 | print("Log2 of the standard deviation stdeve: ",round(log(stdeve,2),2))
200 | print("Log2 of the standard deviation stdevd: ",round(log(stdevd,2),2))
201 |
202 | # Output security analysis
203 | print("---------- security analysis ------------")
204 |
205 | # Repetition rate
206 | rep_rate = 2*exp(14/gamma1 + 1/(2*gamma1^2)) * exp(1/(2*gamma2^2)) * exp(1/(2*gammae^2)) * ((1-approximate_norm_proof) + approximate_norm_proof*exp(1/(2*gammad^2)))
207 | print("Repetition rate: ", round(rep_rate ,2 ))
208 |
209 | # Knowledge soundness error from Theorem 5.3
210 | soundness_error = 2 * 1/(2*kappa+1)^(d/2) + q1^(-d/l) + q1^(-lmbda) + 2^(-128) + approximate_norm_proof*2^(-256)
211 | print("Log of the knowledge soundness error: ", ceil(log(soundness_error, 2)) )
212 |
213 | # Exact Module-SIS and Module-LWE hardness
214 | Bound1 = 2 * stdev1 * sqrt(2 * (m1 + ve) * d)
215 | Bound2 = 2 * stdev2 * sqrt(2 * m2 * d) + 2^D * eta * sqrt(n*d) + gamma * sqrt(n*d)
216 | Bound = 4 * eta * sqrt(Bound1^2 + Bound2^2)
217 | print("Root Hermite factor for MSIS: ", round( findMSISdelta(Bound,n,d,logq) ,6))
218 | print("Root Hermite factor for MLWE: ", round(mlwe_hardness,6))
219 |
220 |
221 |
222 | # Proof size
223 | print("---------- proof size -------------------")
224 | full_size = n * d * (logq - D) + (ell + 256/d + 1 + approximate_norm_proof * 256/d + lmbda + 1) * d * logq
225 | challenge = ceil(log(2*kappa+1,2)) * d
226 | short_size1 = (m1 + ve) * d * (ceil(log(stdev1,2) + 2.57)) + (m2 - n) * d * (ceil(log(stdev2,2) + 2.57))
227 | short_size2 = 256 * (ceil(log(stdeve,2) + 2.57)) + approximate_norm_proof * 256 * (ceil(log(stdevd,2) + 2.57))
228 | hint = 2.25 * n * d
229 |
230 | print("Total proof size in KB: ", round((full_size + challenge + short_size1 + short_size2 + hint)/(2^13) , 2))
231 | print("full-sized polynomials in KB: ", round(full_size/(2^13) , 2))
232 | print("challenge c in KB: ", round(challenge/(2^13) , 2))
233 | print("short-sized polynomials in KB: ", round((short_size1 + short_size2 + hint)/(2^13) , 2))
234 |
--------------------------------------------------------------------------------
/group_signature.sage:
--------------------------------------------------------------------------------
1 | # This is the script for computing the size of the group signature.
2 |
3 |
4 | # Function for estimating the MSIS hardness given parameters:
5 | # a (n x m) matrix in \Rq along with the solution bound B. It returns the
6 | # root Hermite factor \delta. We use the methodology presented by
7 | # [GamNgu08, Mic08] and hence m is irrelevant.
8 |
9 | def findMSISdelta(B, n, d, logq):
10 | logC = log(B, 2)
11 | logdelta = logC^2 / (4*n*d*logq)
12 | return 2^logdelta
13 |
14 | # Function for estimating the MLWE hardness for a (m x n) matrix in \Rq and
15 | # secret coefficients sampled uniformly at random between -nu and nu.
16 | # We use the LWE-Estimator by [AlbPlaSco15] as a black-box.
17 |
18 | def findMLWEdelta(nu, n, d, logq):
19 | load("https://bitbucket.org/malb/lwe-estimator/raw/HEAD/estimator.py")
20 | n = n * d
21 | q = 2^logq
22 | stddev = sqrt(((2*nu+1)^2 - 1)/12)
23 | alpha = alphaf(sigmaf(stddev),q)
24 | set_verbose(1)
25 | L = estimate_lwe(n, alpha, q, reduction_cost_model=BKZ.enum)
26 | delta_enum1 = L['usvp']['delta_0']
27 | delta_enum2 = L['dec']['delta_0']
28 | delta_enum3 = L['dual']['delta_0']
29 | L = estimate_lwe(n, alpha, q, reduction_cost_model=BKZ.sieve)
30 | delta_sieve1 = L['usvp']['delta_0']
31 | delta_sieve2 = L['dec']['delta_0']
32 | delta_sieve3 = L['dual']['delta_0']
33 | return max(delta_enum1,delta_enum2,delta_enum3,delta_sieve1,delta_sieve2,delta_sieve3)
34 |
35 | # Group signature parameters
36 | gs_d = 512 # ring dimension for the group signature
37 | k = 4 # gs_d = k * d
38 | gs_N = 2 # height of the matrix A
39 | gs_M = 3 # N + M is the width of the matrix A
40 | gs_tau = 5 # length of the gadget matrix
41 | gs_logp = 38 # log of the prime of the group signature
42 | gs_p = 2^gs_logp # approximate value for p
43 | gs_const = 113 # (heuristic) operator norm of the randomness matrix R
44 | gs_stdev = 2*(gs_const + 1) * sqrt(gs_p^(2/gs_tau)+1) # standard deviation for trapdoor sampling
45 | gs_B = gs_stdev * sqrt(2*((2*gs_tau+1)*gs_N + gs_M)*gs_d) # bound on the user secret key
46 | gs_extracted = 2*gs_B*sqrt(1 + 2*gs_const^2) # extracted Module-SIS solution
47 |
48 | # Parameters for the encryption scheme
49 | p = 3329 # Log of the prime for encryption scheme
50 | N = 4 # height of the matrix A
51 | K = 9 # width of the matrix A
52 | rand_coeff = 2 # coefficients of the randomness vectors, between -rand_coeff and rand_coeff
53 |
54 | # Security parameter, ring dimension of \R and challenge space
55 | secpam = 128 # security parameter
56 | d = 128 # dimension of R = Z[X]/(X^d + 1)
57 | l = 2 # number of irreducible factors of X^d + 1 modulo each q_i, we assume each q_i = 2l+1 (mod 4l)
58 | kappa = 2 # maximum coefficient of a challenge. We want |\chal| = (2*kappa+1)^(d/2) >= 2^secpam
59 | eta = 59 # the heuristic bound on \sqrt[2k](|| \sigma_{-1}(c^k)*c^k ||_1) for k = 32
60 |
61 | # Defining the log of the proof system modulus -- finding true values will come later
62 | nbofdiv = 2 # number of prime divisors of q, usually 1 or 2
63 | logq1 = 26 # log of the smallest prime divisor of q, we want to have a prime close to 3329
64 | logq = 64 # log of the proof system modulus q
65 | lmbda = 2 * ceil( secpam/(2*logq1) ) # number of repetitions for boosting soundness, we assume lambda is even
66 |
67 | # Length and size of the committed messages
68 | m1 = ((2*gs_tau+1)*gs_N + gs_M)*k + K + 1 # length of s1 = (user secret key s1,s2,s3, randomness of length K, identity)
69 | m2 = 0 # length of s2, to be determined
70 | ell = 0 # length of m
71 | alpha = sqrt(gs_B^2 + rand_coeff^2*K*d + d) # norm of s1
72 |
73 | # Parameters for proving norm bounds
74 | ve = 2 # number of exact norm proofs
75 | BoundsToProve = [ gs_B, rand_coeff*sqrt(K*d) ] # exact bounds beta_i to prove for i=1,2,...,ve
76 | k_bin = 1 # length of a vector to prove binary coefficients
77 | alphae = sqrt(gs_B^2 + rand_coeff^2*K*d + (k_bin + ve)*d) # bound alpha^(e) on the vector e^(e) = (s1,s2,s3,r,i,bin. dec. of gs_B^2 - ||(s1,s2,s3)||^2, bin dec. of B^2_enc - ||r||^2)
78 | ce = ((2*gs_tau+1)*gs_N + gs_M)*k + K + k_bin + ve # length of the vector e^(e)
79 | approximate_norm_proof = 1 # boolean to indicate if we perform approximate norm proofs
80 | alphad = rand_coeff*(K*d+1)*sqrt((N+1)*d)/2 # bound alpha^(d) on the vector e^(d) = v_enc from Equation 74.
81 |
82 | # Parameters for rejection sampling
83 | gamma1 = 17 # rejection sampling for s1
84 | gamma2 = 1.2 # rejection sampling for s2
85 | gammae = 2.5 # rejection sampling for Rs^(e)
86 | gammad = 12 # rejection sampling for R's^(d) -- ignore if approximate_norm_proof = 0
87 |
88 | # Setting the standard deviations, apart from stdev2
89 | stdev1 = gamma1 * eta * sqrt(alpha^2 + ve * d)
90 | stdev2 = 0
91 | stdeve = gammae * sqrt(337) * alphae
92 | stdevd = gammad * sqrt(337) * alphad
93 |
94 | # Finding MLWE dimension
95 | print("Computing the Module-LWE dimension...")
96 | nu = 1 # randomness vector s2 with coefficients between -nu and nu
97 | mlwe = 0 # dimension of the Module-LWE problem
98 | mlwe_hardness = 2
99 | while mlwe_hardness > 1.0045: # increasing the mlwe dimension until MLWE provides ~ 128-bit security
100 | mlwe += 1
101 | mlwe_hardness = findMLWEdelta(nu,mlwe,d, logq)
102 |
103 |
104 |
105 |
106 | # Finding an appropriate Module-SIS dimension n
107 | print("Computing the Module-SIS dimension...")
108 | n = 0 # dimension of the Module-SIS problem
109 | D = 0 # dropping low-order bits of t_A
110 | gamma = 0 # dropping low-order bits of w
111 | value_n_found = false # Boolean for finding n
112 | while value_n_found == false: # searching for n
113 | n += 1
114 | m2 = mlwe + n + ell + lmbda/2 + 256/d + 1 + approximate_norm_proof * 256/d + 1 # we use the packing optimisation from Section 5.3
115 | stdev2 = gamma2 * eta * nu * sqrt(m2 * d) # set stdev2 with the current candidate for n
116 | Bound1 = 2 * stdev1 * sqrt(2 * (m1 + ve) * d) # bound on bar{z}_1
117 | Bound2 = 2 * stdev2 * sqrt(2 * m2 * d) + 2^D * eta * sqrt(n*d) + gamma * sqrt(n*d) # bound on bar{z}_2 = (bar{z}_{2,1},bar{z}_{2,2})
118 | Bound = 4 * eta * sqrt(Bound1^2 + Bound2^2) # bound on the extracted MSIS solution
119 | if findMSISdelta(Bound,n,d,logq) < 1.0045 and Bound < 2^logq: # until we reach ~ 128-bit security
120 | value_n_found = true # it is secure
121 |
122 |
123 |
124 |
125 | # Given n, find the largest possible gamma which makes the MSIS solution still small
126 | print("Computing the parameter gamma...")
127 | gamma = 2^logq # initialisation
128 | value_gamma_found = false # Boolean for finding gamma
129 | while value_gamma_found == false: # searching for right gamma
130 | gamma /= 2 # decrease the value of gamma
131 | Bound1 = 2 * stdev1 * sqrt(2 * (m1 + ve) * d) # bound on bar{z}_1
132 | Bound2 = 2 * stdev2 * sqrt(2 * m2 * d) + 2^D * eta * sqrt(n*d) + gamma * sqrt(n*d) # bound on bar{z}_2
133 | Bound = 4 * eta * sqrt(Bound1^2 + Bound2^2) # bound on the extracted MSIS solution
134 | if findMSISdelta(Bound,n,d,logq) < 1.0045 and Bound < 2^logq: # until we reach ~ 128-bit security
135 | value_gamma_found = true # it is secure
136 |
137 |
138 | # Finding exact values for q, q1 and gamma:
139 | print("Computing moduli q1, q etc. ...")
140 | true_gamma_found = false # Boolean for finding correct gamma
141 | q1 = 4*l*int(2^logq1/(4*l)) + (2*l + 1) # we need q1 to be congruent to 2l+1 modulo 4l
142 | while true_gamma_found == false:
143 | q1 = q1 - 4*l
144 | while is_prime(q1) == False : # we need q1 to be prime
145 | q1 -= 4*l
146 | if nbofdiv == 1: # if number of divisors of q is 1, then q = q1
147 | q = q1
148 | else:
149 | gs_p = 4*l * int(2^(logq)/(4*l*2^(logq1))) + 2*l + 1 # we need gs_p = q2 to be congruent to 2l+1 modulo 4l
150 | while is_prime(gs_p) == False : # we need q2 to be prime
151 | gs_p -= 4*l
152 | q = q1 * gs_p # if number of divisors of q is 2, then q = q1*q2
153 | Div_q = divisors(q-1) # consider divisors of q-1
154 | for i in Div_q:
155 | if gamma*4/5 < i and i <= gamma and is_even(i): # find a divisor which is close to gamma
156 | gamma = i # we found a good candidate for gamma
157 | true_gamma_found = true
158 |
159 |
160 | # Given n and gamma, find the largest possible D which makes the MSIS solution small
161 | print("Computing the parameter D...")
162 | D = logq # initialisation
163 | value_D_found = false # Boolean for finding D
164 | while value_D_found == false: # searching for right D
165 | D -= 1 # decrease the value of D
166 | Bound1 = 2 * stdev1 * sqrt(2 * (m1 + ve) * d) # bound on bar{z}_1
167 | Bound2 = 2 * stdev2 * sqrt(2 * m2 * d) + 2^D * eta * sqrt(n*d) + gamma * sqrt(n*d) # bound on bar{z}_2
168 | Bound = 4 * eta * sqrt(Bound1^2 + Bound2^2) # bound on the extracted MSIS solution
169 | if findMSISdelta(Bound,n,d,logq) < 1.0045 and Bound < 2^logq and 2^(D-1)*kappa*d < gamma: # until we reach ~ 128-bit security
170 | value_D_found = true # it is secure
171 |
172 |
173 |
174 | # Checking knowledge soundness conditions from Theorem 5.3
175 | print("Checking knowledge soundness conditions...")
176 | t = 1.64
177 | Be = 2 * sqrt(256/26) * t * stdeve
178 |
179 | if q < 41 * ce * d * Be:
180 | print("ERROR: can't use Lemma 2.9")
181 |
182 | if q <= Be^2 + Be*sqrt(k_bin*d):
183 | print("ERROR: can't prove E_bin*s + v_bin has binary coefficients")
184 |
185 | if q <= Be^2 + Be*sqrt(ve*d):
186 | print("ERROR: can't prove all x_i have binary coefficients")
187 |
188 | for bound in BoundsToProve:
189 | if q <= 3 * bound^2 + Be^2:
190 | print("ERROR: can't prove || E_i*s - v_i || <= beta_i")
191 |
192 | # Checking whether there is no modulo overflow for verifiable encryption
193 | print("Checking modulo overflow conditions...")
194 | Bd = 2 * 14 * stdevd
195 |
196 | if q <= p * (rand_coeff*sqrt(K*d)/2 + 1 + Bd):
197 | print("ERROR: modulo overflow")
198 |
199 |
200 | # Output computed parameters
201 | print("---------- computed parameters ----------")
202 | print("The smallest prime divisor q1 of q: ", q1)
203 | print("Prime p for group signature scheme: ", gs_p)
204 | print("Proof system modulus q: ", q)
205 | print("Parameter gamma for dropping low-order bits of w: ", gamma)
206 | print("Parameter D for dropping low-order bits of t_A : ", D)
207 | print("Module-SIS dimension: ", n)
208 | print("Module-LWE dimension: ", mlwe)
209 | print("Length of the randomness vector s2: ", m2)
210 | print("Log2 of the standard deviation stdev1: ",round(log(stdev1,2),2))
211 | print("Log2 of the standard deviation stdev2: ",round(log(stdev2,2),2))
212 | print("Log2 of the standard deviation stdeve: ",round(log(stdeve,2),2))
213 | print("Log2 of the standard deviation stdevd: ",round(log(stdevd,2),2))
214 |
215 |
216 |
217 | # Output security analysis
218 | print("---------- security analysis ------------")
219 |
220 | # Repetition rate
221 | rep_rate = 2*exp(14/gamma1 + 1/(2*gamma1^2)) * exp(1/(2*gamma2^2)) * exp(1/(2*gammae^2)) * ((1-approximate_norm_proof) + approximate_norm_proof*exp(1/(2*gammad^2)))
222 | print("Repetition rate: ", round(rep_rate ,2 ))
223 |
224 | # Knowledge soundness error from Theorem 5.3
225 | soundness_error = 2 * 1/(2*kappa+1)^(d/2) + q1^(-d/l) + q1^(-lmbda) + 2^(-128) + approximate_norm_proof*2^(-256)
226 | print("Log of the knowledge soundness error: ", ceil(log(soundness_error, 2)) )
227 |
228 | # Exact Module-SIS and Module-LWE hardness
229 | Bound1 = 2 * stdev1 * sqrt(2 * (m1 + ve) * d)
230 | Bound2 = 2 * stdev2 * sqrt(2 * m2 * d) + 2^D * eta * sqrt(n*d) + gamma * sqrt(n*d)
231 | Bound = 4 * eta * sqrt(Bound1^2 + Bound2^2)
232 | print("Root Hermite factor for group signature MSIS: ", round(findMSISdelta(gs_extracted , gs_N,k*d, gs_logp),6))
233 | print("Root Hermite factor for proof system MSIS: ", round(findMSISdelta(Bound,n,d,logq) ,6))
234 | print("Root Hermite factor for proof system MLWE: ", round(mlwe_hardness,6))
235 |
236 |
237 |
238 | # Proof size
239 | print("---------- proof size -------------------")
240 | full_size = n * d * (logq - D) + (ell + 256/d + 1 + approximate_norm_proof * 256/d + lmbda + 1) * d * logq
241 | challenge = ceil(log(2*kappa+1,2)) * d
242 | short_size1 = (m1 + ve) * d * (ceil(log(stdev1,2) + 2.57)) + (m2 - n) * d * (ceil(log(stdev2,2) + 2.57))
243 | short_size2 = 256 * (ceil(log(stdeve,2) + 2.57)) + approximate_norm_proof * 256 * (ceil(log(stdevd,2) + 2.57))
244 | hint = 2.25 * n * d
245 | ciphertext_size = (N+1) * d * ceil(log(p,2))
246 |
247 | print("Public key size in KB: ", round(gs_N * gs_tau * gs_N * gs_d * gs_logp/(2^13),2))
248 | print("Secret key size in KB: ", round((gs_N+gs_M) * gs_tau * gs_N * gs_d * 2/(2^13),2))
249 | print("Total group signature size in KB: ", round((full_size + challenge + short_size1 + short_size2 + hint + ciphertext_size)/(2^13) , 2))
250 | print("full-sized polynomials in KB: ", round(full_size/(2^13) , 2))
251 | print("challenge c in KB: ", round(challenge/(2^13) , 2))
252 | print("short-sized polynomials in KB: ", round((short_size1 + short_size2 + hint)/(2^13) , 2))
253 | print("ciphertext size in KB: ", round(ciphertext_size/(2^13),2))
254 |
255 | # Computing the extra cost of verifiable encryption
256 | verenc_fullsize = ciphertext_size + 256*logq
257 | verenc_shortsize = N*d*(ceil(log(stdev1,2) + 2.57)) + 256*(ceil(log(stdev2,2) + 2.57)) + 256*(ceil(log(stdevd,2) + 2.57))
258 | print("extra cost of adding verifiable encryption: ",round((verenc_fullsize+verenc_shortsize)/(2^13),2))
--------------------------------------------------------------------------------