├── 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)) --------------------------------------------------------------------------------