def compute_multiexp_2(a, b): outcome = multiply(a[0], b[0]) if len(a) == 0: return outcome for i in range(1, len(a)): outcome = add(outcome, multiply(a[i], b[i])) return outcome
def get_ciphertexts(n): ciphertexts_R = [0]*n ciphertexts_S = [0]*n for i in range(n): r = randint(1,curve_order-1) s = randint(1,curve_order-1) ciphertexts_R[i] = multiply(G1, r) ciphertexts_S[i] = multiply(G1, s) return [ciphertexts_R, ciphertexts_S]
def gprod_prove_inner(current_hash, crs, vec_b, vec_c,inner_prod, n, logn): [crs_g, crs_h, u] = crs[:] proof = [] ### Adding in zero knowledge vec_r = [0]*n; for i in range(n): vec_r[i] = randbelow(curve_order) R = compute_multiexp(crs_h[:], vec_r[:]) blinder_2 = compute_innerprod(vec_b[:], vec_r[:]) current_hash = hash_integers([current_hash,int(R[0]),int(R[1]), int(R[2]), blinder_2]) x = current_hash % curve_order inner_prod = (inner_prod + blinder_2 * x ) % curve_order for i in range(n): vec_c[i] = (vec_c[i] + vec_r[i] * x) % curve_order ### Inserting inner_prod into exponent. current_hash = hash_integers([current_hash,inner_prod]) x = current_hash % curve_order; u = multiply(u, x) for j in range(logn): n = n // 2 zL = compute_innerprod(vec_b[n:], vec_c[:n]) zR = compute_innerprod(vec_b[:n], vec_c[n:]) CL = add(compute_multiexp(crs_g[:n], vec_b[n:]), compute_multiexp(crs_h[n:],vec_c[:n])) CL = add(CL, multiply(u, zL)) CR = add(compute_multiexp(crs_g[n:], vec_b[:n]), compute_multiexp(crs_h[:n],vec_c[n:])) CR = add(CR, multiply(u, zR)) proof.append([CL, CR]) current_hash = hash_integers([current_hash,int(CL[0]),int(CL[1]), int(CL[2]), int(CR[0]), int(CR[1]), int(CR[2])]) x = current_hash % curve_order; inv_x =inverse(x); for i in range(n): crs_g[i] = add(multiply(crs_g[n + i],inv_x), crs_g[i] ) crs_h[i] = add(multiply(crs_h[n + i],x), crs_h[i] ) vec_b[i] = (vec_b[i] + x * vec_b[n + i] ) % curve_order vec_c[i] = (vec_c[i] + inv_x * vec_c[n + i] ) % curve_order crs_g = crs_g[:n]; crs_h = crs_h[:n] vec_b = vec_b[:n]; vec_c = vec_c[:n] return [current_hash, [R, blinder_2, proof[:], vec_b[0], vec_c[0]]]
def gprod_prove_outer(current_hash, crs, vec_a, len_gprod, gprod, n, logn): [crs_g, u, crs_se1, crs_se2] = crs[:] vec_b = [0] * n vec_b[0] = 1 for i in range(1,len_gprod): vec_b[i] = vec_a[i] * vec_b[i-1] % curve_order for i in range(len_gprod,n): vec_b[i] = randbelow(curve_order) B = compute_multiexp(crs_g[:], vec_b[:]) blinder = compute_innerprod(vec_a[len_gprod:],vec_b[len_gprod:]) current_hash = hash_integers([current_hash, gprod, blinder, int(B[0]), int(B[1]), int(B[2])]) x = current_hash % curve_order; inv_x =inverse(x); vec_c = [0] * n; pow_x = x; pow_x2 = 1 for i in range(len_gprod-1): vec_c[i] = ( vec_a[i+1] * pow_x - pow_x2) % curve_order pow_x = pow_x * x % curve_order pow_x2 = pow_x2 * x % curve_order vec_c[len_gprod-1] = (vec_a[0] * pow_x - pow_x2) % curve_order pow_x = pow_x * x % curve_order for i in range(len_gprod, n): vec_c[i] = (vec_a[i] * pow_x) % curve_order crs_h = [0]*n; pow_inv_x = inv_x for i in range(len_gprod - 1): crs_h[i] = multiply(crs_g[i+1], pow_inv_x) pow_inv_x = pow_inv_x * inv_x % curve_order crs_h[len_gprod-1] = multiply(crs_g[0], pow_inv_x) pow_inv_x = pow_inv_x * inv_x % curve_order for i in range(len_gprod, n): crs_h[i] = multiply(crs_g[i], pow_inv_x) inner_prod = (blinder * (x ** (len_gprod+1)) + gprod * (x ** len_gprod) - 1) % curve_order crs = [crs_g[:],crs_h[:],u] # [current_hash, inner_proof] = gprod_prove_inner(current_hash, crs[:], vec_b[:], vec_c[:], inner_prod, n, logn) inner_prod_info = [crs_h[:], vec_b[:], vec_c[:], inner_prod] return [current_hash, [B, blinder], inner_prod_info[:]]
def gprod_verify_inner(current_hash, crs, vec_crs_h_exp, C, inner_prod, inner_proof, len_gprod, n, logn): [crs_g, crs_h, u] = crs[:] ### Adding in zero knowledge [R, blinder_2,proof, last_b, last_c] = inner_proof[:] current_hash = hash_integers([current_hash,int(R[0]),int(R[1]), int(R[2]), blinder_2]) x = current_hash % curve_order inner_prod = (inner_prod + blinder_2 * x ) % curve_order C = add(C, multiply(R,x)) ### Putting inner_prod into exponent. current_hash = hash_integers([current_hash,inner_prod]) x = current_hash % curve_order; u = multiply(u, x) C = add(C, multiply(u,inner_prod)) vec_crs_g_exp = [1] * n; vec_crs_h_shifted = [1] * n; n_var = n for j in range(logn): n_var = n_var // 2 [CL, CR] = proof[j] current_hash = hash_integers([current_hash,int(CL[0]),int(CL[1]), int(CL[2]), int(CR[0]), int(CR[1]), int(CR[2])]) x = current_hash % curve_order; inv_x =inverse(x) for i in range(n): bin_i = int_to_binaryintarray(i,logn) if bin_i[logn - j - 1] == 1: vec_crs_g_exp[i] = (vec_crs_g_exp[i] * inv_x) % curve_order vec_crs_h_shifted[i] = (vec_crs_h_shifted[i] * x) % curve_order C = add(add(multiply(CR, inv_x), C), multiply(CL, x)) vec_crs_h_exp[0] = (vec_crs_h_exp[0] * vec_crs_h_shifted[len_gprod - 1]) % curve_order for i in range(1,len_gprod): vec_crs_h_exp[i] = (vec_crs_h_exp[i] * vec_crs_h_shifted[i-1]) % curve_order for i in range(len_gprod,n): vec_crs_h_exp[i] = (vec_crs_h_exp[i] * vec_crs_h_shifted[i]) % curve_order inner_prod = last_b * last_c % curve_order final_g = compute_multiexp(crs_g[:], vec_crs_g_exp[:]) final_h = compute_multiexp(crs_h[:], vec_crs_h_exp[:]) expected_outcome = multiply(final_g, curve_order - last_b) expected_outcome = add(expected_outcome, multiply(final_h, curve_order - last_c)) expected_outcome = add(expected_outcome, multiply(u, curve_order - inner_prod)) if add( expected_outcome, C) != (1,1,0): print("ERROR: final exponent is incorrect") return [current_hash, 0] return [current_hash, 1]
def gprod_verify_outer(current_hash, crs, A, len_gprod, gprod, gprod_proof, n, logn): [crs_g, u, crs_se1, crs_se2] = crs[:] [B, blinder] = gprod_proof[:] current_hash = hash_integers([current_hash, gprod, blinder, int(B[0]), int(B[1]), int(B[2])]) x = current_hash % curve_order; inv_x =inverse(x); C = crs_g[0] for i in range(1,len_gprod): C = add( C, crs_g[i]) C = multiply(C, curve_order - inv_x) C = add(C, A) vec_crs_h_exp = [1]*n; pow_inv_x = inv_x for i in range(1,len_gprod): vec_crs_h_exp[i] = pow_inv_x pow_inv_x = pow_inv_x * inv_x % curve_order vec_crs_h_exp[0] = pow_inv_x pow_inv_x = pow_inv_x * inv_x % curve_order for i in range(len_gprod, n): vec_crs_h_exp[i] = pow_inv_x inner_prod = (blinder * (x ** (len_gprod+1)) + gprod * (x ** len_gprod) - 1) % curve_order # [current_hash, b] = gprod_verify_inner(current_hash, crs[:], vec_crs_h_exp[:], C, inner_prod, inner_proof[:], # len_gprod, n, logn) inner_prod_info = [vec_crs_h_exp[:], B, C, inner_prod, len_gprod] return [current_hash, inner_prod_info[:]]
def get_crs(n): crs = [0]*n for i in range(n): a = randint(1,curve_order-1) crs[i] = multiply(G1, a) return crs
def shuffle(ciphertexts_R, ciphertexts_S): n = len(ciphertexts_R) leftover_values = [0] * n for i in range(n): leftover_values[i] = i shuffle = [0] * n for i in range(n): k = randint(0, n - i - 1) shuffle[i] = leftover_values.pop(k) ciphertexts_shuffled_R = [0] * n ciphertexts_shuffled_S = [0] * n for i in range(n): ciphertexts_shuffled_R[i] = ciphertexts_R[shuffle[i]][:] ciphertexts_shuffled_S[i] = ciphertexts_S[shuffle[i]][:] r = randbelow(curve_order) for i in range(n): ciphertexts_shuffled_R[i] = multiply(ciphertexts_shuffled_R[i], r) ciphertexts_shuffled_S[i] = multiply(ciphertexts_shuffled_S[i], r) return (ciphertexts_shuffled_R, ciphertexts_shuffled_S, shuffle, r)
def sameexp_prove(current_hash, g1, g2, h1, h2, y1, y2, exp, bl1, bl2): r = randbelow(curve_order) s = randbelow(curve_order) t = randbelow(curve_order) R1 = add(multiply(g1, r), multiply(h1, s)) R2 = add(multiply(g2, r), multiply(h2, t)) current_hash = hash_integers([ current_hash, int(g1[0]), int(g1[1]), int(g1[2]), int(g2[0]), int(g2[1]), int(g2[2]), int(y1[0]), int(y1[1]), int(y1[2]), int(y2[0]), int(y2[1]), int(y2[2]), int(R1[0]), int(R1[1]), int(R1[2]), int(R2[0]), int(R2[1]), int(R2[2]) ]) x = current_hash % curve_order u1 = (r + x * exp) % curve_order u2 = (s + x * bl1) % curve_order u3 = (t + x * bl2) % curve_order return (current_hash, [R1, R2, u1, u2, u3])
def sameexp_verify(current_hash, g1, g2, h1, h2, y1, y2, sameexp_proof): [R1, R2, u1, u2, u3] = sameexp_proof[:] current_hash = hash_integers([ current_hash, int(g1[0]), int(g1[1]), int(g1[2]), int(g2[0]), int(g2[1]), int(g2[2]), int(y1[0]), int(y1[1]), int(y1[2]), int(y2[0]), int(y2[1]), int(y2[2]), int(R1[0]), int(R1[1]), int(R1[2]), int(R2[0]), int(R2[1]), int(R2[2]) ]) x = current_hash % curve_order outcome1 = add(R1, multiply(y1, x)) outcome1 = add(outcome1, multiply(g1, curve_order - u1)) outcome1 = add(outcome1, multiply(h1, curve_order - u2)) outcome2 = add(R2, multiply(y2, x)) outcome2 = add(outcome2, multiply(g2, curve_order - u1)) outcome2 = add(outcome2, multiply(h2, curve_order - u3)) if outcome1 != Z1: print("ERROR: schnorr proof doesn't verify Z1") return (current_hash, 0) if outcome2 != Z1: print("ERROR: schnorr proof doesn't verify Z2") return (current_hash, 0) return (current_hash, 1)
def shuffle_prove(crs, num_blinders, ciphertexts_R, ciphertexts_S, ciphertexts_T, ciphertexts_U, shuffle, r): [crs_g, u, crs_se1, crs_se2] = crs[:] n = len(ciphertexts_R) + num_blinders logn = int(math.log(n, 2)) vec_m = [0] * n for i in range(len(ciphertexts_R)): vec_m[i] = shuffle[i] for i in range(len(ciphertexts_R), n): vec_m[i] = randbelow(curve_order) M = compute_multiexp(crs_g[:], vec_m[:]) current_hash = hash_integers([int(M[0]), int(M[1]), int(M[2])]) for i in range(len(ciphertexts_T)): current_hash = hash_integers([ current_hash, int(ciphertexts_T[i][0]), int(ciphertexts_T[i][1]), int(ciphertexts_T[i][2]), int(ciphertexts_U[i][0]), int(ciphertexts_U[i][1]), int(ciphertexts_U[i][2]) ]) print("current_hash = ", current_hash) vec_a = [0] * len(ciphertexts_R) for i in range(len(ciphertexts_R)): vec_a[i] = current_hash % curve_order current_hash = hash_integers([current_hash]) vec_a_shuffled = [0] * n for i in range(len(ciphertexts_R)): vec_a_shuffled[i] = vec_a[shuffle[i]] for i in range(len(ciphertexts_R), n): vec_a_shuffled[i] = randbelow(curve_order) A = compute_multiexp(crs_g[:], vec_a_shuffled[:]) current_hash = hash_integers( [current_hash, int(A[0]), int(A[1]), int(A[2])]) alpha = current_hash % curve_order current_hash = hash_integers([current_hash]) beta = current_hash % curve_order vec_gprod = vec_a_shuffled[:] for i in range(n): vec_gprod[i] = (vec_gprod[i] + vec_m[i] * alpha + beta) % curve_order gprod = 1 for i in range(len(ciphertexts_R)): gprod = (gprod * vec_gprod[i]) % curve_order start = timer() [current_hash, gprod_proof, inner_prod_info] = gprod_prove(current_hash, crs[:], vec_gprod[:], len(ciphertexts_R), gprod, n, logn) end = timer() print("gprod time = ", end - start) [crs_h, vec_b, vec_c, inner_prod] = inner_prod_info[:] start = timer() R = compute_multiexp(ciphertexts_R[:], vec_a[:]) S = compute_multiexp(ciphertexts_S[:], vec_a[:]) end = timer() print("R, S time = ", end - start, len(vec_a[:len(ciphertexts_R)])) vec_gammas = [0] * num_blinders vec_deltas = [0] * num_blinders current_hash = hash_integers( [current_hash, int(A[0]), int(A[1]), int(A[2])]) for i in range(num_blinders): current_hash = hash_integers([current_hash]) vec_gammas[i] = current_hash % curve_order current_hash = hash_integers([current_hash]) vec_deltas[i] = current_hash % curve_order blinder_t = 0 blinder_u = 0 for i in range(num_blinders): blinder_t = (blinder_t + vec_gammas[i] * vec_a_shuffled[len(ciphertexts_R) + i]) % curve_order blinder_u = (blinder_u + vec_deltas[i] * vec_a_shuffled[len(ciphertexts_R) + i]) % curve_order T = add(multiply(R, r), multiply(crs_se1, blinder_t)) U = add(multiply(S, r), multiply(crs_se2, blinder_u)) for i in range(num_blinders): ciphertexts_T.append(multiply(crs_se1, vec_gammas[i])) ciphertexts_U.append(multiply(crs_se2, vec_deltas[i])) (current_hash, sameexp_proof) = sameexp_prove(current_hash, R, S, crs_se1, crs_se2, T, U, r, blinder_t, blinder_u) start = timer() crs = [crs_g[:], crs_h[:], u] [current_hash, gprod_and_multiexp_proof] = prove_multiexp_and_gprod_inner( current_hash, crs[:], vec_b[:], vec_c[:], inner_prod, ciphertexts_T[:], ciphertexts_U[:], vec_a_shuffled[:], n, logn) end = timer() print("inner product time = ", end - start) return [ M, A, gprod_proof[:], T, U, sameexp_proof, gprod_and_multiexp_proof ]
def shuffle_verify(crs, num_blinders, ciphertexts_R, ciphertexts_S, ciphertexts_T, ciphertexts_U, shuffle_proof): [crs_g, u, crs_se1, crs_se2] = crs[:] n = len(ciphertexts_R) + num_blinders logn = int(math.log(n, 2)) [M, A, gprod_proof, T, U, sameexp_proof, inner_proof] = shuffle_proof[:] current_hash = hash_integers([int(M[0]), int(M[1]), int(M[2])]) for i in range(len(ciphertexts_T)): current_hash = hash_integers([ current_hash, int(ciphertexts_T[i][0]), int(ciphertexts_T[i][1]), int(ciphertexts_T[i][2]), int(ciphertexts_U[i][0]), int(ciphertexts_U[i][1]), int(ciphertexts_U[i][2]) ]) vec_a = [0] * len(ciphertexts_R) for i in range(len(ciphertexts_R)): vec_a[i] = current_hash % curve_order current_hash = hash_integers([current_hash]) current_hash = hash_integers( [current_hash, int(A[0]), int(A[1]), int(A[2])]) alpha = current_hash % curve_order current_hash = hash_integers([current_hash]) beta = current_hash % curve_order gprod = 1 for i in range(len(ciphertexts_R)): gprod = (gprod * (vec_a[i] + i * alpha + beta)) % curve_order A1 = crs_g[0] for i in range(1, n): A1 = add(A1, crs_g[i]) A1 = multiply(A1, beta) A1 = add(A1, multiply(M, alpha)) A1 = add(A1, A) start = timer() [current_hash, inner_prod_info] = gprod_verify(current_hash, crs[:], A1, len(ciphertexts_R), gprod, gprod_proof[:], n, logn) end = timer() print("gprod time = ", end - start) [vec_crs_h_exp, B, C, inner_prod, len_gprod] = inner_prod_info[:] start = timer() R = compute_multiexp(ciphertexts_R[:], vec_a[:]) S = compute_multiexp(ciphertexts_S[:], vec_a[:]) end = timer() print("R, S time = ", end - start) vec_gammas = [0] * num_blinders vec_deltas = [0] * num_blinders current_hash = hash_integers( [current_hash, int(A[0]), int(A[1]), int(A[2])]) for i in range(num_blinders): current_hash = hash_integers([current_hash]) vec_gammas[i] = current_hash % curve_order current_hash = hash_integers([current_hash]) vec_deltas[i] = current_hash % curve_order (current_hash, b) = sameexp_verify(current_hash, R, S, crs_se1, crs_se2, T, U, sameexp_proof[:]) if b != 1: print("VERIFICATION FAILURE: does not have same exponent") return 0 for i in range(num_blinders): ciphertexts_T.append(multiply(crs_se1, vec_gammas[i])) ciphertexts_U.append(multiply(crs_se2, vec_deltas[i])) start = timer() [current_hash, b] = verify_multiexp_and_gprod_inner(current_hash, crs[:], vec_crs_h_exp, len_gprod, B, C, inner_prod, ciphertexts_T[:], ciphertexts_U[:], A, T, U, inner_proof[:], n, logn) end = timer() print("inner product time = ", end - start) if b != 1: print("VERIFICATION FAILURE: does not have correct inner product") return 0 return 1
def multiexp_verify(current_hash, crs, ciphertexts_R, ciphertexts_S, commit_exps, ip_proof, multiexp_R, multiexp_S, n, logn): [R, Rbl, Sbl, proof, last_exp] = ip_proof[:] ### Adding zero-knowledge current_hash = hash_integers([ current_hash, int(R[0]), int(R[1]), int(R[2]), int(Rbl[0]), int(Rbl[1]), int(Rbl[2]), int(Sbl[0]), int(Sbl[1]), int(Sbl[2]) ]) x = current_hash % curve_order commit_exps = add(commit_exps, multiply(R, x)) multiexp_R = add(multiexp_R, multiply(Rbl, x)) multiexp_S = add(multiexp_S, multiply(Sbl, x)) vec_crs_exp = [1] * n n_var = n for j in range(logn): n_var = n_var // 2 ## print("i = ", i, "commit_exps = ", commit_exps) [zL, zR, CL, CR] = proof[j] current_hash = hash_integers([ current_hash, int(zL[0][0]), int(zL[0][1]), int(zR[0][0]), int(zR[0][1]), int(CL[0]), int(CL[1]), int(CR[0]), int(CR[1]) ]) x = current_hash inv_x = inverse(x) for i in range(n): bin_i = int_to_binaryintarray(i, logn) if bin_i[logn - j - 1] == 1: vec_crs_exp[i] = (vec_crs_exp[i] * x) % curve_order multiexp_R = add(add(multiply(zL[0], x), multiexp_R), multiply(zR[0], inv_x)) multiexp_S = add(add(multiply(zL[1], x), multiexp_S), multiply(zR[1], inv_x)) commit_exps = add(add(multiply(CR, inv_x), commit_exps), multiply(CL, x)) crs_final = compute_multiexp(crs[:], vec_crs_exp[:]) R_final = compute_multiexp(ciphertexts_R[:], vec_crs_exp[:]) S_final = compute_multiexp(ciphertexts_S[:], vec_crs_exp[:]) if add(multiply(crs_final, curve_order - last_exp), commit_exps) != (1, 1, 0): print("ERROR: final exponent is incorrect") return [current_hash, 0] if add(multiply(R_final, curve_order - last_exp), multiexp_R) != (1, 1, 0): print("ERROR: final ciphertext R is incorrect") return [current_hash, 0] if add(multiply(S_final, curve_order - last_exp), multiexp_S) != (1, 1, 0): print("ERROR: final ciphertext S is incorrect") return [current_hash, 0] return [current_hash, 1]
def multiexp_prove(current_hash, crs, ciphertexts_R, ciphertexts_S, exponents, n, logn): proof = [] ### Adding in zero knowledge vec_r = [0] * n for i in range(n): vec_r[i] = randbelow(curve_order) R = compute_multiexp(crs[:], vec_r[:]) Rbl = compute_multiexp(ciphertexts_R[:], vec_r[:]) Sbl = compute_multiexp(ciphertexts_S[:], vec_r[:]) current_hash = hash_integers([ current_hash, int(R[0]), int(R[1]), int(R[2]), int(Rbl[0]), int(Rbl[1]), int(Rbl[2]), int(Sbl[0]), int(Sbl[1]), int(Sbl[2]) ]) x = current_hash % curve_order for i in range(n): exponents[i] = (exponents[i] + vec_r[i] * x) % curve_order for j in range(logn): n = n // 2 zL = [ compute_multiexp(ciphertexts_R[n:], exponents[:n]), compute_multiexp(ciphertexts_S[n:], exponents[:n]) ] zR = [ compute_multiexp(ciphertexts_R[:n], exponents[n:]), compute_multiexp(ciphertexts_S[:n], exponents[n:]) ] CL = compute_multiexp(crs[n:], exponents[:n]) CR = compute_multiexp(crs[:n], exponents[n:]) proof.append([zL, zR, CL, CR]) current_hash = hash_integers([ current_hash, int(zL[0][0]), int(zL[0][1]), int(zR[0][0]), int(zR[0][1]), int(CL[0]), int(CL[1]), int(CR[0]), int(CR[1]) ]) x = current_hash % curve_order inv_x = inverse(x) for i in range(n): crs[i] = add(multiply(crs[n + i], x), crs[i]) ciphertexts_R[i] = add(multiply(ciphertexts_R[n + i], x), ciphertexts_R[i]) ciphertexts_S[i] = add(multiply(ciphertexts_S[n + i], x), ciphertexts_S[i]) crs = crs[:n] ciphertexts_R = ciphertexts_R[:n] ciphertexts_S = ciphertexts_S[:n] for i in range(n): exponents[i] = (exponents[n + i] * inv_x + exponents[i]) % curve_order exponents = exponents[:n] return [current_hash, [R, Rbl, Sbl, proof, exponents[0]]]
def prove_multiexp_and_gprod_inner(current_hash, crs, vec_b, vec_c, inner_prod, ciphertexts_1, ciphertexts_2, vec_exp, n, logn): [crs_g, crs_h_scaled, u] = crs[:] crs_h = crs_g[:] proof = [] ### Adding in zero knowledge vec_rgp = [0] * n vec_sgp = [0] * n vec_rme = [0] * n for i in range(n): vec_rgp[i] = randbelow(curve_order) vec_sgp[i] = randbelow(curve_order) vec_rme[i] = randbelow(curve_order) Rgp = compute_multiexp(crs_g[:], vec_rgp[:]) Sgp = compute_multiexp(crs_h_scaled[:], vec_sgp[:]) blgp1 = (compute_innerprod(vec_b[:], vec_sgp[:]) + compute_innerprod(vec_c[:], vec_rgp[:])) % curve_order blgp2 = compute_innerprod(vec_rgp[:], vec_sgp[:]) Rme = compute_multiexp(crs_h[:], vec_rme[:]) Bl1me = compute_multiexp(ciphertexts_1[:], vec_rme[:]) Bl2me = compute_multiexp(ciphertexts_2[:], vec_rme[:]) zkinfo = [Rgp, Sgp, Rme, blgp1, blgp2, Bl1me, Bl2me] current_hash = hash_integers([ current_hash, int(Rgp[0]), int(Rgp[1]), int(Rgp[2]), int(Sgp[0]), int(Sgp[1]), int(Sgp[2]), blgp1, blgp2, int(Rme[0]), int(Rme[1]), int(Rme[2]), int(Bl1me[0]), int(Bl1me[1]), int(Bl1me[2]), int(Bl2me[0]), int(Bl2me[1]), int(Bl2me[2]) ]) x = current_hash % curve_order inner_prod = (inner_prod + blgp1 * x + blgp2 * x**2) % curve_order for i in range(n): vec_b[i] = (vec_b[i] + vec_rgp[i] * x) % curve_order vec_c[i] = (vec_c[i] + vec_sgp[i] * x) % curve_order vec_exp[i] = (vec_exp[i] + vec_rme[i] * x) % curve_order ### Inserting inner_prod into exponent. current_hash = hash_integers([current_hash, inner_prod]) x = current_hash % curve_order u = multiply(u, x) for j in range(logn): n = n // 2 zLgp = compute_innerprod(vec_b[n:], vec_c[:n]) zRgp = compute_innerprod(vec_b[:n], vec_c[n:]) zLme = [ compute_multiexp(ciphertexts_1[n:], vec_exp[:n]), compute_multiexp(ciphertexts_2[n:], vec_exp[:n]) ] zRme = [ compute_multiexp(ciphertexts_1[:n], vec_exp[n:]), compute_multiexp(ciphertexts_2[:n], vec_exp[n:]) ] CLgp_b = add(compute_multiexp(crs_g[:n], vec_b[n:]), multiply(u, zLgp)) CLgp_c = compute_multiexp(crs_h_scaled[n:], vec_c[:n]) CRgp_b = add(compute_multiexp(crs_g[n:], vec_b[:n]), multiply(u, zRgp)) CRgp_c = compute_multiexp(crs_h_scaled[:n], vec_c[n:]) CLme = compute_multiexp(crs_h[n:], vec_exp[:n]) CRme = compute_multiexp(crs_h[:n], vec_exp[n:]) proof.append([CLgp_b, CLgp_c, CRgp_b, CRgp_c, zLme, zRme, CLme, CRme]) current_hash = hash_integers([ current_hash, int(CLgp_b[0]), int(CLgp_b[1]), int(CLgp_b[2]), int(CLgp_c[0]), int(CLgp_c[1]), int(CLgp_c[2]), int(CRgp_b[0]), int(CRgp_b[1]), int(CRgp_b[2]), int(CRgp_c[0]), int(CRgp_c[1]), int(CRgp_c[2]), int(zLme[0][0]), int(zLme[0][1]), int(zLme[0][2]), int(zRme[0][0]), int(zRme[0][1]), int(zRme[0][2]), int(CLme[0]), int(CLme[1]), int(CLme[2]), int(CRme[0]), int(CRme[1]), int(CRme[2]) ]) x = current_hash % curve_order inv_x = inverse(x) for i in range(n): crs_g[i] = add(multiply(crs_g[n + i], inv_x), crs_g[i]) crs_h_scaled[i] = add(multiply(crs_h_scaled[n + i], x), crs_h_scaled[i]) vec_b[i] = (vec_b[i] + x * vec_b[n + i]) % curve_order vec_c[i] = (vec_c[i] + inv_x * vec_c[n + i]) % curve_order crs_h[i] = add(multiply(crs_h[n + i], x), crs_h[i]) ciphertexts_1[i] = add(multiply(ciphertexts_1[n + i], x), ciphertexts_1[i]) ciphertexts_2[i] = add(multiply(ciphertexts_2[n + i], x), ciphertexts_2[i]) vec_exp[i] = (vec_exp[n + i] * inv_x + vec_exp[i]) % curve_order crs_g = crs_g[:n] crs_h_scaled = crs_h_scaled[:n] vec_b = vec_b[:n] vec_c = vec_c[:n] crs_h = crs_h[:n] ciphertexts_1 = ciphertexts_1[:n] ciphertexts_2 = ciphertexts_2[:n] vec_exp = vec_exp[:n] final_values = [vec_b[0], vec_c[0], vec_exp[0]] current_hash = hash_integers( [current_hash, vec_b[0], vec_c[0], vec_exp[0]]) return [current_hash, [zkinfo[:], proof[:], final_values[:]]]
def verify_multiexp_and_gprod_inner(current_hash, crs, vec_crs_h_exp, len_gprod, B, C, inner_prod, ciphertexts_1, ciphertexts_2, commit_exps, multiexp_1, multiexp_2, inner_proof, n, logn): [crs_g, u, crs_se1, crs_se2] = crs[:] ### Adding in zero knowledge [zkinfo, proof, final_values] = inner_proof[:] [Rgp, Sgp, Rme, blgp1, blgp2, Bl1me, Bl2me] = zkinfo[:] current_hash = hash_integers([ current_hash, int(Rgp[0]), int(Rgp[1]), int(Rgp[2]), int(Sgp[0]), int(Sgp[1]), int(Sgp[2]), blgp1, blgp2, int(Rme[0]), int(Rme[1]), int(Rme[2]), int(Bl1me[0]), int(Bl1me[1]), int(Bl1me[2]), int(Bl2me[0]), int(Bl2me[1]), int(Bl2me[2]) ]) x = current_hash % curve_order inner_prod = (inner_prod + blgp1 * x + blgp2 * x**2) % curve_order B = add(B, multiply(Rgp, x)) C = add(C, multiply(Sgp, x)) commit_exps = add(commit_exps, multiply(Rme, x)) multiexp_1 = add(multiexp_1, multiply(Bl1me, x)) multiexp_2 = add(multiexp_2, multiply(Bl2me, x)) ### Putting inner_prod into exponent. current_hash = hash_integers([current_hash, inner_prod]) x = current_hash % curve_order u = multiply(u, x) B = add(B, multiply(u, inner_prod)) [final_b, final_c, final_exp] = final_values[:] vec_crs_g_exp = [final_b] * n vec_crs_h_shifted = [1] * n n_var = n for j in range(logn): n_var = n_var // 2 [CLgp_b, CLgp_c, CRgp_b, CRgp_c, zLme, zRme, CLme, CRme] = proof[j] current_hash = hash_integers([ current_hash, int(CLgp_b[0]), int(CLgp_b[1]), int(CLgp_b[2]), int(CLgp_c[0]), int(CLgp_c[1]), int(CLgp_c[2]), int(CRgp_b[0]), int(CRgp_b[1]), int(CRgp_b[2]), int(CRgp_c[0]), int(CRgp_c[1]), int(CRgp_c[2]), int(zLme[0][0]), int(zLme[0][1]), int(zLme[0][2]), int(zRme[0][0]), int(zRme[0][1]), int(zRme[0][2]), int(CLme[0]), int(CLme[1]), int(CLme[2]), int(CRme[0]), int(CRme[1]), int(CRme[2]) ]) x = current_hash % curve_order inv_x = inverse(x) for i in range(n): bin_i = int_to_binaryintarray(i, logn) if bin_i[logn - j - 1] == 1: vec_crs_g_exp[i] = (vec_crs_g_exp[i] * inv_x) % curve_order vec_crs_h_shifted[i] = (vec_crs_h_shifted[i] * x) % curve_order B = add(add(multiply(CRgp_b, inv_x), B), multiply(CLgp_b, x)) C = add(add(multiply(CRgp_c, inv_x), C), multiply(CLgp_c, x)) multiexp_1 = add(add(multiply(zLme[0], x), multiexp_1), multiply(zRme[0], inv_x)) multiexp_2 = add(add(multiply(zLme[1], x), multiexp_2), multiply(zRme[1], inv_x)) commit_exps = add(add(multiply(CRme, inv_x), commit_exps), multiply(CLme, x)) ciphertexts_1_final = compute_multiexp(ciphertexts_1[:], vec_crs_h_shifted[:]) ciphertexts_2_final = compute_multiexp(ciphertexts_2[:], vec_crs_h_shifted[:]) if add(multiply(ciphertexts_1_final, curve_order - final_exp), multiexp_1) != (1, 1, 0): print("ERROR: final ciphertext 1 is incorrect") return [current_hash, 0] if add(multiply(ciphertexts_2_final, curve_order - final_exp), multiexp_2) != (1, 1, 0): print("ERROR: final ciphertext 2 is incorrect") return [current_hash, 0] current_hash = hash_integers([current_hash, final_b, final_c, final_exp]) x = current_hash % curve_order vec_crs_h_exp[0] = (x**2 * vec_crs_g_exp[0] + x * vec_crs_h_shifted[0] * final_exp + vec_crs_h_exp[0] * vec_crs_h_shifted[len_gprod - 1] * final_c) % curve_order for i in range(1, len_gprod): vec_crs_h_exp[i] = (x**2 * vec_crs_g_exp[i] + x * vec_crs_h_shifted[i] * final_exp + vec_crs_h_exp[i] * vec_crs_h_shifted[i - 1] * final_c) % curve_order for i in range(len_gprod, n): vec_crs_h_exp[i] = ( x**2 * vec_crs_g_exp[i] + x * vec_crs_h_shifted[i] * final_exp + vec_crs_h_exp[i] * vec_crs_h_shifted[i] * final_c) % curve_order inner_prod = final_b * final_c % curve_order expected_outcome = compute_multiexp(crs_g[:], vec_crs_h_exp[:]) expected_outcome = add(expected_outcome, multiply(u, (inner_prod * x**2) % curve_order)) expected_outcome = add(expected_outcome, multiply(commit_exps, curve_order - x)) expected_outcome = add(expected_outcome, multiply(C, curve_order - 1)) expected_outcome = add(expected_outcome, multiply(B, (-x**2) % curve_order)) if expected_outcome != Z1: print("ERROR: final exponent is incorrect") return [current_hash, 0] return [current_hash, 1]