proof_mpc.sage 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  1. '''
  2. bulletproof protocol 2 with multi-exponentiation.
  3. '''
  4. load('../mpc/curve.sage')
  5. load('../mpc/ec_share.sage')
  6. load('../mpc/share.sage')
  7. load('../mpc/beaver.sage')
  8. load('utils.sage')
  9. class MpcProof(object):
  10. def __init__(self, transcript, Q_generator, G_factors, H_factors, G, H, a_shares, b_shares, source, party_id):
  11. '''
  12. create inner product proof
  13. '''
  14. self.n = len(G)
  15. self.m = self.n
  16. assert (self.n == len(H) == len(H_factors) == len(a_shares) == len(b_shares))
  17. self.source = source
  18. self.party_id=party_id
  19. self.Q = Q_generator
  20. self.G = G
  21. self.H = H
  22. self.G_factors = G_factors
  23. self.H_factors = H_factors
  24. self.transcript = transcript
  25. self.L = []
  26. self.R = []
  27. L_l = []
  28. R_l = []
  29. self.c_l = []
  30. self.c_r = []
  31. self.a_shares_l = []
  32. self.a_shares_r = []
  33. self.b_shares_l = []
  34. self.b_shares_r = []
  35. self.G_hist = []
  36. self.H_hist = []
  37. if self.n!=1:
  38. self.n /=2
  39. a_shares_l, a_shares_r = a_shares[0:self.n].copy(), a_shares[self.n:].copy()
  40. b_shares_l, b_shares_r = b_shares[0:self.n].copy(), b_shares[self.n:].copy()
  41. self.a_shares_l += [a_shares_l.copy()]
  42. self.a_shares_r += [a_shares_r.copy()]
  43. self.b_shares_l += [b_shares_l.copy()]
  44. self.b_shares_r += [b_shares_r.copy()]
  45. G_l, G_r = G[0:self.n].copy(), G[self.n:].copy()
  46. H_l, H_r = H[0:self.n].copy(), H[self.n:].copy()
  47. self.G_hist+=[[G_l.copy(), G_r.copy()]]
  48. self.H_hist+=[[H_l.copy(), H_r.copy()]]
  49. # authenticated inner product
  50. c_shares_l = [MultiplicationAuthenticatedShares(a_share, b_share, self.source.triplet(self.party_id), self.party_id) for a_share, b_share in zip(a_shares_l, b_shares_r)].copy()
  51. c_shares_r = [MultiplicationAuthenticatedShares(a_share, b_share, self.source.triplet(self.party_id), self.party_id) for a_share, b_share in zip(a_shares_r, b_shares_l)].copy()
  52. self.c_l += [c_shares_l]
  53. self.c_r += [c_shares_r]
  54. #verifier.append_message(b'L', bytes(''.join([l.__str__() for l in [self.L]]), encoding='utf-8'))
  55. #verifier.append_message(b'R', bytes(''.join([r.__str__() for r in [self.R]]), encoding='utf-8'))
  56. #u = K(verifier.challenge_bytes(b'u'))
  57. u = K(1) #for testing purpose
  58. u_inv = 1/u
  59. for i in range(self.n):
  60. # a_prime
  61. a_shares_l[i] = a_shares_l[i].mul_scalar(u) + a_shares_r[i].mul_scalar(u_inv)
  62. # p_prime
  63. b_shares_l[i] = b_shares_l[i].mul_scalar(u_inv) + b_shares_r[i].mul_scalar(u)
  64. #TODO (research) get pt from share.
  65. # G_prime
  66. G_l[i] = to_ec_shares(CurvePoint.msm([G_l[i].share, G_r[i].share], [u_inv * G_factors[i], u * G_factors[self.n+i]]))
  67. # H_prime
  68. H_l[i] = to_ec_shares(CurvePoint.msm([H_l[i].share, H_r[i].share], [u * H_factors[i], u_inv * H_factors[self.n+i]]))
  69. a_shares = a_shares_l # a is a_prime
  70. b_shares = b_shares_l # b is b_prime
  71. G = G_l # G is G_prime
  72. H = H_l # H is H_prime
  73. while self.n!=1:
  74. self.n /=2
  75. a_shares_l, a_shares_r = a_shares[0:self.n], a_shares[self.n:] # a_prime_l, a_prime_r
  76. b_shares_l, b_shares_r = b_shares[0:self.n], b_shares[self.n:] # b_prime_l, b_prime_r
  77. self.a_shares_l += [a_shares_l.copy()]
  78. self.a_shares_r += [a_shares_r.copy()]
  79. self.b_shares_l += [b_shares_l.copy()]
  80. self.b_shares_r += [b_shares_r.copy()]
  81. G_l, G_r = G[0:self.n], G[self.n:] # G_prime_l, G_prime_r
  82. H_l, H_r = H[0:self.n], H[self.n:] # H_prime_l, H_prime_r
  83. self.G_hist += [[G_l, G_r]]
  84. self.H_hist += [[H_l, H_r]]
  85. c_shares_l = [MultiplicationAuthenticatedShares(a_share, b_share, self.source.triplet(self.party_id), self.party_id) for (a_share,b_share) in zip(a_shares_l, b_shares_r)] # c_prime_l
  86. c_shares_r = [MultiplicationAuthenticatedShares(a_share, b_share, self.source.triplet(self.party_id), self.party_id) for (a_share,b_share) in zip(a_shares_r, b_shares_l)] # c_prime_r
  87. self.c_l += [c_shares_l]
  88. self.c_r += [c_shares_r]
  89. #verifier.append_message(b'L', bytes(''.join([l.__str__() for l in [self.L]]), encoding='utf-8'))
  90. #verifier.append_message(b'R', bytes(''.join([r.__str__() for r in [self.R]]), encoding='utf-8'))
  91. #u = K(verifier.challenge_bytes(b'u'))
  92. u = K(1) # for testing purpose
  93. u_inv = 1/u
  94. for i in range(self.n):
  95. # u * a_prime_l + u^{-1} * a_prime_r
  96. a_shares_l[i] = a_shares_l[i].mul_scalar(u) + a_shares_r[i].mul_scalar(u_inv)
  97. # u^{-1} * b_prime_l + u * b_prime_r
  98. b_shares_l[i] = b_shares_l[i].mul_scalar(u_inv) + b_shares_r[i].mul_scalar(u)
  99. # G_l_prime
  100. G_l[i] = to_ec_shares(CurvePoint.msm([G_l[i].share, G_r[i].share], [u_inv, u]))
  101. # H_l_prime
  102. H_l[i] = to_ec_shares(CurvePoint.msm([H_l[i].share, H_r[i].share], [u, u_inv]))
  103. a_shares = a_shares_l
  104. b_shares = b_shares_l
  105. G = G_l
  106. H = H_l
  107. self.a_shares = a_shares[0]
  108. self.b_shares = b_shares[0]
  109. self.G = G
  110. self.H = H
  111. def create(self, their_c_l_shares, their_c_r_shares):
  112. '''
  113. create inner product proof
  114. '''
  115. self.c_l = [[my_c_l[i].mul(their_c_l[i].d, their_c_l[i].e) for i in range(len(my_c_l))] for my_c_l, their_c_l in zip(self.c_l, their_c_l_shares)]
  116. self.c_r = [[my_c_r[i].mul(their_c_r[i].d, their_c_r[i].e) for i in range(len(my_c_r))] for my_c_r, their_c_r in zip(self.c_r, their_c_r_shares)]
  117. # create L,R for proof validation
  118. L_l = []
  119. R_l = []
  120. counter = 0
  121. if self.m!=1:
  122. self.m /= 2
  123. al_share_g = [al_share.mul_scalar(g) for al_share, g in zip(self.a_shares_l[counter], self.G_factors[self.m:2*self.m])]
  124. br_share_h = [br_share.mul_scalar(h) for br_share, h in zip(self.b_shares_r[counter], self.H_factors[0:self.m])]
  125. self.L_gr_al_g_share = MSM(self.G_hist[counter][1], al_share_g, self.source, self.party_id)
  126. self.L_hl_br_h_share = MSM(self.H_hist[counter][0], br_share_h, self.source, self.party_id)
  127. self.L_q_cl_share = MSM(self.Q, self.c_l[counter], self.source, self.party_id)
  128. #self.L_q_cl_share = self.L_hl_br_h_share.copy()
  129. # L, R
  130. # note that P = L*R
  131. L_shares = [self.L_gr_al_g_share, self.L_hl_br_h_share , self.L_q_cl_share]
  132. ar_share_g = [ar_share.mul_scalar(g) for ar_share, g in zip(self.a_shares_r[counter], G_factors[0:self.m])]
  133. bl_share_h = [bl_share.mul_scalar(h) for bl_share, h in zip(self.b_shares_l[counter], H_factors[self.m:2*self.m])]
  134. self.R_gl_ar_g_share = MSM(self.G_hist[counter][0], ar_share_g, self.source, self.party_id)
  135. self.R_hr_bl_h_share = MSM(self.H_hist[counter][1], bl_share_h, self.source, self.party_id)
  136. self.R_q_cr_share = MSM(self.Q, self.c_r[counter], self.source, self.party_id)
  137. R_shares = [self.R_gl_ar_g_share, self.R_hr_bl_h_share, self.R_q_cr_share]
  138. L_l += [L_shares]
  139. R_l += [R_shares]
  140. counter +=1
  141. while self.m!=1:
  142. #TODO
  143. assert(False)
  144. self.m /=2
  145. # L_prime
  146. L_gr_al_share = MSM(self.G_hist[counter][1], self.a_shares_l[counter], self.source, self.party_id)
  147. L_hl_br_share = MSM(self.H_hist[counter][0], self.b_shares_r[counter], self.source, self.party_id)
  148. L_q_cl_share = MSM(self.Q, self.c_l[counter], self.source, self.party_id)
  149. L_shares = [L_gr_al_share, L_hl_br_share, L_q_cl_share]
  150. # R_prime
  151. R_gl_ar_share = MSM(self.G_hist[counter][0], a_shares_r, self.source, self.party_id)
  152. R_hr_bl_share = MSM(self.H_hist[counter][1], b_shares_l, self.source, self.party_id)
  153. R_q_cr_share = MSM(self.Q, self.c_r[counter], self.source, self.party_id)
  154. R_shares = [R_gl_ar_share, R_hr_bl_share, R_q_cr_share]
  155. L_l += [L_shares]
  156. R_l += [R_shares]
  157. counter +=1
  158. #
  159. self.lhs = L_l
  160. self.rhs = R_l
  161. def challenges(self, n, verifier):
  162. challenges = []
  163. challenges_inv = []
  164. lg_n = len(self.lhs)
  165. for L, R in zip(self.lhs, self.rhs):
  166. #verifier.append_message(b'L', bytes(''.join([l.__str__() for l in [L]]), encoding='utf-8'))
  167. #verifier.append_message(b'R', bytes(''.join([r.__str__() for r in [R]]), encoding='utf-8'))
  168. #u = K(verifier.challenge_bytes(b'u'))
  169. u = K(1) # for testing purpose
  170. u_inv = 1/u
  171. challenges += [u]
  172. challenges_inv += [u_inv]
  173. inv_prod = K(1)
  174. for u_inv in challenges_inv:
  175. inv_prod *=K(1)
  176. challenges_sq = [i*i for i in challenges]
  177. challenges_inv_sq = [i*i for i in challenges_inv]
  178. mul_inv = K(1)
  179. for i in challenges_inv:
  180. mul_inv *=i
  181. S = [mul_inv]
  182. for i in range(1,n):
  183. lg_i = 32 - 1 - countZeros(i)
  184. k = 1 << lg_i
  185. u_lg_i_sq = challenges_sq[(lg_n -1) - lg_i]
  186. S += [S[i-k] * u_lg_i_sq]
  187. return challenges_sq, challenges_inv_sq, S
  188. def calculate_c_shares(self, n, verifier, G_factors, H_factors):
  189. self.u_sq, self.u_inv_sq, self.s = self.challenges(n, verifier)
  190. self.gas_shares = [self.a_shares.mul_scalar(s_i * g_i) for g_i, s_i in zip(G_factors, self.s)][:n]
  191. # inverse of count is reverse
  192. self.inv_s = reversed(self.s)
  193. self.hbs_shares = [self.b_shares.mul_scalar(s_i_inv * h_i) for h_i, s_i_inv in zip(H_factors, self.inv_s)]
  194. self.neg_u_sq = [i*K(-1) for i in self.u_sq]
  195. self.neg_u_inv_sq = [i*K(-1) for i in self.u_inv_sq]
  196. # P
  197. ## u^c
  198. self.my_c_shares = [MultiplicationAuthenticatedShares(a_share, b_share, self.source.triplet(self.party_id), self.party_id) for a_share, b_share in zip([self.a_shares], [self.b_shares])]
  199. def open_lr(self, Q, G, H, their_c_shares_de, peer_lhs, peer_rhs):
  200. c_shares = [my_c_share.mul(their_c_shares_de[i][0], their_c_shares_de[i][1]) for i, my_c_share in enumerate(self.my_c_shares)]
  201. self.res_p_1 = MSM(Q, c_shares, self.source, self.party_id)
  202. ## g^{g_factor_a_s}
  203. self.res_p_2 = MSM(G, self.gas_shares, self.source, self.party_id)
  204. ## h^{h_factor_b_s}
  205. self.res_p_3 = MSM(H, self.hbs_shares, self.source, self.party_id)
  206. ## L
  207. for my_lhs, their_lhs in zip(self.lhs, peer_lhs):
  208. L_triad = []
  209. for my_lhs_i, their_lhs_i in zip(my_lhs, their_lhs):
  210. my_lhs_i_de = [[ps.d, ps.e] for ps in my_lhs_i.point_scalars]
  211. their_lhs_i_de = [[ps.d, ps.e] for ps in their_lhs_i.point_scalars]
  212. lhs_i_share = my_lhs_i.msm(their_lhs_i_de)
  213. L_triad += [lhs_i_share]
  214. self.L += [sum_shares(L_triad, self.source, self.party_id)]
  215. ## R
  216. for my_rhs, their_rhs in zip(self.rhs, peer_rhs):
  217. R_triad = []
  218. for my_rhs_i, their_rhs_i in zip(my_rhs, their_rhs):
  219. my_rhs_i_de = [[ps.d, ps.e] for ps in my_rhs_i.point_scalars]
  220. their_rhs_i_de = [[ps.d, ps.e] for ps in their_rhs_i.point_scalars]
  221. rhs_i_share = my_rhs_i.msm(their_rhs_i_de)
  222. R_triad += [rhs_i_share]
  223. self.R += [sum_shares(R_triad, self.source, self.party_id)]
  224. # L^(u^2)
  225. temp = K(0)
  226. self.res_p_4 = MSM(self.L, [AuthenticatedShare(temp, self.source, self.party_id) if self.party_id==0 else AuthenticatedShare(neg_u_sq_i-temp, self.source, self.party_id) for neg_u_sq_i in self.neg_u_sq], self.source, self.party_id)
  227. # R^(u^-2)
  228. self.res_p_5 = MSM(self.R, [AuthenticatedShare(temp, self.source, self.party_id) if self.party_id==0 else AuthenticatedShare(neg_u_inv_sq_i-temp, self.source, self.party_id) for neg_u_inv_sq_i in self.neg_u_inv_sq], self.source, self.party_id)
  229. # P prime = L^{u^2} * P * R^{u^{-1}}
  230. self.res_p = [self.res_p_1, self.res_p_2, self.res_p_3, self.res_p_4, self.res_p_5]
  231. def open_and_validate_P(self, res_p, P):
  232. P_msm_parts = []
  233. for my_res_p, their_res_p in zip(self.res_p, res_p):
  234. my_res_de = [[ps.d, ps.e] for ps in my_res_p.point_scalars]
  235. their_res_de = [[ps.d, ps.e] for ps in their_res_p.point_scalars]
  236. lhs = my_res_p.msm(their_res_de)
  237. rhs = their_res_p.msm(my_res_de)
  238. p_part = lhs.authenticated_open(rhs)
  239. P_msm_parts += [p_part]
  240. # P prime == H(u^{-1} * a_prime_r, u * a_prime_l, u * b_prime_r, u ^ {-1} * b_prime_l, c_prime)
  241. my_P = sum(P_msm_parts)
  242. assert (my_P == P), 'P: {}, expected: {}'.format(my_P, P)