groth_inner_product.sage 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. import numpy as np
  2. # Implementation of Groth09 inner product proof
  3. q = 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001
  4. K = GF(q)
  5. a = K(0x00)
  6. b = K(0x05)
  7. E = EllipticCurve(K, (a, b))
  8. G = E(0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000000, 0x02)
  9. p = 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001
  10. assert E.order() == p
  11. Scalar = GF(p)
  12. x = np.array([
  13. Scalar(110), Scalar(56), Scalar(89), Scalar(6543), Scalar(2)
  14. ])
  15. y = np.array([
  16. Scalar(4), Scalar(88), Scalar(14), Scalar(33), Scalar(6)
  17. ])
  18. z = x.dot(y)
  19. assert len(x) == len(y)
  20. # Create some generator points. Normally we would use hash to curve.
  21. # All these points will be generators since the curve is a cyclic group
  22. H = E.random_element()
  23. G_vec = [E.random_element() for _ in range(len(x))]
  24. # We will now construct a proof
  25. # Commitments
  26. def dot_product(x, y):
  27. result = None
  28. for x_i, y_i in zip(x, y):
  29. if result is None:
  30. result = int(x_i) * y_i
  31. else:
  32. result += int(x_i) * y_i
  33. return result
  34. t = Scalar.random_element()
  35. r = Scalar.random_element()
  36. s = Scalar.random_element()
  37. C_z = int(t) * H + int(z) * G
  38. C_x = int(r) * H + dot_product(x, G_vec)
  39. C_y = int(s) * H + dot_product(y, G_vec)
  40. d_x = np.array([Scalar.random_element() for _ in range(len(x))])
  41. d_y = np.array([Scalar.random_element() for _ in range(len(x))])
  42. r_d = Scalar.random_element()
  43. s_d = Scalar.random_element()
  44. A_d = int(r_d) * H + dot_product(d_x, G_vec)
  45. B_d = int(s_d) * H + dot_product(d_y, G_vec)
  46. # (cx + d_x)(cy + d_y) = d_x d_y + c(x d_y + y d_x) + c^2 xy
  47. t_0 = Scalar.random_element()
  48. t_1 = Scalar.random_element()
  49. C_0 = int(t_0) * H + int(d_x.dot(d_y)) * G
  50. C_1 = int(t_1) * H + int(x.dot(d_y) + y.dot(d_x)) * G
  51. # Challenge
  52. # Using the Fiat-Shamir transform, we would hash the transcript
  53. c = Scalar.random_element()
  54. # Responses
  55. f_x = c * x + d_x
  56. f_y = c * y + d_y
  57. r_x = c * r + r_d
  58. s_y = c * s + s_d
  59. t_z = c**2 * t + c * t_1 + t_0
  60. # Verify
  61. assert int(c) * C_x + A_d == int(r_x) * H + dot_product(f_x, G_vec)
  62. assert int(c) * C_y + B_d == int(s_y) * H + dot_product(f_y, G_vec)
  63. # Actual inner product check
  64. # Comm(f_x f_y) == e^2 C_z + c Comm(x d_y + y d_x) + Comm(d_x d_y)
  65. assert int(t_z) * H + int(f_x.dot(f_y)) * G == int(c**2) * C_z + int(c) * C_1 + C_0