groth_poly_commit.sage 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. import numpy as np
  2. from collections import namedtuple
  3. PolyProof = namedtuple("PolyProof", [
  4. "poly_commit",
  5. "poly_blind_commit",
  6. "poly_response",
  7. "poly_blind_respond",
  8. "x_blind_factors",
  9. "evaluation_commits",
  10. "evaluation_response",
  11. "value"
  12. ])
  13. # Implementation of Groth09 inner product proof
  14. q = 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001
  15. K = GF(q)
  16. a = K(0x00)
  17. b = K(0x05)
  18. E = EllipticCurve(K, (a, b))
  19. G = E(0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000000, 0x02)
  20. p = 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001
  21. assert E.order() == p
  22. Scalar = GF(p)
  23. # Create some generator points. Normally we would use hash to curve.
  24. # All these points will be generators since the curve is a cyclic group
  25. H = E.random_element()
  26. G_vec = [E.random_element() for _ in range(1000)]
  27. def dot_product(x, y):
  28. result = None
  29. for x_i, y_i in zip(x, y):
  30. if result is None:
  31. result = int(x_i) * y_i
  32. else:
  33. result += int(x_i) * y_i
  34. return result
  35. def create_proof(a, x):
  36. x = np.array([x**i for i in range(len(a))])
  37. # Evaluate the polynomial
  38. z = a.dot(x)
  39. assert len(a) == len(x)
  40. # We will now construct a proof
  41. # Commitments
  42. t = Scalar.random_element()
  43. r = Scalar.random_element()
  44. s = Scalar.random_element()
  45. C_z = int(t) * H + int(z) * G
  46. C_x = int(r) * H + dot_product(a, G_vec)
  47. C_y = int(s) * H + dot_product(x, G_vec)
  48. d_x = np.array([Scalar.random_element() for _ in range(len(x))])
  49. d_y = np.array([Scalar.random_element() for _ in range(len(x))])
  50. r_d = Scalar.random_element()
  51. s_d = Scalar.random_element()
  52. A_d = int(r_d) * H + dot_product(d_x, G_vec)
  53. B_d = int(s_d) * H + dot_product(d_y, G_vec)
  54. # (cx + d_x)(cy + d_y) = d_x d_y + c(x d_y + y d_x) + c^2 xy
  55. t_0 = Scalar.random_element()
  56. t_1 = Scalar.random_element()
  57. C_0 = int(t_0) * H + int(d_x.dot(d_y)) * G
  58. C_1 = int(t_1) * H + int(a.dot(d_y) + x.dot(d_x)) * G
  59. # Challenge
  60. # Using the Fiat-Shamir transform, we would hash the transcript
  61. #c = Scalar.random_element()
  62. c = 110
  63. # Responses
  64. f_x = c * a + d_x
  65. f_y = c * x + d_y
  66. r_x = c * r + r_d
  67. s_y = c * s + s_d
  68. t_z = c**2 * t + c * t_1 + t_0
  69. # Verify
  70. #B_d = int(s_d) * H + dot_product(d_y, G_vec)
  71. #C_y = int(s) * H + dot_product(x, G_vec)
  72. assert int(c) * C_x + A_d == int(r_x) * H + dot_product(f_x, G_vec)
  73. assert int(c) * C_y + B_d == int(s_y) * H + dot_product(f_y, G_vec)
  74. # Actual inner product check
  75. # Comm(f_x f_y) == e^2 C_z + c Comm(x d_y + y d_x) + Comm(d_x d_y)
  76. assert int(t_z) * H + int(f_x.dot(f_y)) * G == int(c**2) * C_z + int(c) * C_1 + C_0
  77. return PolyProof(
  78. poly_commit=C_x,
  79. poly_blind_commit=A_d,
  80. poly_response=f_x,
  81. poly_blind_respond=r_x,
  82. x_blind_factors=(s_d, d_y, s),
  83. evaluation_commits=(C_0, C_1, C_z),
  84. evaluation_response=t_z,
  85. value=z
  86. )
  87. def verify_proof(proof, x):
  88. C_x = proof.poly_commit
  89. A_d = proof.poly_blind_commit
  90. f_x = proof.poly_response
  91. r_x = proof.poly_blind_respond
  92. (s_d, d_y, s) = proof.x_blind_factors
  93. (C_0, C_1, C_z) = proof.evaluation_commits
  94. t_z = proof.evaluation_response
  95. z = proof.value
  96. x = np.array([x**i for i in range(len(a))])
  97. c = 110
  98. f_y = c * x + d_y
  99. s_y = c * s + s_d
  100. B_d = int(s_d) * H + dot_product(d_y, G_vec)
  101. C_y = int(s) * H + dot_product(x, G_vec)
  102. if int(c) * C_x + A_d != int(r_x) * H + dot_product(f_x, G_vec):
  103. return False
  104. if int(c) * C_y + B_d != int(s_y) * H + dot_product(f_y, G_vec):
  105. return False
  106. # Actual inner product check
  107. # Comm(f_x f_y) == e^2 C_z + c Comm(x d_y + y d_x) + Comm(d_x d_y)
  108. if int(t_z) * H + int(f_x.dot(f_y)) * G != int(c**2) * C_z + int(c) * C_1 + C_0:
  109. return False
  110. return True
  111. a = np.array([
  112. Scalar(110), Scalar(56), Scalar(89), Scalar(6543), Scalar(2)
  113. ])
  114. xx = Scalar(77)
  115. proof = create_proof(a, xx)
  116. assert verify_proof(proof, xx)