├── README.md ├── docs └── shuffle_ssle.pdf ├── python_code ├── __init__.py ├── fiat_shamir.py ├── gprod.py ├── group_ops.py ├── inner_product.py ├── libff.dylib ├── multiexp.py ├── prove.py ├── sameexp.py ├── setup.py ├── test.py └── utils.py └── rust_code ├── Cargo.toml └── src ├── main.rs └── shuffle.rs /README.md: -------------------------------------------------------------------------------- 1 | # Shuffle_SSLE -------------------------------------------------------------------------------- /docs/shuffle_ssle.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethresearch/Shuffle_SSLE/16761f8a90251c1aa32b52563b221c8df2a978fe/docs/shuffle_ssle.pdf -------------------------------------------------------------------------------- /python_code/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethresearch/Shuffle_SSLE/16761f8a90251c1aa32b52563b221c8df2a978fe/python_code/__init__.py -------------------------------------------------------------------------------- /python_code/fiat_shamir.py: -------------------------------------------------------------------------------- 1 | import hashlib 2 | from eth_abi import encode_abi 3 | from py_ecc.secp256k1.secp256k1 import bytes_to_int 4 | 5 | def hash_integers(values): 6 | k = bytes(32) 7 | 8 | for i in range(0,len(values)): 9 | k1 = int(values[i]).to_bytes(32, byteorder='big') 10 | v = encode_abi(['bytes32','bytes32'],[k,k1]) 11 | k = hashlib.sha256(v).digest() 12 | 13 | return bytes_to_int(k) 14 | 15 | #print("hash_integers",hash_integers([2,3,4])) 16 | -------------------------------------------------------------------------------- /python_code/gprod.py: -------------------------------------------------------------------------------- 1 | from group_ops import add, multiply, Z1 2 | from secrets import randbelow 3 | 4 | from fiat_shamir import hash_integers 5 | from utils import compute_multiexp, compute_innerprod, inverse, curve_order, int_to_binaryintarray 6 | 7 | 8 | def gprod_prove_outer(current_hash, crs, vec_a, len_gprod, gprod, n, logn): 9 | 10 | [crs_g, u, crs_se1, crs_se2] = crs[:] 11 | 12 | vec_b = [0] * n 13 | vec_b[0] = 1 14 | for i in range(1,len_gprod): 15 | vec_b[i] = vec_a[i] * vec_b[i-1] % curve_order 16 | 17 | for i in range(len_gprod,n): 18 | vec_b[i] = randbelow(curve_order) 19 | 20 | B = compute_multiexp(crs_g[:], vec_b[:]) 21 | blinder = compute_innerprod(vec_a[len_gprod:],vec_b[len_gprod:]) 22 | 23 | current_hash = hash_integers([current_hash, gprod, blinder, int(B[0]), int(B[1]), int(B[2])]) 24 | x = current_hash % curve_order; inv_x =inverse(x); 25 | 26 | vec_c = [0] * n; 27 | pow_x = x; 28 | pow_x2 = 1 29 | for i in range(len_gprod-1): 30 | vec_c[i] = ( vec_a[i+1] * pow_x - pow_x2) % curve_order 31 | pow_x = pow_x * x % curve_order 32 | pow_x2 = pow_x2 * x % curve_order 33 | 34 | vec_c[len_gprod-1] = (vec_a[0] * pow_x - pow_x2) % curve_order 35 | 36 | pow_x = pow_x * x % curve_order 37 | for i in range(len_gprod, n): 38 | vec_c[i] = (vec_a[i] * pow_x) % curve_order 39 | 40 | crs_h = [0]*n; pow_inv_x = inv_x 41 | for i in range(len_gprod - 1): 42 | crs_h[i] = multiply(crs_g[i+1], pow_inv_x) 43 | pow_inv_x = pow_inv_x * inv_x % curve_order 44 | crs_h[len_gprod-1] = multiply(crs_g[0], pow_inv_x) 45 | 46 | pow_inv_x = pow_inv_x * inv_x % curve_order 47 | for i in range(len_gprod, n): 48 | crs_h[i] = multiply(crs_g[i], pow_inv_x) 49 | 50 | inner_prod = (blinder * (x ** (len_gprod+1)) + gprod * (x ** len_gprod) - 1) % curve_order 51 | 52 | crs = [crs_g[:],crs_h[:],u] 53 | 54 | # [current_hash, inner_proof] = gprod_prove_inner(current_hash, crs[:], vec_b[:], vec_c[:], inner_prod, n, logn) 55 | 56 | inner_prod_info = [crs_h[:], vec_b[:], vec_c[:], inner_prod] 57 | 58 | return [current_hash, [B, blinder], inner_prod_info[:]] 59 | 60 | def gprod_prove_inner(current_hash, crs, vec_b, vec_c,inner_prod, n, logn): 61 | [crs_g, crs_h, u] = crs[:] 62 | proof = [] 63 | 64 | ### Adding in zero knowledge 65 | vec_r = [0]*n; 66 | for i in range(n): 67 | vec_r[i] = randbelow(curve_order) 68 | 69 | R = compute_multiexp(crs_h[:], vec_r[:]) 70 | blinder_2 = compute_innerprod(vec_b[:], vec_r[:]) 71 | 72 | current_hash = hash_integers([current_hash,int(R[0]),int(R[1]), int(R[2]), blinder_2]) 73 | x = current_hash % curve_order 74 | 75 | inner_prod = (inner_prod + blinder_2 * x ) % curve_order 76 | for i in range(n): 77 | vec_c[i] = (vec_c[i] + vec_r[i] * x) % curve_order 78 | 79 | 80 | ### Inserting inner_prod into exponent. 81 | current_hash = hash_integers([current_hash,inner_prod]) 82 | x = current_hash % curve_order; 83 | u = multiply(u, x) 84 | 85 | for j in range(logn): 86 | n = n // 2 87 | 88 | zL = compute_innerprod(vec_b[n:], vec_c[:n]) 89 | zR = compute_innerprod(vec_b[:n], vec_c[n:]) 90 | 91 | CL = add(compute_multiexp(crs_g[:n], vec_b[n:]), compute_multiexp(crs_h[n:],vec_c[:n])) 92 | CL = add(CL, multiply(u, zL)) 93 | CR = add(compute_multiexp(crs_g[n:], vec_b[:n]), compute_multiexp(crs_h[:n],vec_c[n:])) 94 | CR = add(CR, multiply(u, zR)) 95 | 96 | proof.append([CL, CR]) 97 | 98 | current_hash = hash_integers([current_hash,int(CL[0]),int(CL[1]), int(CL[2]), 99 | int(CR[0]), int(CR[1]), int(CR[2])]) 100 | 101 | x = current_hash % curve_order; inv_x =inverse(x); 102 | 103 | for i in range(n): 104 | crs_g[i] = add(multiply(crs_g[n + i],inv_x), crs_g[i] ) 105 | crs_h[i] = add(multiply(crs_h[n + i],x), crs_h[i] ) 106 | vec_b[i] = (vec_b[i] + x * vec_b[n + i] ) % curve_order 107 | vec_c[i] = (vec_c[i] + inv_x * vec_c[n + i] ) % curve_order 108 | 109 | crs_g = crs_g[:n]; crs_h = crs_h[:n] 110 | vec_b = vec_b[:n]; vec_c = vec_c[:n] 111 | 112 | return [current_hash, [R, blinder_2, proof[:], vec_b[0], vec_c[0]]] 113 | 114 | def gprod_verify_outer(current_hash, crs, A, len_gprod, gprod, gprod_proof, n, logn): 115 | 116 | [crs_g, u, crs_se1, crs_se2] = crs[:] 117 | [B, blinder] = gprod_proof[:] 118 | 119 | current_hash = hash_integers([current_hash, gprod, blinder, int(B[0]), int(B[1]), int(B[2])]) 120 | x = current_hash % curve_order; inv_x =inverse(x); 121 | 122 | C = crs_g[0] 123 | for i in range(1,len_gprod): 124 | C = add( C, crs_g[i]) 125 | 126 | C = multiply(C, curve_order - inv_x) 127 | C = add(C, A) 128 | 129 | vec_crs_h_exp = [1]*n; pow_inv_x = inv_x 130 | for i in range(1,len_gprod): 131 | vec_crs_h_exp[i] = pow_inv_x 132 | pow_inv_x = pow_inv_x * inv_x % curve_order 133 | 134 | vec_crs_h_exp[0] = pow_inv_x 135 | 136 | pow_inv_x = pow_inv_x * inv_x % curve_order 137 | for i in range(len_gprod, n): 138 | vec_crs_h_exp[i] = pow_inv_x 139 | 140 | inner_prod = (blinder * (x ** (len_gprod+1)) + gprod * (x ** len_gprod) - 1) % curve_order 141 | 142 | # [current_hash, b] = gprod_verify_inner(current_hash, crs[:], vec_crs_h_exp[:], C, inner_prod, inner_proof[:], 143 | # len_gprod, n, logn) 144 | 145 | inner_prod_info = [vec_crs_h_exp[:], B, C, inner_prod, len_gprod] 146 | 147 | return [current_hash, inner_prod_info[:]] 148 | 149 | def gprod_verify_inner(current_hash, crs, vec_crs_h_exp, C, inner_prod, inner_proof, len_gprod, n, logn): 150 | [crs_g, crs_h, u] = crs[:] 151 | 152 | ### Adding in zero knowledge 153 | [R, blinder_2,proof, last_b, last_c] = inner_proof[:] 154 | 155 | 156 | current_hash = hash_integers([current_hash,int(R[0]),int(R[1]), int(R[2]), blinder_2]) 157 | x = current_hash % curve_order 158 | 159 | inner_prod = (inner_prod + blinder_2 * x ) % curve_order 160 | C = add(C, multiply(R,x)) 161 | 162 | ### Putting inner_prod into exponent. 163 | current_hash = hash_integers([current_hash,inner_prod]) 164 | x = current_hash % curve_order; 165 | 166 | u = multiply(u, x) 167 | C = add(C, multiply(u,inner_prod)) 168 | 169 | vec_crs_g_exp = [1] * n; 170 | vec_crs_h_shifted = [1] * n; 171 | 172 | n_var = n 173 | for j in range(logn): 174 | n_var = n_var // 2 175 | [CL, CR] = proof[j] 176 | 177 | current_hash = hash_integers([current_hash,int(CL[0]),int(CL[1]), int(CL[2]), 178 | int(CR[0]), int(CR[1]), int(CR[2])]) 179 | 180 | x = current_hash % curve_order; inv_x =inverse(x) 181 | 182 | for i in range(n): 183 | bin_i = int_to_binaryintarray(i,logn) 184 | if bin_i[logn - j - 1] == 1: 185 | vec_crs_g_exp[i] = (vec_crs_g_exp[i] * inv_x) % curve_order 186 | vec_crs_h_shifted[i] = (vec_crs_h_shifted[i] * x) % curve_order 187 | 188 | C = add(add(multiply(CR, inv_x), C), multiply(CL, x)) 189 | 190 | vec_crs_h_exp[0] = (vec_crs_h_exp[0] * vec_crs_h_shifted[len_gprod - 1]) % curve_order 191 | for i in range(1,len_gprod): 192 | vec_crs_h_exp[i] = (vec_crs_h_exp[i] * vec_crs_h_shifted[i-1]) % curve_order 193 | for i in range(len_gprod,n): 194 | vec_crs_h_exp[i] = (vec_crs_h_exp[i] * vec_crs_h_shifted[i]) % curve_order 195 | 196 | inner_prod = last_b * last_c % curve_order 197 | final_g = compute_multiexp(crs_g[:], vec_crs_g_exp[:]) 198 | final_h = compute_multiexp(crs_h[:], vec_crs_h_exp[:]) 199 | 200 | expected_outcome = multiply(final_g, curve_order - last_b) 201 | expected_outcome = add(expected_outcome, multiply(final_h, curve_order - last_c)) 202 | expected_outcome = add(expected_outcome, multiply(u, curve_order - inner_prod)) 203 | 204 | if add( expected_outcome, C) != (1,1,0): 205 | print("ERROR: final exponent is incorrect") 206 | return [current_hash, 0] 207 | 208 | return [current_hash, 1] 209 | -------------------------------------------------------------------------------- /python_code/group_ops.py: -------------------------------------------------------------------------------- 1 | field_modulus = 21888242871839275222246405745257275088696311157297823662689037894645226208583 2 | 3 | # Curve is y**2 = x**3 + 3 4 | b = 3 5 | 6 | # Generator for curve over FQ 7 | G1 = (1, 2, 1) 8 | 9 | # Point at infinity over FQ 10 | Z1 = (1, 1, 0) 11 | 12 | # Check that a point is on the curve defined by y**2 == x**3 + b 13 | def is_on_curve(pt): 14 | (x, y, z) = pt[:] 15 | return (y**2 * z - x**3) % field_modulus == b * z**3 % field_modulus 16 | 17 | 18 | # Elliptic curve doubling 19 | def double(pt): 20 | (x, y, z) = pt[:] 21 | W = (3 * x * x) % field_modulus 22 | S = (y * z) % field_modulus 23 | B = (x * y * S) % field_modulus 24 | H = (W * W - 8 * B) % field_modulus 25 | S_squared = (S * S) % field_modulus 26 | newx = (2 * H * S) % field_modulus 27 | newy = (W * (4 * B - H) - 8 * y * y * S_squared) % field_modulus 28 | newz = (8 * S * S_squared) % field_modulus 29 | return (newx, newy, newz) 30 | 31 | 32 | # Elliptic curve addition 33 | def add(pt1,pt2): 34 | if pt1[2] == 0 or pt2[2] == 0: 35 | return pt1 if pt2[2] == 0 else pt2 36 | (x1, y1, z1) = pt1[:] 37 | (x2, y2, z2) = pt2[:] 38 | U1 = ( y2 * z1 ) % field_modulus 39 | U2 = ( y1 * z2 ) % field_modulus 40 | V1 = ( x2 * z1 ) % field_modulus 41 | V2 = ( x1 * z2 ) % field_modulus 42 | if V1 == V2 and U1 == U2: 43 | return double(pt1[:]) 44 | elif V1 == V2: 45 | return (1, 1, 0) 46 | U = ( U1 - U2 ) % field_modulus 47 | V = ( V1 - V2 ) % field_modulus 48 | V_squared = ( V * V ) % field_modulus 49 | V_squared_times_V2 = ( V_squared * V2 ) % field_modulus 50 | V_cubed = ( V * V_squared ) % field_modulus 51 | W = ( z1 * z2 ) % field_modulus 52 | A = ( U * U * W - V_cubed - 2 * V_squared_times_V2 ) % field_modulus 53 | newx = ( V * A ) % field_modulus 54 | newy = ( U * (V_squared_times_V2 - A) - V_cubed * U2 ) % field_modulus 55 | newz = ( V_cubed * W ) % field_modulus 56 | return (newx, newy, newz) 57 | 58 | 59 | # Elliptic curve point multiplication 60 | def multiply(pt, n): 61 | if n == 0: 62 | return (1, 1, 0) 63 | elif n == 1: 64 | return pt[:] 65 | elif not n % 2: 66 | return multiply(double(pt[:]), n // 2) 67 | else: 68 | return add(multiply(double(pt[:]), int(n // 2)), pt[:]) 69 | -------------------------------------------------------------------------------- /python_code/inner_product.py: -------------------------------------------------------------------------------- 1 | from group_ops import add, multiply, Z1 2 | from secrets import randbelow 3 | 4 | from fiat_shamir import hash_integers 5 | from utils import compute_multiexp, compute_innerprod, inverse, curve_order, int_to_binaryintarray 6 | 7 | from timeit import default_timer as timer 8 | 9 | def prove_multiexp_and_gprod_inner(current_hash, crs, vec_b, vec_c,inner_prod, 10 | ciphertexts_1, ciphertexts_2, vec_exp, n, logn): 11 | [crs_g, crs_h_scaled, u] = crs[:] 12 | crs_h = crs_g[:] 13 | 14 | proof = [] 15 | 16 | ### Adding in zero knowledge 17 | vec_rgp = [0]*n; vec_sgp = [0]*n; vec_rme = [0]*n; 18 | for i in range(n): 19 | vec_rgp[i] = randbelow(curve_order) 20 | vec_sgp[i] = randbelow(curve_order) 21 | vec_rme[i] = randbelow(curve_order) 22 | 23 | Rgp = compute_multiexp(crs_g[:], vec_rgp[:]) 24 | Sgp = compute_multiexp(crs_h_scaled[:], vec_sgp[:]) 25 | blgp1 = (compute_innerprod(vec_b[:], vec_sgp[:]) + compute_innerprod(vec_c[:], vec_rgp[:])) % curve_order 26 | blgp2 = compute_innerprod(vec_rgp[:], vec_sgp[:]) 27 | 28 | Rme = compute_multiexp(crs_h[:], vec_rme[:]) 29 | Bl1me = compute_multiexp(ciphertexts_1[:], vec_rme[:]) 30 | Bl2me = compute_multiexp(ciphertexts_2[:], vec_rme[:]) 31 | 32 | zkinfo = [Rgp, Sgp, Rme, blgp1, blgp2, Bl1me, Bl2me] 33 | 34 | current_hash = hash_integers([current_hash,int(Rgp[0]),int(Rgp[1]), int(Rgp[2]), 35 | int(Sgp[0]),int(Sgp[1]), int(Sgp[2]), 36 | blgp1, blgp2, 37 | int(Rme[0]),int(Rme[1]), int(Rme[2]), 38 | int(Bl1me[0]),int(Bl1me[1]), int(Bl1me[2]),int(Bl2me[0]),int(Bl2me[1]), int(Bl2me[2])]) 39 | x = current_hash % curve_order 40 | 41 | inner_prod = (inner_prod + blgp1 * x + blgp2 * x**2) % curve_order 42 | for i in range(n): 43 | vec_b[i] = (vec_b[i] + vec_rgp[i] * x) % curve_order 44 | vec_c[i] = (vec_c[i] + vec_sgp[i] * x) % curve_order 45 | vec_exp[i] = (vec_exp[i] + vec_rme[i] * x) % curve_order 46 | 47 | 48 | ### Inserting inner_prod into exponent. 49 | current_hash = hash_integers([current_hash,inner_prod]) 50 | x = current_hash % curve_order; 51 | u = multiply(u, x) 52 | 53 | for j in range(logn): 54 | n = n // 2 55 | 56 | zLgp = compute_innerprod(vec_b[n:], vec_c[:n]) 57 | zRgp = compute_innerprod(vec_b[:n], vec_c[n:]) 58 | zLme = [compute_multiexp(ciphertexts_1[n:], vec_exp[:n]), compute_multiexp(ciphertexts_2[n:], vec_exp[:n])] 59 | zRme = [compute_multiexp(ciphertexts_1[:n], vec_exp[n:]), compute_multiexp(ciphertexts_2[:n], vec_exp[n:])] 60 | 61 | CLgp_b = add( compute_multiexp(crs_g[:n], vec_b[n:]), multiply(u, zLgp)) 62 | CLgp_c = compute_multiexp(crs_h_scaled[n:],vec_c[:n]) 63 | 64 | CRgp_b = add(compute_multiexp(crs_g[n:], vec_b[:n]), multiply(u, zRgp)) 65 | CRgp_c = compute_multiexp(crs_h_scaled[:n],vec_c[n:]) 66 | CLme = compute_multiexp(crs_h[n:], vec_exp[:n]) 67 | CRme = compute_multiexp(crs_h[:n], vec_exp[n:]) 68 | 69 | proof.append([CLgp_b, CLgp_c, CRgp_b, CRgp_c, zLme, zRme, CLme, CRme]) 70 | 71 | current_hash = hash_integers([current_hash,int(CLgp_b[0]),int(CLgp_b[1]), int(CLgp_b[2]), 72 | int(CLgp_c[0]),int(CLgp_c[1]), int(CLgp_c[2]), 73 | int(CRgp_b[0]), int(CRgp_b[1]), int(CRgp_b[2]), 74 | int(CRgp_c[0]), int(CRgp_c[1]), int(CRgp_c[2]), 75 | int(zLme[0][0]), int(zLme[0][1]), int(zLme[0][2]), 76 | int(zRme[0][0]), int(zRme[0][1]), int(zRme[0][2]), int(CLme[0]),int(CLme[1]), int(CLme[2]), 77 | int(CRme[0]), int(CRme[1]), int(CRme[2])]) 78 | 79 | x = current_hash % curve_order; inv_x =inverse(x); 80 | 81 | for i in range(n): 82 | crs_g[i] = add(multiply(crs_g[n + i],inv_x), crs_g[i] ) 83 | crs_h_scaled[i] = add(multiply(crs_h_scaled[n + i],x), crs_h_scaled[i] ) 84 | vec_b[i] = (vec_b[i] + x * vec_b[n + i] ) % curve_order 85 | vec_c[i] = (vec_c[i] + inv_x * vec_c[n + i] ) % curve_order 86 | 87 | crs_h[i] = add(multiply(crs_h[n + i],x), crs_h[i] ) 88 | ciphertexts_1[i] = add(multiply(ciphertexts_1[n + i], x), ciphertexts_1[i]) 89 | ciphertexts_2[i] = add(multiply(ciphertexts_2[n + i], x), ciphertexts_2[i]) 90 | 91 | vec_exp[i] = (vec_exp[n + i] * inv_x + vec_exp[i]) % curve_order 92 | 93 | crs_g = crs_g[:n]; crs_h_scaled = crs_h_scaled[:n] 94 | vec_b = vec_b[:n]; vec_c = vec_c[:n] 95 | 96 | crs_h = crs_h[:n] 97 | ciphertexts_1 = ciphertexts_1[:n] 98 | ciphertexts_2 = ciphertexts_2[:n] 99 | 100 | vec_exp = vec_exp[:n] 101 | 102 | final_values = [vec_b[0], vec_c[0], vec_exp[0]] 103 | current_hash = hash_integers([current_hash, vec_b[0], vec_c[0], vec_exp[0]]) 104 | 105 | return [current_hash, [zkinfo[:], proof[:], final_values[:]]] 106 | 107 | def verify_multiexp_and_gprod_inner(current_hash, crs, vec_crs_h_exp, len_gprod, B, C, inner_prod, 108 | ciphertexts_1, ciphertexts_2, commit_exps, multiexp_1, multiexp_2, inner_proof,n, logn): 109 | [crs_g, u, crs_se1, crs_se2] = crs[:] 110 | 111 | ### Adding in zero knowledge 112 | [zkinfo, proof, final_values] = inner_proof[:] 113 | [Rgp, Sgp, Rme, blgp1, blgp2, Bl1me, Bl2me] = zkinfo[:] 114 | 115 | current_hash = hash_integers([current_hash,int(Rgp[0]),int(Rgp[1]), int(Rgp[2]), 116 | int(Sgp[0]),int(Sgp[1]), int(Sgp[2]), blgp1, blgp2, 117 | int(Rme[0]),int(Rme[1]), int(Rme[2]), 118 | int(Bl1me[0]),int(Bl1me[1]), int(Bl1me[2]),int(Bl2me[0]),int(Bl2me[1]), int(Bl2me[2])]) 119 | x = current_hash % curve_order 120 | 121 | inner_prod = (inner_prod + blgp1 * x + blgp2 * x**2) % curve_order 122 | B = add(B, multiply(Rgp,x)) 123 | C = add(C, multiply(Sgp,x)) 124 | commit_exps = add(commit_exps, multiply(Rme, x)) 125 | multiexp_1 = add(multiexp_1, multiply(Bl1me, x)) 126 | multiexp_2 = add(multiexp_2, multiply(Bl2me, x)) 127 | 128 | ### Putting inner_prod into exponent. 129 | current_hash = hash_integers([current_hash,inner_prod]) 130 | x = current_hash % curve_order; 131 | 132 | u = multiply(u, x) 133 | B = add(B, multiply(u,inner_prod)) 134 | 135 | [final_b, final_c, final_exp] = final_values[:] 136 | vec_crs_g_exp = [final_b] * n; 137 | vec_crs_h_shifted = [1] * n; 138 | 139 | n_var = n 140 | for j in range(logn): 141 | n_var = n_var // 2 142 | 143 | [CLgp_b, CLgp_c, CRgp_b, CRgp_c, zLme, zRme, CLme, CRme] = proof[j] 144 | 145 | current_hash = hash_integers([current_hash,int(CLgp_b[0]),int(CLgp_b[1]), int(CLgp_b[2]), 146 | int(CLgp_c[0]),int(CLgp_c[1]), int(CLgp_c[2]), 147 | int(CRgp_b[0]), int(CRgp_b[1]), int(CRgp_b[2]), 148 | int(CRgp_c[0]), int(CRgp_c[1]), int(CRgp_c[2]), 149 | int(zLme[0][0]), int(zLme[0][1]), int(zLme[0][2]), 150 | int(zRme[0][0]), int(zRme[0][1]), int(zRme[0][2]), int(CLme[0]),int(CLme[1]), int(CLme[2]), 151 | int(CRme[0]), int(CRme[1]), int(CRme[2])]) 152 | 153 | x = current_hash % curve_order; inv_x =inverse(x) 154 | 155 | for i in range(n): 156 | bin_i = int_to_binaryintarray(i,logn) 157 | if bin_i[logn - j - 1] == 1: 158 | vec_crs_g_exp[i] = (vec_crs_g_exp[i] * inv_x) % curve_order 159 | vec_crs_h_shifted[i] = (vec_crs_h_shifted[i] * x) % curve_order 160 | 161 | B = add(add(multiply(CRgp_b, inv_x), B), multiply(CLgp_b, x)) 162 | C = add(add(multiply(CRgp_c, inv_x), C), multiply(CLgp_c, x)) 163 | multiexp_1 = add(add( multiply(zLme[0],x), multiexp_1 ), multiply(zRme[0], inv_x) ) 164 | multiexp_2 = add(add( multiply(zLme[1],x), multiexp_2 ), multiply(zRme[1], inv_x) ) 165 | 166 | commit_exps = add(add(multiply(CRme, inv_x), commit_exps), multiply(CLme, x)) 167 | 168 | ciphertexts_1_final = compute_multiexp(ciphertexts_1[:], vec_crs_h_shifted[:]) 169 | ciphertexts_2_final = compute_multiexp(ciphertexts_2[:], vec_crs_h_shifted[:]) 170 | 171 | if add( multiply(ciphertexts_1_final, curve_order - final_exp), multiexp_1) != (1,1,0): 172 | print("ERROR: final ciphertext 1 is incorrect") 173 | return [current_hash, 0] 174 | 175 | if add( multiply(ciphertexts_2_final, curve_order - final_exp), multiexp_2) != (1,1,0): 176 | print("ERROR: final ciphertext 2 is incorrect") 177 | return [current_hash, 0] 178 | 179 | current_hash = hash_integers([current_hash, final_b, final_c, final_exp]) 180 | x = current_hash % curve_order 181 | 182 | vec_crs_h_exp[0] = ( x**2 * vec_crs_g_exp[0] + 183 | x * vec_crs_h_shifted[0] * final_exp + 184 | vec_crs_h_exp[0] * vec_crs_h_shifted[len_gprod - 1] * final_c) % curve_order 185 | for i in range(1,len_gprod): 186 | vec_crs_h_exp[i] = (x**2 * vec_crs_g_exp[i] + x * vec_crs_h_shifted[i] * final_exp + 187 | vec_crs_h_exp[i] * vec_crs_h_shifted[i-1] * final_c) % curve_order 188 | 189 | for i in range(len_gprod,n): 190 | vec_crs_h_exp[i] = (x**2 * vec_crs_g_exp[i] + x * vec_crs_h_shifted[i] * final_exp 191 | + vec_crs_h_exp[i] * vec_crs_h_shifted[i] * final_c) % curve_order 192 | 193 | inner_prod = final_b * final_c % curve_order 194 | 195 | expected_outcome = compute_multiexp(crs_g[:], vec_crs_h_exp[:]) 196 | expected_outcome = add(expected_outcome, multiply(u, (inner_prod * x**2 ) % curve_order)) 197 | expected_outcome = add(expected_outcome, multiply(commit_exps, curve_order - x)) 198 | expected_outcome = add(expected_outcome, multiply(C, curve_order - 1)) 199 | expected_outcome = add(expected_outcome, multiply(B, (- x**2 ) % curve_order ) ) 200 | 201 | if expected_outcome != Z1: 202 | print("ERROR: final exponent is incorrect") 203 | return [current_hash, 0] 204 | 205 | return [current_hash, 1] 206 | -------------------------------------------------------------------------------- /python_code/libff.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ethresearch/Shuffle_SSLE/16761f8a90251c1aa32b52563b221c8df2a978fe/python_code/libff.dylib -------------------------------------------------------------------------------- /python_code/multiexp.py: -------------------------------------------------------------------------------- 1 | from group_ops import add, multiply, Z1 2 | from secrets import randbelow 3 | from fiat_shamir import hash_integers 4 | 5 | from utils import compute_multiexp, curve_order 6 | 7 | def multiexp_prove(current_hash, crs, ciphertexts_R, ciphertexts_S, exponents, n,logn): 8 | proof = [] 9 | 10 | ### Adding in zero knowledge 11 | vec_r = [0]*n; 12 | for i in range(n): 13 | vec_r[i] = randbelow(curve_order) 14 | 15 | R = compute_multiexp(crs[:], vec_r[:]) 16 | Rbl = compute_multiexp(ciphertexts_R[:], vec_r[:]) 17 | Sbl = compute_multiexp(ciphertexts_S[:], vec_r[:]) 18 | 19 | current_hash = hash_integers([current_hash,int(R[0]),int(R[1]), int(R[2]), 20 | int(Rbl[0]),int(Rbl[1]), int(Rbl[2]),int(Sbl[0]),int(Sbl[1]), int(Sbl[2])]) 21 | x = current_hash % curve_order 22 | 23 | for i in range(n): 24 | exponents[i] = (exponents[i] + vec_r[i] * x) % curve_order 25 | 26 | for j in range(logn): 27 | n = n // 2 28 | 29 | zL = [compute_multiexp(ciphertexts_R[n:], exponents[:n]), compute_multiexp(ciphertexts_S[n:], exponents[:n])] 30 | zR = [compute_multiexp(ciphertexts_R[:n], exponents[n:]), compute_multiexp(ciphertexts_S[:n], exponents[n:])] 31 | CL = compute_multiexp(crs[n:], exponents[:n]) 32 | CR = compute_multiexp(crs[:n], exponents[n:]) 33 | 34 | proof.append([zL, zR, CL, CR]) 35 | 36 | current_hash = hash_integers([current_hash,int(zL[0][0]), int(zL[0][1]),int(zR[0][0]), 37 | int(zR[0][1]),int(CL[0]),int(CL[1]),int(CR[0]), int(CR[1])]) 38 | 39 | x = current_hash % curve_order; inv_x =inverse(x); 40 | 41 | for i in range(n): 42 | crs[i] = add(multiply(crs[n + i],x), crs[i] ) 43 | ciphertexts_R[i] = add(multiply(ciphertexts_R[n + i], x), ciphertexts_R[i]) 44 | ciphertexts_S[i] = add(multiply(ciphertexts_S[n + i], x), ciphertexts_S[i]) 45 | 46 | crs = crs[:n] 47 | ciphertexts_R = ciphertexts_R[:n] 48 | ciphertexts_S = ciphertexts_S[:n] 49 | 50 | for i in range(n): 51 | exponents[i] = (exponents[n + i] * inv_x + exponents[i] ) % curve_order 52 | 53 | exponents = exponents[:n] 54 | 55 | return [current_hash,[R, Rbl, Sbl, proof, exponents[0]]] 56 | 57 | def multiexp_verify(current_hash, crs, ciphertexts_R, ciphertexts_S, commit_exps, ip_proof, multiexp_R, multiexp_S, n,logn): 58 | [R, Rbl, Sbl, proof, last_exp] = ip_proof[:] 59 | 60 | ### Adding zero-knowledge 61 | 62 | current_hash = hash_integers([current_hash,int(R[0]),int(R[1]), int(R[2]), 63 | int(Rbl[0]),int(Rbl[1]), int(Rbl[2]),int(Sbl[0]),int(Sbl[1]), int(Sbl[2])]) 64 | x = current_hash % curve_order 65 | 66 | commit_exps = add(commit_exps, multiply(R, x)) 67 | multiexp_R = add(multiexp_R, multiply(Rbl, x)) 68 | multiexp_S = add(multiexp_S, multiply(Sbl, x)) 69 | 70 | vec_crs_exp = [1] * n 71 | n_var = n 72 | 73 | for j in range(logn): 74 | n_var = n_var // 2 75 | ## print("i = ", i, "commit_exps = ", commit_exps) 76 | [zL, zR, CL, CR] = proof[j] 77 | 78 | current_hash = hash_integers([current_hash,int(zL[0][0]), int(zL[0][1]),int(zR[0][0]), 79 | int(zR[0][1]),int(CL[0]),int(CL[1]),int(CR[0]), int(CR[1])]) 80 | 81 | x = current_hash; inv_x =inverse(x) 82 | 83 | for i in range(n): 84 | bin_i = int_to_binaryintarray(i,logn) 85 | if bin_i[logn - j - 1] == 1: 86 | vec_crs_exp[i] = (vec_crs_exp[i] * x) % curve_order 87 | 88 | multiexp_R = add(add( multiply(zL[0],x), multiexp_R ), multiply(zR[0], inv_x) ) 89 | multiexp_S = add(add( multiply(zL[1],x), multiexp_S ), multiply(zR[1], inv_x) ) 90 | 91 | commit_exps = add(add(multiply(CR, inv_x), commit_exps), multiply(CL, x)) 92 | 93 | 94 | crs_final = compute_multiexp(crs[:], vec_crs_exp[:]) 95 | R_final = compute_multiexp(ciphertexts_R[:], vec_crs_exp[:]) 96 | S_final = compute_multiexp(ciphertexts_S[:], vec_crs_exp[:]) 97 | 98 | if add( multiply(crs_final, curve_order - last_exp), commit_exps) != (1,1,0): 99 | print("ERROR: final exponent is incorrect") 100 | return [current_hash, 0] 101 | 102 | if add( multiply(R_final, curve_order - last_exp), multiexp_R) != (1,1,0): 103 | print("ERROR: final ciphertext R is incorrect") 104 | return [current_hash, 0] 105 | 106 | if add( multiply(S_final, curve_order - last_exp), multiexp_S) != (1,1,0): 107 | print("ERROR: final ciphertext S is incorrect") 108 | return [current_hash, 0] 109 | 110 | return [current_hash, 1] 111 | -------------------------------------------------------------------------------- /python_code/prove.py: -------------------------------------------------------------------------------- 1 | from group_ops import add, multiply, Z1 2 | from timeit import default_timer as timer 3 | 4 | from random import randint 5 | from secrets import randbelow 6 | import math 7 | 8 | from fiat_shamir import hash_integers 9 | from gprod import gprod_prove_outer as gprod_prove, gprod_verify_outer as gprod_verify 10 | from sameexp import sameexp_prove, sameexp_verify 11 | from inner_product import prove_multiexp_and_gprod_inner, verify_multiexp_and_gprod_inner 12 | from utils import compute_multiexp, compute_innerprod, inverse, int_to_binaryintarray, curve_order 13 | 14 | def shuffle(ciphertexts_R, ciphertexts_S): 15 | n = len(ciphertexts_R); 16 | leftover_values = [0] * n; 17 | for i in range(n): 18 | leftover_values[i] = i; 19 | 20 | shuffle = [0] * n 21 | for i in range(n): 22 | k = randint(0, n - i - 1 ) 23 | shuffle[i] = leftover_values.pop(k) 24 | 25 | ciphertexts_shuffled_R = [0] * n 26 | ciphertexts_shuffled_S = [0] * n 27 | for i in range(n): 28 | ciphertexts_shuffled_R[i] = ciphertexts_R[shuffle[i]][:] 29 | ciphertexts_shuffled_S[i] = ciphertexts_S[shuffle[i]][:] 30 | 31 | r = randbelow(curve_order) 32 | for i in range(n): 33 | ciphertexts_shuffled_R[i] = multiply(ciphertexts_shuffled_R[i], r) 34 | ciphertexts_shuffled_S[i] = multiply(ciphertexts_shuffled_S[i], r) 35 | 36 | 37 | return (ciphertexts_shuffled_R, ciphertexts_shuffled_S, shuffle, r) 38 | 39 | 40 | def shuffle_prove(crs, num_blinders, ciphertexts_R, ciphertexts_S, ciphertexts_T, ciphertexts_U, shuffle, r): 41 | 42 | [crs_g, u, crs_se1, crs_se2] = crs[:] 43 | n = len(ciphertexts_R) + num_blinders 44 | logn = int(math.log(n,2)) 45 | 46 | vec_m = [0] * n 47 | for i in range(len(ciphertexts_R)): 48 | vec_m[i] = shuffle[i] 49 | 50 | for i in range(len(ciphertexts_R), n): 51 | vec_m[i] = randbelow(curve_order) 52 | 53 | M = compute_multiexp(crs_g[:], vec_m[:]) 54 | 55 | current_hash = hash_integers([int(M[0]), int(M[1]), int(M[2])]) 56 | for i in range(len(ciphertexts_T)): 57 | current_hash = hash_integers([current_hash, int(ciphertexts_T[i][0]), 58 | int(ciphertexts_T[i][1]), int(ciphertexts_T[i][2]), 59 | int(ciphertexts_U[i][0]), int(ciphertexts_U[i][1]), 60 | int(ciphertexts_U[i][2])]) 61 | 62 | print("current_hash = ", current_hash) 63 | 64 | vec_a = [0] * len(ciphertexts_R) 65 | for i in range(len(ciphertexts_R)): 66 | vec_a[i] = current_hash % curve_order 67 | current_hash = hash_integers([current_hash]) 68 | 69 | vec_a_shuffled = [0] * n 70 | for i in range(len(ciphertexts_R)): 71 | vec_a_shuffled[i] = vec_a[shuffle[i]] 72 | 73 | for i in range(len(ciphertexts_R), n): 74 | vec_a_shuffled[i] = randbelow(curve_order) 75 | 76 | A = compute_multiexp(crs_g[:], vec_a_shuffled[:]) 77 | 78 | current_hash = hash_integers([current_hash, int(A[0]), int(A[1]), int(A[2])]) 79 | alpha = current_hash % curve_order 80 | 81 | current_hash = hash_integers([current_hash]) 82 | beta = current_hash % curve_order 83 | 84 | vec_gprod = vec_a_shuffled[:] 85 | for i in range(n): 86 | vec_gprod[i] = (vec_gprod[i] + vec_m[i] * alpha + beta ) % curve_order 87 | 88 | gprod = 1 89 | for i in range(len(ciphertexts_R)): 90 | gprod = (gprod * vec_gprod[i] ) % curve_order 91 | 92 | start = timer() 93 | [current_hash, gprod_proof, inner_prod_info] = gprod_prove(current_hash, crs[:], vec_gprod[:], len(ciphertexts_R), gprod, n, logn) 94 | end = timer() 95 | print("gprod time = ", end - start) 96 | 97 | [crs_h, vec_b, vec_c, inner_prod] = inner_prod_info[:] 98 | 99 | start = timer() 100 | R = compute_multiexp(ciphertexts_R[:], vec_a[:]) 101 | S = compute_multiexp(ciphertexts_S[:], vec_a[:]) 102 | end = timer() 103 | print("R, S time = ", end - start, len(vec_a[:len(ciphertexts_R)])) 104 | 105 | vec_gammas = [0]* num_blinders; vec_deltas = [0] * num_blinders; 106 | current_hash = hash_integers([current_hash, int(A[0]), int(A[1]), int(A[2])]) 107 | for i in range(num_blinders): 108 | current_hash = hash_integers([current_hash]) 109 | vec_gammas[i] = current_hash % curve_order 110 | current_hash = hash_integers([current_hash]) 111 | vec_deltas[i] = current_hash % curve_order 112 | 113 | blinder_t = 0; blinder_u = 0; 114 | for i in range(num_blinders): 115 | blinder_t = (blinder_t + vec_gammas[i] * vec_a_shuffled[len(ciphertexts_R) + i]) % curve_order; 116 | blinder_u = (blinder_u + vec_deltas[i] * vec_a_shuffled[len(ciphertexts_R) + i]) % curve_order; 117 | 118 | T = add(multiply(R, r), multiply(crs_se1, blinder_t)); 119 | U = add(multiply(S, r), multiply(crs_se2, blinder_u)); 120 | 121 | for i in range(num_blinders): 122 | ciphertexts_T.append(multiply(crs_se1, vec_gammas[i])) 123 | ciphertexts_U.append(multiply(crs_se2, vec_deltas[i])) 124 | 125 | (current_hash, sameexp_proof) = sameexp_prove(current_hash, R, S, crs_se1, crs_se2, T, U, r, blinder_t, blinder_u) 126 | 127 | start = timer() 128 | crs = [crs_g[:], crs_h[:], u] 129 | [current_hash, gprod_and_multiexp_proof] = prove_multiexp_and_gprod_inner(current_hash, 130 | crs[:], vec_b[:], vec_c[:],inner_prod, 131 | ciphertexts_T[:], ciphertexts_U[:], vec_a_shuffled[:], n, logn) 132 | end = timer() 133 | print("inner product time = ", end - start) 134 | 135 | return [M, A, gprod_proof[:], T, U, sameexp_proof, gprod_and_multiexp_proof] 136 | 137 | def shuffle_verify(crs, num_blinders, ciphertexts_R, ciphertexts_S, ciphertexts_T, ciphertexts_U, shuffle_proof): 138 | 139 | [crs_g, u, crs_se1, crs_se2] = crs[:] 140 | n = len(ciphertexts_R) + num_blinders 141 | logn = int(math.log(n,2)) 142 | 143 | [M, A, gprod_proof, T, U, sameexp_proof, inner_proof] = shuffle_proof[:] 144 | 145 | current_hash = hash_integers([int(M[0]), int(M[1]), int(M[2])]) 146 | for i in range(len(ciphertexts_T)): 147 | current_hash = hash_integers([current_hash, int(ciphertexts_T[i][0]), 148 | int(ciphertexts_T[i][1]), int(ciphertexts_T[i][2]), 149 | int(ciphertexts_U[i][0]), int(ciphertexts_U[i][1]), 150 | int(ciphertexts_U[i][2])]) 151 | 152 | vec_a = [0] * len(ciphertexts_R) 153 | for i in range(len(ciphertexts_R)): 154 | vec_a[i] = current_hash % curve_order 155 | current_hash = hash_integers([current_hash]) 156 | 157 | current_hash = hash_integers([current_hash, int(A[0]), int(A[1]), int(A[2])]) 158 | alpha = current_hash % curve_order 159 | 160 | current_hash = hash_integers([current_hash]) 161 | beta = current_hash % curve_order 162 | 163 | gprod = 1 164 | for i in range(len(ciphertexts_R)): 165 | gprod = (gprod * (vec_a[i] + i * alpha + beta) ) % curve_order 166 | 167 | A1 = crs_g[0] 168 | for i in range(1,n): 169 | A1 = add(A1, crs_g[i]) 170 | A1 = multiply(A1, beta) 171 | A1 = add(A1, multiply(M, alpha)) 172 | A1 = add(A1, A) 173 | 174 | start = timer() 175 | [current_hash, inner_prod_info] = gprod_verify(current_hash, crs[:], A1, len(ciphertexts_R), gprod, 176 | gprod_proof[:],n,logn) 177 | end = timer() 178 | print("gprod time = ", end - start) 179 | [vec_crs_h_exp, B, C, inner_prod, len_gprod] = inner_prod_info[:] 180 | 181 | start = timer() 182 | R = compute_multiexp(ciphertexts_R[:], vec_a[:]) 183 | S = compute_multiexp(ciphertexts_S[:], vec_a[:]) 184 | end = timer() 185 | 186 | print("R, S time = ", end - start) 187 | 188 | vec_gammas = [0]* num_blinders; vec_deltas = [0] * num_blinders; 189 | current_hash = hash_integers([current_hash, int(A[0]), int(A[1]), int(A[2])]) 190 | for i in range(num_blinders): 191 | current_hash = hash_integers([current_hash]) 192 | vec_gammas[i] = current_hash % curve_order 193 | current_hash = hash_integers([current_hash]) 194 | vec_deltas[i] = current_hash % curve_order 195 | 196 | (current_hash, b) = sameexp_verify(current_hash, R, S, crs_se1, crs_se2, T, U, sameexp_proof[:]) 197 | 198 | if b != 1: 199 | print("VERIFICATION FAILURE: does not have same exponent") 200 | return 0 201 | 202 | for i in range(num_blinders): 203 | ciphertexts_T.append(multiply(crs_se1, vec_gammas[i])) 204 | ciphertexts_U.append(multiply(crs_se2, vec_deltas[i])) 205 | 206 | 207 | start = timer() 208 | [current_hash, b] = verify_multiexp_and_gprod_inner(current_hash, crs[:], vec_crs_h_exp, len_gprod, B, C, inner_prod, 209 | ciphertexts_T[:], ciphertexts_U[:], A, T, U, inner_proof[:],n, logn) 210 | end = timer() 211 | 212 | print("inner product time = ", end - start) 213 | 214 | if b != 1: 215 | print("VERIFICATION FAILURE: does not have correct inner product") 216 | return 0 217 | 218 | return 1 219 | -------------------------------------------------------------------------------- /python_code/sameexp.py: -------------------------------------------------------------------------------- 1 | from group_ops import add, multiply, Z1 2 | from fiat_shamir import hash_integers 3 | from utils import curve_order 4 | from secrets import randbelow 5 | 6 | def sameexp_prove(current_hash, g1, g2, h1, h2, y1, y2, exp, bl1, bl2): 7 | 8 | r = randbelow(curve_order) 9 | s = randbelow(curve_order) 10 | t = randbelow(curve_order) 11 | R1 = add(multiply(g1, r), multiply(h1, s)); 12 | R2 = add(multiply(g2, r), multiply(h2, t)); 13 | 14 | current_hash = hash_integers([current_hash, int(g1[0]), int(g1[1]), int(g1[2]), 15 | int(g2[0]), int(g2[1]), int(g2[2]),int(y1[0]), int(y1[1]), int(y1[2]), 16 | int(y2[0]), int(y2[1]), int(y2[2]), int(R1[0]), int(R1[1]), int(R1[2]), 17 | int(R2[0]), int(R2[1]), int(R2[2])]) 18 | 19 | x = current_hash % curve_order 20 | 21 | u1 = (r + x * exp) % curve_order 22 | u2 = (s + x * bl1) % curve_order 23 | u3 = (t + x * bl2) % curve_order 24 | 25 | return (current_hash, [R1, R2, u1, u2, u3]) 26 | 27 | def sameexp_verify(current_hash, g1, g2, h1, h2, y1, y2, sameexp_proof): 28 | 29 | [R1, R2,u1, u2, u3] = sameexp_proof[:] 30 | 31 | current_hash = hash_integers([current_hash, int(g1[0]), int(g1[1]), int(g1[2]), 32 | int(g2[0]), int(g2[1]), int(g2[2]),int(y1[0]), int(y1[1]), int(y1[2]), 33 | int(y2[0]), int(y2[1]), int(y2[2]), int(R1[0]), int(R1[1]), int(R1[2]), 34 | int(R2[0]), int(R2[1]), int(R2[2])]) 35 | 36 | x = current_hash % curve_order 37 | 38 | outcome1 = add(R1, multiply(y1, x)) 39 | outcome1 = add(outcome1, multiply(g1, curve_order - u1)) 40 | outcome1 = add(outcome1, multiply(h1, curve_order - u2)) 41 | 42 | outcome2 = add(R2, multiply(y2, x)) 43 | outcome2 = add(outcome2, multiply(g2, curve_order - u1)) 44 | outcome2 = add(outcome2, multiply(h2, curve_order - u3)) 45 | 46 | if outcome1 != Z1: 47 | print("ERROR: schnorr proof doesn't verify Z1") 48 | return (current_hash, 0) 49 | 50 | if outcome2 != Z1: 51 | print("ERROR: schnorr proof doesn't verify Z2") 52 | return (current_hash, 0) 53 | 54 | return (current_hash, 1) 55 | -------------------------------------------------------------------------------- /python_code/setup.py: -------------------------------------------------------------------------------- 1 | from group_ops import add, multiply, Z1, G1 2 | from random import randint 3 | from utils import curve_order 4 | 5 | ##### Totally insecure setup. Just a placeholder. Replace before usage. 6 | def get_crs(n): 7 | crs = [0]*n 8 | 9 | 10 | for i in range(n): 11 | a = randint(1,curve_order-1) 12 | crs[i] = multiply(G1, a) 13 | 14 | return crs 15 | 16 | ##### Generation of example ciphertexts. For testing. 17 | def get_ciphertexts(n): 18 | ciphertexts_R = [0]*n 19 | ciphertexts_S = [0]*n 20 | 21 | for i in range(n): 22 | r = randint(1,curve_order-1) 23 | s = randint(1,curve_order-1) 24 | ciphertexts_R[i] = multiply(G1, r) 25 | ciphertexts_S[i] = multiply(G1, s) 26 | 27 | return [ciphertexts_R, ciphertexts_S] 28 | -------------------------------------------------------------------------------- /python_code/test.py: -------------------------------------------------------------------------------- 1 | from group_ops import add, multiply, Z1 2 | from timeit import default_timer as timer 3 | 4 | from setup import get_crs, get_ciphertexts 5 | 6 | from prove import shuffle, shuffle_prove, shuffle_verify 7 | from utils import compute_multiexp, curve_order 8 | from random import randint 9 | 10 | 11 | 12 | crs = get_crs(131) 13 | crs = [crs[:128],crs[128],crs[129],crs[130]] 14 | 15 | num_ciphertexts = 124 16 | num_blinders = 4 17 | 18 | [ciphertexts_R, ciphertexts_S] = get_ciphertexts(num_ciphertexts) 19 | 20 | print("start shuffle") 21 | start = timer() 22 | (ciphertexts_T, ciphertexts_U, shuffle, r) = shuffle(ciphertexts_R[:], ciphertexts_S[:]) 23 | end = timer() 24 | print("end shuffle", end - start) 25 | 26 | print("start prover") 27 | start = timer() 28 | shuffle_proof = shuffle_prove(crs[:], num_blinders, ciphertexts_R[:], ciphertexts_S[:], 29 | ciphertexts_T[:], ciphertexts_U[:], shuffle[:], r) 30 | end = timer() 31 | prover_time = end - start 32 | print("end prover", end - start) 33 | 34 | print("start verifier") 35 | start = timer() 36 | b = shuffle_verify(crs[:], num_blinders, ciphertexts_R[:], ciphertexts_S[:], 37 | ciphertexts_T[:], ciphertexts_U[:], shuffle_proof[:]) 38 | end = timer() 39 | verifier_time = end - start 40 | print("end verifier", end - start) 41 | 42 | print("prover_time =", prover_time, "verifier_time =", verifier_time) 43 | 44 | print("b = ", b) 45 | -------------------------------------------------------------------------------- /python_code/utils.py: -------------------------------------------------------------------------------- 1 | from py_ecc.optimized_bn128 import Z1 2 | from py_ecc.fields import optimized_bn128_FQ as FQ 3 | 4 | from group_ops import add, multiply 5 | import ctypes 6 | from ctypes import * 7 | cdll.LoadLibrary("libff.dylib") 8 | lib = CDLL("libff.dylib") 9 | 10 | curve_order = 21888242871839275222246405745257275088548364400416034343698204186575808495617 11 | 12 | def compute_innerprod(a,b): 13 | outcome = 0 14 | for i in range(len(a)): 15 | outcome = ( outcome + a[i] * b[i] ) % curve_order 16 | 17 | return outcome 18 | 19 | def arr_to_ctypes_arr(arr): 20 | ctypes_arr = (ctypes.c_char_p * len(arr))() 21 | ctypes_arr[:] = list(map(lambda x: int(x).to_bytes(32, 'little'), arr)) 22 | return ctypes_arr 23 | 24 | def compute_multiexp_2(a,b): 25 | 26 | outcome = multiply(a[0], b[0]) 27 | if len(a)==0: 28 | return outcome 29 | 30 | for i in range(1,len(a)): 31 | outcome = add(outcome, multiply(a[i], b[i])) 32 | 33 | return outcome 34 | 35 | def compute_multiexp(crs, vec): 36 | if vec == []: 37 | return Z1 38 | 39 | crs_subset = crs[:len(vec)] 40 | exponents = arr_to_ctypes_arr([vec[i] for i in range(len(vec))]) 41 | points_x = arr_to_ctypes_arr(list(map(lambda p: int(p[0]), crs_subset))) 42 | points_y = arr_to_ctypes_arr(list(map(lambda p: int(p[1]), crs_subset))) 43 | points_z = arr_to_ctypes_arr(list(map(lambda p: int(p[2]), crs_subset))) 44 | 45 | res_x = ctypes.c_buffer(32) 46 | res_y = ctypes.c_buffer(32) 47 | res_z = ctypes.c_buffer(32) 48 | lib.multiexp(exponents, len(exponents), points_x, points_y, points_z, len(crs_subset), res_x, res_y, res_z); 49 | F = (int.from_bytes(res_x, byteorder='little', signed=False), int.from_bytes(res_y, byteorder='little', signed=False), int.from_bytes(res_z, byteorder='little', signed=False)) 50 | 51 | # return (FQ(F[0]),FQ(F[1]),FQ(F[2])) 52 | return F 53 | 54 | 55 | def inverse(a): 56 | if a == 0: 57 | print("ERROR: No inverse exists") 58 | return "ERROR" 59 | 60 | a = a % curve_order; 61 | 62 | t1 = 0; 63 | t2 = 1; 64 | r1 = curve_order; 65 | r2 = a; 66 | 67 | while (r2 != 0): 68 | q = r1 // r2 ; 69 | t1old = t1; r1old = r1; 70 | 71 | t1 = t2; 72 | t2 = t1old - q * t2 73 | r1 = r2 74 | r2 = r1old - q * r2 75 | 76 | if (t1 < 0): 77 | return (curve_order + t1); 78 | return t1; 79 | 80 | def int_to_binaryintarray(x,logn): 81 | y = bin(x)[2:] 82 | z = [0] * (logn) 83 | for i in range(len(y)): 84 | z[i] = int(y[len(y) - i - 1]) 85 | return z 86 | -------------------------------------------------------------------------------- /rust_code/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "shuffle" 3 | version = "0.1.0" 4 | authors = ["mmaller "] 5 | edition = "2018" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | algebra = { git = "https://github.com/scipr-lab/zexe", package = "algebra", features = [ "bls12_381" ] } 11 | algebra-core = { git = "https://github.com/scipr-lab/zexe", package = "algebra-core", features = [ "parallel" ] } 12 | ff-fft = {git = "https://github.com/scipr-lab/zexe", package = "ff-fft"} 13 | #sha2 = "0.9.1" 14 | blake2 = "0.9.0" 15 | rand = "0.7.3" 16 | -------------------------------------------------------------------------------- /rust_code/src/main.rs: -------------------------------------------------------------------------------- 1 | mod shuffle; 2 | 3 | use shuffle::{setup, prove, verify}; 4 | 5 | use algebra::{bls12_381::{Fr, G1Affine}}; 6 | use algebra_core::{AffineCurve, curves::ProjectiveCurve}; 7 | 8 | use rand::{thread_rng,Rng}; 9 | use std::time::{Instant}; 10 | 11 | 12 | 13 | fn get_shuffle(ciph_r: &Vec, ciph_s: &Vec, ell: usize) -> 14 | (Vec, Vec, Vec, Fr) 15 | { 16 | let mut rng = thread_rng(); 17 | 18 | let mut vec_leftover: Vec = Vec::new(); 19 | for i in 0..ell { 20 | vec_leftover.push(i as u32); 21 | } 22 | 23 | let mut vec_shuffle: Vec = Vec::new(); 24 | for i in 0..ell { 25 | let k = rng.gen_range(0, ell - i); 26 | vec_shuffle.push(vec_leftover[k]); 27 | vec_leftover.retain(|&x| x != vec_shuffle[i]); 28 | } 29 | 30 | 31 | let mut ciph_t: Vec = Vec::new(); 32 | let mut ciph_u: Vec = Vec::new(); 33 | let r: Fr = rng.gen(); 34 | for i in 0..ell { 35 | ciph_t.push( ciph_r[vec_shuffle[i] as usize].mul(r).into_affine() ); 36 | ciph_u.push( ciph_s[vec_shuffle[i] as usize].mul(r).into_affine() ); 37 | } 38 | 39 | (ciph_t, ciph_u, vec_shuffle, r) 40 | } 41 | 42 | 43 | fn main() { 44 | let n: usize = 128; 45 | let ell: usize = n - 4; 46 | let logn: usize = 7; 47 | if (2 as u32).pow(logn as u32) != n as u32 { 48 | println!("Error, logn must equal log_2(n), should panic"); 49 | } 50 | 51 | let mut rng = thread_rng(); 52 | 53 | let now = Instant::now(); 54 | let crs = setup(n, logn, n - ell); 55 | let new_now = Instant::now(); 56 | println!("crs time = {:?}", new_now.duration_since(now)); 57 | 58 | let now = Instant::now(); 59 | let mut ciph_r: Vec = Vec::new(); 60 | let mut ciph_s: Vec = Vec::new(); 61 | 62 | let generator = G1Affine::prime_subgroup_generator(); 63 | for _i in 0..ell { 64 | let alpha1: Fr = rng.gen(); 65 | let alpha2: Fr = rng.gen(); 66 | ciph_r.push( generator.mul(alpha1).into_affine() ); 67 | ciph_s.push( generator.mul(alpha2).into_affine() ); 68 | } 69 | let new_now = Instant::now(); 70 | println!("shuffle time = {:?}", new_now.duration_since(now)); 71 | 72 | let (ciph_t, ciph_u, vec_shuffle, r) = get_shuffle(&ciph_r, &ciph_s, ell); 73 | 74 | let crs_cp = crs.clone(); 75 | let ciph_t_cp = ciph_t.clone(); 76 | let ciph_u_cp = ciph_u.clone(); 77 | 78 | let now = Instant::now(); 79 | let proof_shuffle = prove(crs_cp, &ciph_r, &ciph_s, ciph_t_cp, ciph_u_cp, vec_shuffle, r, 80 | ell, n, logn); 81 | let new_now = Instant::now(); 82 | println!("proving time = {:?}", new_now.duration_since(now)); 83 | 84 | let now = Instant::now(); 85 | let crs_cp = crs.clone(); 86 | let b = verify(crs_cp, ciph_r, ciph_s, ciph_t, ciph_u, proof_shuffle, ell, n, logn); 87 | let new_now = Instant::now(); 88 | println!("Verification passes = {:?}", b); 89 | println!("verifying time = {:?}", new_now.duration_since(now)); 90 | 91 | } 92 | -------------------------------------------------------------------------------- /rust_code/src/shuffle.rs: -------------------------------------------------------------------------------- 1 | use algebra::{bls12_381::{Fr, G1Affine, G1Projective}, 2 | ProjectiveCurve 3 | }; 4 | use algebra_core::{AffineCurve, msm::VariableBaseMSM, Zero, One, PrimeField, 5 | bytes::{ToBytes},to_bytes, fields::Field}; 6 | use rand::{thread_rng,Rng}; 7 | //use sha2::{Sha256, Digest}; 8 | use blake2::{Blake2b, Digest}; 9 | use std::time::{Instant}; 10 | 11 | 12 | // The Common Reference String (CRS) is available to both the prover and verifier and allows the verifier to 13 | // verify and make claims about committed values. 14 | #[derive(Clone)] 15 | pub struct CrsStruct { 16 | // Key used to generate proofs. 17 | pub crs_g: Vec, 18 | pub crs_h: Vec, 19 | pub u: G1Affine, 20 | pub crs_se1: G1Affine, 21 | pub crs_se2: G1Affine, 22 | pub crs_g_prod_ell: G1Projective, 23 | pub crs_g_prod_n: G1Projective, 24 | pub crs_gh: Vec, 25 | pub bitstring: Vec> 26 | } 27 | 28 | pub struct ShuffleProofStruct { 29 | pub g_m: G1Affine, 30 | pub g_a: G1Affine, 31 | pub proof_gprod: GprodProofStruct, 32 | pub g_r: G1Affine, 33 | pub g_s: G1Affine, 34 | pub g_t: G1Affine, 35 | pub g_u: G1Affine, 36 | pub proof_sameexp: SameexpProofStruct, 37 | pub proof_gpme: GpmeProofStruct, 38 | } 39 | 40 | pub struct GprodProofStruct { 41 | pub g_b: G1Affine, 42 | pub blinder: Fr, 43 | //pub proof_inner: GprodInnerProofStruct, 44 | } 45 | 46 | pub struct GprodProverInfoStruct { 47 | pub crs_h_scaled: Vec, 48 | pub vec_b: Vec, 49 | pub vec_c: Vec, 50 | pub inner_prod: Fr, 51 | } 52 | 53 | pub struct GprodVerifierInfoStruct { 54 | pub vec_crs_h_exp: Vec, 55 | pub g_b: G1Affine, 56 | pub g_c: G1Affine, 57 | pub inner_prod: Fr, 58 | } 59 | 60 | pub struct GpmeProofStruct { 61 | pub g_rgp: G1Affine, 62 | pub g_sgp: G1Affine, 63 | pub g_rme: G1Affine, 64 | pub blinder1_gp: Fr, 65 | pub blinder2_gp: Fr, 66 | pub g_mebl1: G1Affine, 67 | pub g_mebl2: G1Affine, 68 | pub proof: Vec<[G1Affine; 10]>, 69 | pub b_final: Fr, 70 | pub c_final: Fr, 71 | pub a_final: Fr, 72 | } 73 | 74 | pub struct SameexpProofStruct { 75 | pub g_r1: G1Affine, 76 | pub g_r2: G1Affine, 77 | pub u1: Fr, 78 | pub u2: Fr, 79 | pub u3: Fr, 80 | } 81 | 82 | #[derive(Clone)] 83 | pub struct FinalExpStruct { 84 | base: Vec, 85 | exponents: Vec, 86 | } 87 | 88 | pub fn hash_values(hash_input: Vec) -> Vec { 89 | //let mut hasher = Sha256::new(); 90 | let mut hasher = Blake2b::new(); 91 | hasher.update(hash_input); 92 | let current_hash = hasher.finalize(); 93 | current_hash.to_vec() 94 | } 95 | 96 | pub fn get_challenge_from_current_hash(current_hash: &Vec) -> Fr { 97 | 98 | //Sometimes x is None. Hash again if this happens. 99 | // let y = loop { 100 | // let x = Fr::from_random_bytes(¤t_hash); 101 | // if x != None { 102 | // break x; 103 | // } 104 | // current_hash = hash_values(current_hash); 105 | // }; 106 | 107 | let y = Fr::from_random_bytes(¤t_hash[..31]); 108 | 109 | let z = y.unwrap(); 110 | z 111 | } 112 | 113 | pub fn get_inner_prod(a: &Vec, b: &Vec) -> Fr { 114 | let mut c: Fr = Fr::zero(); 115 | for i in 0..a.len() { 116 | c += a[i] * b[i]; 117 | } 118 | c 119 | } 120 | 121 | pub fn add_to_final_expo(mut final_exps: FinalExpStruct, base_input: G1Affine, exponents_input: Fr) -> FinalExpStruct { 122 | final_exps.base.push(base_input); 123 | final_exps.exponents.push(exponents_input); 124 | final_exps 125 | } 126 | 127 | /// Totally insecure setup function. Need to directly hash to curve to make secure. 128 | pub fn setup(n: usize, logn: usize, num_blinders: usize) -> CrsStruct{ 129 | let mut rng = thread_rng(); 130 | 131 | let generator = G1Affine::prime_subgroup_generator(); 132 | 133 | let mut c1: Vec=Vec::new(); 134 | let mut c2: Vec=Vec::new(); 135 | 136 | for _i in 0..n { 137 | let alpha1: Fr = rng.gen(); 138 | let alpha2: Fr = rng.gen(); 139 | c1.push( generator.mul(alpha1).into_affine() ); 140 | c2.push( generator.mul(alpha2).into_affine() ); 141 | } 142 | 143 | let alpha: Fr = rng.gen(); 144 | let c3: G1Affine = generator.mul(alpha).into_affine(); 145 | 146 | let mut c4 = c1[0]; 147 | for i in 1..(n-num_blinders) { 148 | c4 += &c1[i]; 149 | } 150 | 151 | let mut c4n = c4; 152 | for i in 0..num_blinders { 153 | c4n += &c1[n - num_blinders + i]; 154 | } 155 | 156 | let mut c5: Vec = Vec::new(); 157 | c5.extend(& c1); 158 | c5.extend(& c2); 159 | 160 | let alpha1: Fr = rng.gen(); 161 | let alpha2: Fr = rng.gen(); 162 | let sameexp1 = generator.mul(alpha1).into_affine(); 163 | let sameexp2 = generator.mul(alpha2).into_affine(); 164 | 165 | let crs = CrsStruct { 166 | crs_g: c1, 167 | crs_h: c2, 168 | u: c3, 169 | crs_se1: sameexp1, 170 | crs_se2: sameexp2, 171 | crs_g_prod_ell: c4.into_projective(), 172 | crs_g_prod_n: c4n.into_projective(), 173 | crs_gh: c5, 174 | bitstring: get_bitstring(n, logn), 175 | }; 176 | 177 | crs 178 | } 179 | 180 | pub fn get_bitstring(n:usize, logn: usize) -> Vec> { 181 | let mut bitstring: Vec> = Vec::new(); 182 | for _i in 0..n { 183 | let vec_i: Vec = Vec::new(); 184 | bitstring.push(vec_i); 185 | } 186 | 187 | for j in 0..logn { 188 | for i in 0..n { 189 | let current_bitstring = format!("{:b}", i); 190 | let mut bit_vec: Vec = current_bitstring.chars().collect(); 191 | bit_vec.reverse(); 192 | while bit_vec.len() < logn { 193 | bit_vec.push('0'); 194 | } 195 | 196 | if bit_vec[logn - j - 1] == '1' { 197 | bitstring[i].push(j); 198 | } 199 | } 200 | } 201 | 202 | bitstring 203 | } 204 | 205 | pub fn prove(crs: CrsStruct, ciph_r: &Vec, ciph_s: &Vec, 206 | mut ciph_t: Vec, mut ciph_u: Vec, vec_shuffle: Vec, r: Fr, 207 | ell: usize, n: usize, logn: usize) 208 | -> ShuffleProofStruct { 209 | 210 | let mut rng = thread_rng(); 211 | let num_blinders: usize = n - ell; 212 | 213 | let mut hash_input = to_bytes!(crs.u).unwrap(); 214 | for i in 0..ell { 215 | hash_input.append(&mut to_bytes!(ciph_r[i]).unwrap()); 216 | hash_input.append(&mut to_bytes!(ciph_s[i]).unwrap()); 217 | hash_input.append(&mut to_bytes!(ciph_t[i]).unwrap()); 218 | hash_input.append(&mut to_bytes!(ciph_u[i]).unwrap()); 219 | } 220 | let mut current_hash = hash_values(hash_input); 221 | 222 | let mut vec_m: Vec = Vec::new(); 223 | for i in 0..ell { 224 | let mut mi = Fr::zero(); 225 | for _j in 0..(vec_shuffle[i] as usize) { 226 | mi = mi + Fr::one(); 227 | } 228 | vec_m.push(mi); 229 | } 230 | for _i in 0..num_blinders { 231 | vec_m.push(rng.gen()); 232 | } 233 | 234 | let vec_m_formatted = vec_m.iter().map(|x| x.into_repr()).collect::>(); 235 | let g_m = VariableBaseMSM::multi_scalar_mul(crs.crs_g.as_slice(), vec_m_formatted.as_slice()).into_affine(); 236 | 237 | let mut hash_input = current_hash; 238 | hash_input.append(&mut to_bytes!(g_m).unwrap()); 239 | current_hash = hash_values(hash_input); 240 | 241 | let mut vec_a: Vec = Vec::new(); 242 | for _i in 0..ell { 243 | vec_a.push(get_challenge_from_current_hash(¤t_hash)); 244 | current_hash = hash_values(current_hash); 245 | } 246 | 247 | let mut vec_a_shuffled: Vec = Vec::new(); 248 | for i in 0..ell { 249 | vec_a_shuffled.push(vec_a[vec_shuffle[i] as usize]); 250 | } 251 | for _i in 0..num_blinders { 252 | vec_a_shuffled.push(rng.gen()); 253 | } 254 | 255 | let vec_formatted = vec_a_shuffled.iter().map(|x| x.into_repr()).collect::>(); 256 | let g_a = VariableBaseMSM::multi_scalar_mul(crs.crs_g.as_slice(), vec_formatted.as_slice()).into_affine(); 257 | 258 | let mut hash_input = current_hash; 259 | hash_input.append(&mut to_bytes!(g_a).unwrap()); 260 | current_hash = hash_values(hash_input); 261 | 262 | let chal_alpha = get_challenge_from_current_hash(¤t_hash); 263 | current_hash = hash_values(current_hash); 264 | let chal_beta = get_challenge_from_current_hash(¤t_hash); 265 | 266 | let mut vec_gprod: Vec = Vec::new(); 267 | for i in 0..n { 268 | vec_gprod.push(vec_a_shuffled[i] + vec_m[i] * chal_alpha + chal_beta); 269 | } 270 | 271 | let mut gprod = Fr::one(); 272 | for i in 0..ell { 273 | gprod *= vec_gprod[i]; 274 | } 275 | 276 | let (current_hash, proof_gprod, gprod_prover_info) = gprod_prove(current_hash, &crs, gprod, vec_gprod, ell, n); 277 | 278 | let vec_formatted = vec_a.iter().map(|x| x.into_repr()).collect::>(); 279 | let g_r = VariableBaseMSM::multi_scalar_mul(ciph_r.as_slice(), vec_formatted.as_slice()).into_affine(); 280 | let g_s = VariableBaseMSM::multi_scalar_mul(ciph_s.as_slice(), vec_formatted.as_slice()).into_affine(); 281 | 282 | let mut hash_input = current_hash; 283 | hash_input.append(&mut to_bytes!(g_a).unwrap()); 284 | hash_input.append(&mut to_bytes!(g_r).unwrap()); 285 | hash_input.append(&mut to_bytes!(g_s).unwrap()); 286 | let mut current_hash = hash_values(hash_input); 287 | 288 | let mut vec_gamma: Vec = Vec::new(); 289 | let mut vec_delta: Vec = Vec::new(); 290 | for _i in 0..num_blinders { 291 | current_hash = hash_values(current_hash); 292 | vec_gamma.push( get_challenge_from_current_hash(¤t_hash) ); 293 | current_hash = hash_values(current_hash); 294 | vec_delta.push( get_challenge_from_current_hash(¤t_hash) ); 295 | } 296 | 297 | let mut blinder_se1: Fr = Fr::zero(); 298 | let mut blinder_se2: Fr = Fr::zero(); 299 | for i in 0..num_blinders { 300 | blinder_se1 += vec_gamma[i] * vec_a_shuffled[ell + i]; 301 | blinder_se2 += vec_delta[i] * vec_a_shuffled[ell + i]; 302 | } 303 | 304 | let g_t = (g_r.mul(r) + crs.crs_se1.mul(blinder_se1) ).into_affine(); 305 | let g_u = (g_s.mul(r) + crs.crs_se2.mul(blinder_se2) ).into_affine(); 306 | 307 | 308 | let (current_hash, proof_sameexp) = sameexp_prove(current_hash, g_r, g_s, crs.crs_se1, 309 | crs.crs_se2, g_t, g_u, r, blinder_se1, blinder_se2); 310 | 311 | for i in 0..num_blinders { 312 | ciph_t.push(crs.crs_se1.mul(vec_gamma[i]).into_affine()); 313 | ciph_u.push(crs.crs_se2.mul(vec_delta[i]).into_affine()); 314 | } 315 | 316 | let (_current_hash, proof_gpme) = gprod_and_multiexp_prove(current_hash, crs, gprod_prover_info.crs_h_scaled, 317 | gprod_prover_info.vec_b, gprod_prover_info.vec_c, gprod_prover_info.inner_prod, 318 | ciph_t.to_vec(), ciph_u.to_vec(), vec_a_shuffled, n, logn); 319 | 320 | let proof_shuffle = ShuffleProofStruct { 321 | g_m: g_m, 322 | g_a: g_a, 323 | proof_gprod: proof_gprod, 324 | g_r: g_r, 325 | g_s: g_s, 326 | g_t: g_t, 327 | g_u: g_u, 328 | proof_sameexp: proof_sameexp, 329 | proof_gpme: proof_gpme, 330 | }; 331 | 332 | proof_shuffle 333 | 334 | } 335 | 336 | pub fn gprod_prove(mut current_hash: Vec, crs: &CrsStruct, gprod: Fr, 337 | vec_a: Vec, ell: usize, n: usize) 338 | -> (Vec, GprodProofStruct, GprodProverInfoStruct) 339 | { 340 | 341 | let mut rng = thread_rng(); 342 | let num_blinders: usize = n - ell; 343 | 344 | let mut vec_b: Vec = Vec::new(); 345 | let mut bi: Fr = Fr::one(); 346 | for i in 0..ell { 347 | vec_b.push(bi); 348 | bi = bi * vec_a[i + 1]; 349 | } 350 | for _i in 0..num_blinders { 351 | vec_b.push(rng.gen()); 352 | } 353 | 354 | let vec_b_formatted = vec_b.iter().map(|x| x.into_repr()).collect::>(); 355 | let g_b = VariableBaseMSM::multi_scalar_mul(crs.crs_g.as_slice(), vec_b_formatted.as_slice()).into_affine(); 356 | 357 | let mut blinder: Fr = Fr::zero(); 358 | for i in 0..num_blinders { 359 | blinder += vec_a[ell + i] * vec_b[ell +i]; 360 | } 361 | 362 | 363 | let mut hash_input = current_hash; 364 | hash_input.append(&mut to_bytes!(blinder).unwrap()); 365 | hash_input.append(&mut to_bytes!(g_b).unwrap()); 366 | 367 | 368 | current_hash = hash_values(hash_input); 369 | 370 | let chal_x = get_challenge_from_current_hash(¤t_hash); 371 | let chal_inv_x = chal_x.inverse().unwrap(); 372 | 373 | let mut vec_c: Vec = Vec::new(); 374 | 375 | let mut pow_x = chal_x; 376 | let mut pow_x2 = Fr::one(); 377 | for i in 0..(ell-1) { 378 | vec_c.push(vec_a[i+1] * pow_x - pow_x2); 379 | pow_x = pow_x * chal_x; 380 | pow_x2 = pow_x2 * chal_x; 381 | } 382 | 383 | vec_c.push(vec_a[0] * pow_x - pow_x2); 384 | 385 | pow_x = pow_x * chal_x; 386 | for i in 0..num_blinders { 387 | vec_c.push(vec_a[ell + i] * pow_x); 388 | } 389 | 390 | let mut crs_h: Vec = Vec::new(); 391 | let mut pow_inv_x = chal_inv_x; 392 | for i in 0..(ell-1) { 393 | crs_h.push(crs.crs_g[i+1].mul(pow_inv_x).into_affine()); 394 | pow_inv_x = pow_inv_x * chal_inv_x; 395 | } 396 | 397 | crs_h.push(crs.crs_g[0].mul(pow_inv_x).into_affine()); 398 | 399 | pow_inv_x = pow_inv_x * chal_inv_x; 400 | for i in 0..num_blinders { 401 | crs_h.push(crs.crs_g[ell + i].mul(pow_inv_x).into_affine()) 402 | } 403 | 404 | let inner_prod = blinder * chal_x.pow([(ell + 1) as u64]) + gprod * chal_x.pow([ell as u64]) - Fr::one(); 405 | 406 | let proof_gprod = GprodProofStruct { 407 | g_b: g_b, 408 | blinder: blinder, 409 | }; 410 | 411 | let gprod_prover_info = GprodProverInfoStruct { 412 | crs_h_scaled: crs_h, 413 | vec_b: vec_b, 414 | vec_c: vec_c, 415 | inner_prod: inner_prod, 416 | }; 417 | 418 | (current_hash, proof_gprod, gprod_prover_info) 419 | } 420 | 421 | pub fn sameexp_prove(mut current_hash: Vec, g_1: G1Affine, g_2: G1Affine, 422 | h_1: G1Affine, h_2: G1Affine, y_1: G1Affine, 423 | y_2: G1Affine, r: Fr, bl1: Fr, bl2: Fr) -> (Vec, SameexpProofStruct) { 424 | let mut rng = thread_rng(); 425 | 426 | let s1: Fr = rng.gen(); 427 | let s2: Fr = rng.gen(); 428 | let s3: Fr = rng.gen(); 429 | let g_r1: G1Affine = (g_1.mul(s1) + h_1.mul(s2)).into_affine(); 430 | let g_r2: G1Affine = (g_2.mul(s1) + h_2.mul(s3)).into_affine(); 431 | 432 | let mut hash_input = current_hash; 433 | hash_input.append(&mut to_bytes!(g_1).unwrap()); 434 | hash_input.append(&mut to_bytes!(g_2).unwrap()); 435 | hash_input.append(&mut to_bytes!(y_1).unwrap()); 436 | hash_input.append(&mut to_bytes!(y_2).unwrap()); 437 | hash_input.append(&mut to_bytes!(g_r1).unwrap()); 438 | hash_input.append(&mut to_bytes!(g_r2).unwrap()); 439 | 440 | current_hash = hash_values(hash_input); 441 | let chal_x = get_challenge_from_current_hash(¤t_hash); 442 | 443 | let u1: Fr = s1 + chal_x * r; 444 | let u2: Fr = s2 + chal_x * bl1; 445 | let u3: Fr = s3 + chal_x * bl2; 446 | 447 | let proof_sameexp = SameexpProofStruct { 448 | g_r1: g_r1, 449 | g_r2: g_r2, 450 | u1: u1, 451 | u2: u2, 452 | u3: u3, 453 | }; 454 | 455 | (current_hash, proof_sameexp) 456 | } 457 | 458 | pub fn gprod_and_multiexp_prove(mut current_hash: Vec, mut crs: CrsStruct, mut crs_h_scaled: Vec, 459 | mut vec_b: Vec, mut vec_c: Vec, mut inner_prod: Fr, 460 | mut ciph_t: Vec, mut ciph_u: Vec, mut vec_exp: Vec, n: usize, logn: usize) 461 | -> (Vec, GpmeProofStruct) { 462 | 463 | let mut rng = thread_rng(); 464 | let mut vec_rgp: Vec = Vec::new(); 465 | let mut vec_sgp: Vec = Vec::new(); 466 | let mut vec_rme: Vec = Vec::new(); 467 | 468 | for _i in 0..n { 469 | vec_rgp.push(rng.gen()); 470 | vec_sgp.push(rng.gen()); 471 | vec_rme.push(rng.gen()); 472 | } 473 | 474 | let vec_formatted = vec_rgp.iter().map(|x| x.into_repr()).collect::>(); 475 | let g_rgp = VariableBaseMSM::multi_scalar_mul(crs.crs_g.as_slice(), vec_formatted.as_slice()).into_affine(); 476 | 477 | let vec_formatted = vec_sgp.iter().map(|x| x.into_repr()).collect::>(); 478 | let g_sgp = VariableBaseMSM::multi_scalar_mul(crs_h_scaled.as_slice(), vec_formatted.as_slice()).into_affine(); 479 | 480 | let blinder1_gp = get_inner_prod(&vec_b, &vec_sgp) + get_inner_prod(&vec_c, &vec_rgp); 481 | let blinder2_gp = get_inner_prod(&vec_rgp, &vec_sgp) ; 482 | 483 | let vec_formatted = vec_rme.iter().map(|x| x.into_repr()).collect::>(); 484 | let g_rme = VariableBaseMSM::multi_scalar_mul(crs.crs_g.as_slice(), vec_formatted.as_slice()).into_affine(); 485 | 486 | let g_mebl1 = VariableBaseMSM::multi_scalar_mul(ciph_t.as_slice(), vec_formatted.as_slice()).into_affine(); 487 | let g_mebl2 = VariableBaseMSM::multi_scalar_mul(ciph_u.as_slice(), vec_formatted.as_slice()).into_affine(); 488 | 489 | let mut hash_input = current_hash; 490 | hash_input.append(&mut to_bytes!(g_rgp).unwrap()); 491 | hash_input.append(&mut to_bytes!(g_sgp).unwrap()); 492 | hash_input.append(&mut to_bytes!(blinder1_gp).unwrap()); 493 | hash_input.append(&mut to_bytes!(blinder2_gp).unwrap()); 494 | hash_input.append(&mut to_bytes!(g_rme).unwrap()); 495 | hash_input.append(&mut to_bytes!(g_mebl1).unwrap()); 496 | hash_input.append(&mut to_bytes!(g_mebl2).unwrap()); 497 | 498 | current_hash = hash_values(hash_input); 499 | let chal_x = get_challenge_from_current_hash(¤t_hash); 500 | 501 | inner_prod += blinder1_gp * chal_x + blinder2_gp * chal_x * chal_x; 502 | 503 | for i in 0..n { 504 | vec_b[i] += vec_rgp[i] * chal_x; 505 | vec_c[i] += vec_sgp[i] * chal_x; 506 | vec_exp[i] += vec_rme[i] * chal_x; 507 | } 508 | 509 | let mut hash_input = current_hash; 510 | current_hash = hash_values(hash_input); 511 | let chal_x = get_challenge_from_current_hash(¤t_hash); 512 | 513 | crs.u = crs.u.mul(chal_x).into_affine(); 514 | 515 | let mut crs_h = crs.crs_g.clone(); 516 | 517 | let mut proof: Vec<[G1Affine; 10]> = Vec::new(); 518 | let mut current_n: usize = n; 519 | for _j in 0..logn { 520 | current_n = ( (current_n as u32) / 2) as usize; 521 | println!("current_n = {}", current_n); 522 | 523 | let zlgp = get_inner_prod(&vec_b[current_n..].to_vec(), &vec_c[..current_n].to_vec()); 524 | let zrgp = get_inner_prod(&vec_b[..current_n].to_vec(), &vec_c[current_n..].to_vec()); 525 | 526 | //let base = &mut ciph_t[current_n..].to_vec(); 527 | let vec_formatted = vec_exp[..current_n].iter().map(|x| x.into_repr()).collect::>(); 528 | let g_zlme1 = VariableBaseMSM::multi_scalar_mul(&ciph_t[current_n..], vec_formatted.as_slice()).into_affine(); 529 | 530 | //let base = &mut ciph_u[current_n..].to_vec(); 531 | let g_zlme2 = VariableBaseMSM::multi_scalar_mul(&ciph_u[current_n..], vec_formatted.as_slice()).into_affine(); 532 | 533 | //let base = &mut ciph_t[..current_n].to_vec(); 534 | let vec_formatted = vec_exp[current_n..].iter().map(|x| x.into_repr()).collect::>(); 535 | let g_zrme1 = VariableBaseMSM::multi_scalar_mul(&ciph_t[..current_n], vec_formatted.as_slice()).into_affine(); 536 | 537 | //let base = &mut ciph_u[..current_n].to_vec(); 538 | let g_zrme2 = VariableBaseMSM::multi_scalar_mul(&ciph_u[..current_n], vec_formatted.as_slice()).into_affine(); 539 | 540 | let base = &mut crs.crs_g[..current_n].to_vec(); 541 | let vec_formatted = vec_b[current_n..].iter().map(|x| x.into_repr()).collect::>(); 542 | let mut g_clgpb = VariableBaseMSM::multi_scalar_mul(base.as_slice(), vec_formatted.as_slice()).into_affine(); 543 | g_clgpb = g_clgpb + crs.u.mul(zlgp).into_affine(); 544 | 545 | let base = &mut crs_h_scaled[current_n..].to_vec(); 546 | let vec_formatted = vec_c[..current_n].iter().map(|x| x.into_repr()).collect::>(); 547 | let g_clgpc = VariableBaseMSM::multi_scalar_mul(base.as_slice(), vec_formatted.as_slice()).into_affine(); 548 | 549 | let base = &mut crs.crs_g[current_n..].to_vec(); 550 | let vec_formatted = vec_b[..current_n].iter().map(|x| x.into_repr()).collect::>(); 551 | let mut g_crgpb = VariableBaseMSM::multi_scalar_mul(base.as_slice() , vec_formatted.as_slice()).into_affine(); 552 | g_crgpb = g_crgpb + crs.u.mul(zrgp).into_affine(); 553 | 554 | let base = &mut crs_h_scaled[..current_n].to_vec(); 555 | let vec_formatted = vec_c[current_n..].iter().map(|x| x.into_repr()).collect::>(); 556 | let g_crgpc = VariableBaseMSM::multi_scalar_mul(base.as_slice(), vec_formatted.as_slice()).into_affine(); 557 | 558 | let base = &mut crs_h[current_n..].to_vec(); 559 | let vec_formatted = vec_exp[..current_n].iter().map(|x| x.into_repr()).collect::>(); 560 | let g_clme = VariableBaseMSM::multi_scalar_mul(base.as_slice(), vec_formatted.as_slice()).into_affine(); 561 | 562 | let base = &mut crs_h[..current_n].to_vec(); 563 | let vec_formatted = vec_exp[current_n..].iter().map(|x| x.into_repr()).collect::>(); 564 | let g_crme = VariableBaseMSM::multi_scalar_mul(base.as_slice(), vec_formatted.as_slice()).into_affine(); 565 | 566 | proof.push([g_zlme1, g_zlme2, g_zrme1, g_zrme2, g_clgpb, g_clgpc, g_crgpb, g_crgpc, g_clme, g_crme]); 567 | 568 | hash_input = current_hash; 569 | hash_input.append(&mut to_bytes!(g_zlme1).unwrap()); 570 | hash_input.append(&mut to_bytes!(g_zlme2).unwrap()); 571 | hash_input.append(&mut to_bytes!(g_zrme1).unwrap()); 572 | hash_input.append(&mut to_bytes!(g_zrme2).unwrap()); 573 | hash_input.append(&mut to_bytes!(g_clgpb).unwrap()); 574 | hash_input.append(&mut to_bytes!(g_clgpc).unwrap()); 575 | hash_input.append(&mut to_bytes!(g_crgpb).unwrap()); 576 | hash_input.append(&mut to_bytes!(g_crgpc).unwrap()); 577 | hash_input.append(&mut to_bytes!(g_clme).unwrap()); 578 | hash_input.append(&mut to_bytes!(g_crme).unwrap()); 579 | current_hash = hash_values(hash_input); 580 | 581 | let chal_x = get_challenge_from_current_hash(¤t_hash); 582 | let chal_inv_x = chal_x.inverse().unwrap(); 583 | 584 | for i in 0..current_n { 585 | crs.crs_g[i] = crs.crs_g[i] + crs.crs_g[current_n + i].mul(chal_inv_x).into_affine(); 586 | crs_h_scaled[i] = crs_h_scaled[i] + crs_h_scaled[current_n + i].mul(chal_x).into_affine(); 587 | vec_b[i] = vec_b[i] + chal_x * vec_b[current_n + i]; 588 | vec_c[i] = vec_c[i] + chal_inv_x * vec_c[current_n + i]; 589 | 590 | crs_h[i] = crs_h[i] + crs_h[current_n + i].mul(chal_x).into_affine(); 591 | ciph_t[i] = ciph_t[i] + ciph_t[current_n + i].mul(chal_x).into_affine(); 592 | ciph_u[i] = ciph_u[i] + ciph_u[current_n + i].mul(chal_x).into_affine(); 593 | 594 | vec_exp[i] = vec_exp[i] + vec_exp[current_n + i] * chal_inv_x ; 595 | } 596 | 597 | crs.crs_g = crs.crs_g[..current_n].to_vec(); 598 | crs_h_scaled = crs_h_scaled[..current_n].to_vec(); 599 | vec_b = vec_b[..current_n].to_vec(); 600 | vec_c = vec_c[..current_n].to_vec(); 601 | 602 | crs_h = crs_h[..current_n].to_vec(); 603 | ciph_t = ciph_t[..current_n].to_vec(); 604 | ciph_u = ciph_u[..current_n].to_vec(); 605 | } 606 | 607 | let proof_gpme = GpmeProofStruct { 608 | g_rgp: g_rgp, 609 | g_sgp: g_sgp, 610 | g_rme: g_rme, 611 | blinder1_gp: blinder1_gp, 612 | blinder2_gp: blinder2_gp, 613 | g_mebl1: g_mebl1, 614 | g_mebl2: g_mebl2, 615 | proof: proof, 616 | b_final: vec_b[0], 617 | c_final: vec_c[0], 618 | a_final: vec_exp[0], 619 | }; 620 | 621 | (current_hash, proof_gpme) 622 | } 623 | 624 | pub fn verify(crs: CrsStruct, ciph_r: Vec, ciph_s: Vec, 625 | ciph_t: Vec, ciph_u: Vec, proof_shuffle: ShuffleProofStruct, 626 | ell: usize, n: usize, logn: usize) 627 | -> bool { 628 | 629 | let num_blinders = n - ell; 630 | 631 | let now = Instant::now(); 632 | let mut hash_input = to_bytes!(crs.u).unwrap(); 633 | for i in 0..ell { 634 | hash_input.append(&mut to_bytes!(ciph_r[i]).unwrap()); 635 | hash_input.append(&mut to_bytes!(ciph_s[i]).unwrap()); 636 | hash_input.append(&mut to_bytes!(ciph_t[i]).unwrap()); 637 | hash_input.append(&mut to_bytes!(ciph_u[i]).unwrap()); 638 | } 639 | let mut current_hash = hash_values(hash_input); 640 | let new_now = Instant::now(); 641 | println!("hashing time = {:?}", new_now.duration_since(now)); 642 | 643 | 644 | let mut hash_input = current_hash; 645 | hash_input.append(&mut to_bytes!(proof_shuffle.g_m).unwrap()); 646 | current_hash = hash_values(hash_input); 647 | 648 | let mut vec_a: Vec = Vec::new(); 649 | for _i in 0..ell { 650 | vec_a.push(get_challenge_from_current_hash(¤t_hash)); 651 | current_hash = hash_values(current_hash); 652 | } 653 | 654 | let mut hash_input = current_hash; 655 | hash_input.append(&mut to_bytes!(proof_shuffle.g_a).unwrap()); 656 | let mut current_hash = hash_values(hash_input); 657 | 658 | let chal_alpha = get_challenge_from_current_hash(¤t_hash); 659 | current_hash = hash_values(current_hash); 660 | let chal_beta = get_challenge_from_current_hash(¤t_hash); 661 | 662 | let mut gprod = Fr::one(); 663 | let mut field_i = Fr::zero(); 664 | for i in 0..ell { 665 | gprod *= vec_a[i] + field_i * chal_alpha + chal_beta; 666 | field_i += Fr::one(); 667 | } 668 | 669 | let now = Instant::now(); 670 | let g_a1 = proof_shuffle.g_a + (proof_shuffle.g_m.mul(chal_alpha) + (crs.crs_g_prod_n ).mul(chal_beta)).into_affine(); 671 | let new_now = Instant::now(); 672 | println!("g_a1 outer time = {:?}", new_now.duration_since(now)); 673 | 674 | let now = Instant::now(); 675 | let (current_hash, gprod_verifier_info) = gprod_verify(current_hash, &crs, g_a1, gprod, proof_shuffle.proof_gprod, ell, n); 676 | let new_now = Instant::now(); 677 | println!("gprod outer time = {:?}", new_now.duration_since(now)); 678 | // check g_r and g_s correct in final exponentiation 679 | 680 | let mut hash_input = current_hash; 681 | hash_input.append(&mut to_bytes!(proof_shuffle.g_a).unwrap()); 682 | hash_input.append(&mut to_bytes!(proof_shuffle.g_r).unwrap()); 683 | hash_input.append(&mut to_bytes!(proof_shuffle.g_s).unwrap()); 684 | let mut current_hash = hash_values(hash_input); 685 | 686 | let mut vec_gamma: Vec = Vec::new(); 687 | let mut vec_delta: Vec = Vec::new(); 688 | for _i in 0..num_blinders { 689 | current_hash = hash_values(current_hash); 690 | vec_gamma.push( get_challenge_from_current_hash(¤t_hash) ); 691 | current_hash = hash_values(current_hash); 692 | vec_delta.push( get_challenge_from_current_hash(¤t_hash) ); 693 | } 694 | 695 | // challenges = [zk, u_scale, inner[0], ... , inner[logn - 1], veq1, veq2, veq3, veq4, veq5, veq6 ] 696 | let (chal_sameexp, challenges_gpme, challenges_veqs) = get_challenges(current_hash.clone(), 697 | proof_shuffle.g_r, proof_shuffle.g_s, proof_shuffle.g_t, proof_shuffle.g_u, &proof_shuffle.proof_sameexp, 698 | &proof_shuffle.proof_gpme, logn); 699 | 700 | let mut final_exps: FinalExpStruct = FinalExpStruct { 701 | base: Vec::new(), 702 | exponents: Vec::new(), 703 | }; 704 | 705 | 706 | let now = Instant::now(); 707 | final_exps = sameexp_verify(chal_sameexp, challenges_veqs[6..8].to_vec(), final_exps, proof_shuffle.g_r, proof_shuffle.g_s, crs.crs_se1, 708 | crs.crs_se2, proof_shuffle.g_t, proof_shuffle.g_u, proof_shuffle.proof_sameexp); 709 | let new_now = Instant::now(); 710 | println!("sameexp time = {:?}", new_now.duration_since(now)); 711 | 712 | 713 | // check that g_r and g_s are correct. 714 | final_exps = add_to_final_expo(final_exps, proof_shuffle.g_r, - Fr::one()); 715 | final_exps = add_to_final_expo(final_exps, proof_shuffle.g_s, - challenges_veqs[5]); 716 | 717 | for i in 0..vec_a.len() { 718 | final_exps = add_to_final_expo(final_exps, ciph_r[i], vec_a[i]); 719 | final_exps = add_to_final_expo(final_exps, ciph_s[i], challenges_veqs[5] * vec_a[i]); 720 | } 721 | 722 | let now = Instant::now(); 723 | let final_exps = gprod_and_multiexp_verify(crs, challenges_gpme, challenges_veqs, final_exps, 724 | gprod_verifier_info.vec_crs_h_exp, 725 | gprod_verifier_info.g_b, 726 | gprod_verifier_info.g_c, gprod_verifier_info.inner_prod, ciph_t, vec_gamma, ciph_u, vec_delta, proof_shuffle.g_a, 727 | proof_shuffle.g_t, proof_shuffle.g_u, proof_shuffle.proof_gpme, 728 | ell, n, logn); 729 | let new_now = Instant::now(); 730 | println!("inner product time = {:?}", new_now.duration_since(now)); 731 | 732 | let now = Instant::now(); 733 | let vec_formatted = final_exps.exponents.iter().map(|x| x.into_repr()).collect::>(); 734 | let g_expected: G1Affine = VariableBaseMSM::multi_scalar_mul(final_exps.base.as_slice(), vec_formatted.as_slice()).into_affine(); 735 | let b = g_expected.infinity; 736 | let new_now = Instant::now(); 737 | println!("final exponentiation time = {:?}", new_now.duration_since(now)); 738 | 739 | b 740 | } 741 | 742 | pub fn gprod_verify(mut current_hash: Vec, crs: &CrsStruct, g_a1: G1Affine, gprod: Fr, 743 | proof_gprod: GprodProofStruct, ell: usize, n:usize) 744 | -> (Vec, GprodVerifierInfoStruct) { 745 | 746 | let num_blinders = n - ell; 747 | 748 | let mut hash_input = current_hash; 749 | hash_input.append(&mut to_bytes!(proof_gprod.blinder).unwrap()); 750 | hash_input.append(&mut to_bytes!(proof_gprod.g_b).unwrap()); 751 | 752 | 753 | current_hash = hash_values(hash_input); 754 | 755 | let chal_x = get_challenge_from_current_hash(¤t_hash); 756 | let chal_inv_x = chal_x.inverse().unwrap(); 757 | 758 | 759 | let mut g_c = crs.crs_g_prod_ell.mul(-chal_inv_x).into_affine(); 760 | g_c += &g_a1; 761 | 762 | 763 | let mut vec_crs_h_exp: Vec = Vec::new(); 764 | let mut pow_inv_x = chal_inv_x; 765 | vec_crs_h_exp.push(Fr::one()); 766 | for _i in 1..ell { 767 | vec_crs_h_exp.push(pow_inv_x); 768 | pow_inv_x *= chal_inv_x; 769 | } 770 | 771 | vec_crs_h_exp[0] = pow_inv_x; 772 | pow_inv_x *= chal_inv_x; 773 | 774 | for _i in 0..num_blinders { 775 | vec_crs_h_exp.push(pow_inv_x); 776 | } 777 | 778 | let inner_prod = proof_gprod.blinder * chal_x.pow([(ell + 1) as u64]) + gprod * chal_x.pow([ell as u64]) - Fr::one(); 779 | 780 | //let (current_hash, b) = gprod_verify_inner(current_hash, crs, vec_crs_h_exp, g_c, inner_prod, proof_gprod.proof_inner, ell, n, logn); 781 | 782 | let gprod_verifier_info = GprodVerifierInfoStruct { 783 | vec_crs_h_exp: vec_crs_h_exp, 784 | g_b: proof_gprod.g_b, 785 | g_c: g_c, 786 | inner_prod: inner_prod, 787 | }; 788 | 789 | (current_hash, gprod_verifier_info) 790 | 791 | } 792 | 793 | pub fn sameexp_verify(chal_x: Fr, challenges_veqs: Vec, mut final_exps: FinalExpStruct, g_1: G1Affine, g_2: G1Affine, 794 | h_1: G1Affine, h_2: G1Affine, y_1: G1Affine, y_2: G1Affine, proof_sameexp: SameexpProofStruct) 795 | -> FinalExpStruct 796 | { 797 | // let g_expected: G1Affine = proof_sameexp.g_r1 + (y_1.mul(chal_x) 798 | // + g_1.mul(- proof_sameexp.u1) + h_1.mul(- proof_sameexp.u2)).into_affine(); 799 | // let b1 = g_expected.infinity; 800 | 801 | final_exps = add_to_final_expo(final_exps, proof_sameexp.g_r1, challenges_veqs[0]); 802 | final_exps = add_to_final_expo(final_exps, y_1, challenges_veqs[0] * chal_x); 803 | final_exps = add_to_final_expo(final_exps, g_1, - challenges_veqs[0] * proof_sameexp.u1); 804 | final_exps = add_to_final_expo(final_exps, h_1, - challenges_veqs[0] * proof_sameexp.u2); 805 | 806 | // let g_expected: G1Affine = proof_sameexp.g_r2 + (y_2.mul(chal_x) 807 | // + g_2.mul(- proof_sameexp.u1) + h_2.mul(- proof_sameexp.u3)).into_affine(); 808 | // let b2 = g_expected.infinity; 809 | 810 | final_exps = add_to_final_expo(final_exps, proof_sameexp.g_r2, challenges_veqs[1]); 811 | final_exps = add_to_final_expo(final_exps, y_2, challenges_veqs[1] * chal_x); 812 | final_exps = add_to_final_expo(final_exps, g_2, - challenges_veqs[1] * proof_sameexp.u1); 813 | final_exps = add_to_final_expo(final_exps, h_2, - challenges_veqs[1] * proof_sameexp.u3); 814 | 815 | // let b: bool = b1 & b2; 816 | 817 | // b 818 | final_exps 819 | } 820 | 821 | pub fn get_challenges(mut current_hash: Vec, 822 | g_r: G1Affine, g_s: G1Affine, g_t: G1Affine, g_u: G1Affine, proof_sameexp: &SameexpProofStruct, 823 | proof_gpme: &GpmeProofStruct, logn: usize) 824 | -> (Fr, Vec, Vec) { 825 | 826 | let mut hash_input = current_hash; 827 | hash_input.append(&mut to_bytes!(g_r).unwrap()); 828 | hash_input.append(&mut to_bytes!(g_s).unwrap()); 829 | hash_input.append(&mut to_bytes!(g_t).unwrap()); 830 | hash_input.append(&mut to_bytes!(g_u).unwrap()); 831 | hash_input.append(&mut to_bytes!(proof_sameexp.g_r1).unwrap()); 832 | hash_input.append(&mut to_bytes!(proof_sameexp.g_r2).unwrap()); 833 | 834 | current_hash = hash_values(hash_input); 835 | let chal_sameexp = get_challenge_from_current_hash(¤t_hash); 836 | 837 | let mut challenges_gpme: Vec = Vec::new(); 838 | 839 | // One challenge for zero-knowledge gpme. 840 | // [zk] 841 | let mut hash_input = current_hash; 842 | hash_input.append(&mut to_bytes!(proof_gpme.g_rgp).unwrap()); 843 | hash_input.append(&mut to_bytes!(proof_gpme.g_sgp).unwrap()); 844 | hash_input.append(&mut to_bytes!(proof_gpme.blinder1_gp).unwrap()); 845 | hash_input.append(&mut to_bytes!(proof_gpme.blinder2_gp).unwrap()); 846 | hash_input.append(&mut to_bytes!(proof_gpme.g_rme).unwrap()); 847 | hash_input.append(&mut to_bytes!(proof_gpme.g_mebl1).unwrap()); 848 | hash_input.append(&mut to_bytes!(proof_gpme.g_mebl2).unwrap()); 849 | 850 | current_hash = hash_values(hash_input); 851 | challenges_gpme.push( get_challenge_from_current_hash(¤t_hash) ); 852 | // let chal_zk = get_challenge_from_current_hash(¤t_hash); 853 | 854 | // One challenge for scaling u in gpme. 855 | // [u_scale] 856 | let hash_input = current_hash; 857 | current_hash = hash_values(hash_input); 858 | challenges_gpme.push( get_challenge_from_current_hash(¤t_hash) ); 859 | 860 | // One challenge per inner product round in gpme. 861 | // [inner[0], ... , inner[logn - 1]] 862 | for j in 0..logn { 863 | let mut hash_input = current_hash; 864 | for i in 0..10 { 865 | hash_input.append(&mut to_bytes!(proof_gpme.proof[j][i]).unwrap()) 866 | } 867 | 868 | current_hash = hash_values(hash_input); 869 | challenges_gpme.push( get_challenge_from_current_hash(¤t_hash) ) 870 | } 871 | 872 | let mut hash_input = current_hash; 873 | hash_input.append(&mut to_bytes!(proof_gpme.b_final).unwrap()) ; 874 | hash_input.append(&mut to_bytes!(proof_gpme.c_final).unwrap()); 875 | hash_input.append(&mut to_bytes!(proof_gpme.a_final).unwrap()); 876 | current_hash = hash_values(hash_input).to_vec(); 877 | 878 | // One extra challenge per verifier equation. 879 | // [veq1, veq2, veq3, veq4, veq5, veq6 ] 880 | let mut challenges_veqs: Vec = Vec::new(); 881 | for _i in 0..8 { 882 | challenges_veqs.push(get_challenge_from_current_hash(¤t_hash)); 883 | current_hash = hash_values(current_hash).to_vec(); 884 | } 885 | (chal_sameexp, challenges_gpme, challenges_veqs) 886 | } 887 | 888 | pub fn gprod_and_multiexp_verify(crs: CrsStruct, challenges_gpme: Vec, challenges_veqs: Vec, 889 | mut final_exps: FinalExpStruct, 890 | vec_crs_h_exp: Vec, g_b: G1Affine, 891 | g_c: G1Affine, mut inner_prod: Fr, ciph_t: Vec, vec_gamma: Vec, 892 | ciph_u: Vec, vec_delta: Vec, g_a: G1Affine, 893 | g_t: G1Affine, g_u: G1Affine, proof_gpme: GpmeProofStruct, 894 | ell: usize, n: usize, logn: usize 895 | ) -> FinalExpStruct 896 | { 897 | // challenges_gpme = [zk, u_scale, inner[0], ... , inner[logn - 1]] 898 | //challenges_veqs = [ veq0, veq1, veq2, veq3, veq4, veq5 ] 899 | // inverse challenges 900 | let mut x_invs: Vec = challenges_gpme[2..(logn+2)].to_vec(); 901 | algebra_core::batch_inversion(&mut x_invs); 902 | 903 | inner_prod += proof_gpme.blinder1_gp * challenges_gpme[0] + proof_gpme.blinder2_gp * challenges_gpme[0] * challenges_gpme[0]; 904 | 905 | //g_c = g_c + proof_gpme.g_sgp.mul(chal_zk); 906 | final_exps = add_to_final_expo(final_exps, g_c, - challenges_veqs[4]); 907 | final_exps = add_to_final_expo(final_exps, proof_gpme.g_sgp, - challenges_gpme[0] * challenges_veqs[4]); 908 | 909 | //g_t = g_t + proof_gpme.g_mebl1.mul(chal_zk); 910 | final_exps = add_to_final_expo(final_exps, g_t, - challenges_veqs[2]); 911 | final_exps = add_to_final_expo(final_exps, proof_gpme.g_mebl1, - challenges_veqs[2] * challenges_gpme[0]); 912 | 913 | //g_u = g_u + proof_gpme.g_mebl2.mul(chal_zk); 914 | final_exps = add_to_final_expo(final_exps, g_u, - challenges_veqs[3]); 915 | final_exps = add_to_final_expo(final_exps, proof_gpme.g_mebl2, - challenges_veqs[3] * challenges_gpme[0]); 916 | 917 | //g_a = g_a + proof_gpme.g_rme.mul(chal_zk); 918 | final_exps = add_to_final_expo(final_exps, g_a, - challenges_veqs[0]); 919 | final_exps = add_to_final_expo(final_exps, proof_gpme.g_rme, - challenges_veqs[0] * challenges_gpme[0]); 920 | 921 | // g_b = g_b + crs.u.mul(chal_uscale * b_final * c_final - chal_uscale * inner_prod) + proof_gpme.g_rgp.mul(chal_zk); 922 | final_exps = add_to_final_expo(final_exps, g_b, - challenges_veqs[1]); 923 | final_exps = add_to_final_expo(final_exps, proof_gpme.g_rgp, - challenges_gpme[0] * challenges_veqs[1]); 924 | final_exps = add_to_final_expo(final_exps, crs.u, 925 | challenges_gpme[1] * challenges_veqs[1] * proof_gpme.b_final * proof_gpme.c_final 926 | - challenges_veqs[1] * challenges_gpme[1] * inner_prod); 927 | 928 | let mut vec_crs_g_exp: Vec = Vec::new(); 929 | let mut vec_crs_h_shifted: Vec = Vec::new(); 930 | 931 | for _i in 0..n { 932 | vec_crs_g_exp.push(proof_gpme.b_final); 933 | vec_crs_h_shifted.push(Fr::one()); 934 | } 935 | 936 | 937 | for i in 0..n { 938 | for j in 0..crs.bitstring[i].len() { 939 | vec_crs_g_exp[i] *= x_invs[crs.bitstring[i][j]]; 940 | vec_crs_h_shifted[i] *= challenges_gpme[2 + crs.bitstring[i][j]]; 941 | } 942 | } 943 | 944 | let mut current_n: usize = n; 945 | for j in 0..logn { 946 | current_n = ( (current_n as u32) / 2) as usize; 947 | 948 | 949 | let chal_x = challenges_gpme[2 + j]; 950 | let chal_inv_x = x_invs[j]; 951 | 952 | //[g_zlme1, g_zlme2, g_zrme1, g_zrme2, g_clgp, g_crgp, g_clme, g_crme] 953 | //[g_zlme1, g_zlme2, g_zrme1, g_zrme2, g_clgpb, g_clgpc, g_crgpb, g_crgpc, g_clme, g_crme] 954 | 955 | //g_b = proof_gpme.proof[j][4].mul(chal_x) + g_b + proof_gpme.proof[j][6].mul(chal_inv_x); 956 | final_exps = add_to_final_expo(final_exps, proof_gpme.proof[j][4], - challenges_veqs[1] * chal_x); 957 | final_exps = add_to_final_expo(final_exps, proof_gpme.proof[j][6], - challenges_veqs[1] * chal_inv_x); 958 | 959 | //g_c = proof_gpme.proof[j][5].mul(chal_x) + g_c + proof_gpme.proof[j][7].mul(chal_inv_x); 960 | final_exps = add_to_final_expo(final_exps, proof_gpme.proof[j][5], - challenges_veqs[4] * chal_x); 961 | final_exps = add_to_final_expo(final_exps, proof_gpme.proof[j][7], - challenges_veqs[4] * chal_inv_x); 962 | 963 | //g_t = proof_gpme.proof[j][0].mul(chal_x) + g_t + proof_gpme.proof[j][2].mul(chal_inv_x); 964 | final_exps = add_to_final_expo(final_exps, proof_gpme.proof[j][0], - challenges_veqs[2] * chal_x); 965 | final_exps = add_to_final_expo(final_exps, proof_gpme.proof[j][2], - challenges_veqs[2] * chal_inv_x); 966 | 967 | //g_u = proof_gpme.proof[j][1].mul(chal_x) + g_u + proof_gpme.proof[j][3].mul(chal_inv_x); 968 | final_exps = add_to_final_expo(final_exps, proof_gpme.proof[j][1], - challenges_veqs[3] * chal_x); 969 | final_exps = add_to_final_expo(final_exps, proof_gpme.proof[j][3], - challenges_veqs[3] * chal_inv_x); 970 | 971 | //g_a = proof_gpme.proof[j][8].mul(chal_x) + g_a + proof_gpme.proof[j][9].mul(chal_inv_x); 972 | final_exps = add_to_final_expo(final_exps, proof_gpme.proof[j][8], - challenges_veqs[0] * chal_x); 973 | final_exps = add_to_final_expo(final_exps, proof_gpme.proof[j][9], - challenges_veqs[0] * chal_inv_x); 974 | 975 | } 976 | 977 | 978 | // let b1 = (g_ciph_t_final.mul(- proof_gpme.exp_final) + g_t).into_affine().infinity; 979 | // let b2 = (g_ciph_u_final.mul(- proof_gpme.exp_final) + g_u).into_affine().infinity; 980 | for i in 0..ell { 981 | final_exps = add_to_final_expo(final_exps, ciph_t[i], challenges_veqs[2] * vec_crs_h_shifted[i] 982 | * proof_gpme.a_final); 983 | 984 | final_exps = add_to_final_expo(final_exps, ciph_u[i], challenges_veqs[3] * vec_crs_h_shifted[i] 985 | * proof_gpme.a_final); 986 | } 987 | 988 | for i in ell..n { 989 | final_exps = add_to_final_expo(final_exps, crs.crs_se1, vec_gamma[i - ell] * challenges_veqs[2] * vec_crs_h_shifted[i] 990 | * proof_gpme.a_final); 991 | 992 | final_exps = add_to_final_expo(final_exps, crs.crs_se2, vec_delta[i - ell] * challenges_veqs[3] * vec_crs_h_shifted[i] 993 | * proof_gpme.a_final); 994 | } 995 | 996 | 997 | let mut vec_crs_exp: Fr = challenges_veqs[1] * vec_crs_g_exp[0] + 998 | challenges_veqs[0] * vec_crs_h_shifted[0] * proof_gpme.a_final 999 | + challenges_veqs[4] * vec_crs_h_exp[0] * vec_crs_h_shifted[ell-1]*proof_gpme.c_final; 1000 | 1001 | final_exps = add_to_final_expo(final_exps, crs.crs_g[0], vec_crs_exp); 1002 | 1003 | for i in 1..ell { 1004 | vec_crs_exp = challenges_veqs[1] * vec_crs_g_exp[i] + 1005 | challenges_veqs[0] * vec_crs_h_shifted[i] * proof_gpme.a_final 1006 | + challenges_veqs[4] * vec_crs_h_exp[i] * vec_crs_h_shifted[i-1]*proof_gpme.c_final; 1007 | 1008 | final_exps = add_to_final_expo(final_exps, crs.crs_g[i], vec_crs_exp); 1009 | } 1010 | 1011 | for i in ell..n { 1012 | vec_crs_exp = challenges_veqs[1] * vec_crs_g_exp[i] + 1013 | challenges_veqs[0] * vec_crs_h_shifted[i] * proof_gpme.a_final 1014 | + challenges_veqs[4] * vec_crs_h_exp[i] * vec_crs_h_shifted[i]*proof_gpme.c_final; 1015 | 1016 | final_exps = add_to_final_expo(final_exps, crs.crs_g[i], vec_crs_exp); 1017 | } 1018 | 1019 | final_exps 1020 | } 1021 | --------------------------------------------------------------------------------