/ src / secp256k1 / sage / prove_group_implementations.sage
prove_group_implementations.sage
  1  # Test libsecp256k1' group operation implementations using prover.sage
  2  
  3  import sys
  4  
  5  load("group_prover.sage")
  6  load("weierstrass_prover.sage")
  7  
  8  def formula_secp256k1_gej_double_var(a):
  9    """libsecp256k1's secp256k1_gej_double_var, used by various addition functions"""
 10    rz = a.Z * a.Y
 11    s = a.Y^2
 12    l = a.X^2
 13    l = l * 3
 14    l = l / 2
 15    t = -s
 16    t = t * a.X
 17    rx = l^2
 18    rx = rx + t
 19    rx = rx + t
 20    s = s^2
 21    t = t + rx
 22    ry = t * l
 23    ry = ry + s
 24    ry = -ry
 25    return jacobianpoint(rx, ry, rz)
 26  
 27  def formula_secp256k1_gej_add_var(branch, a, b):
 28    """libsecp256k1's secp256k1_gej_add_var"""
 29    if branch == 0:
 30      return (constraints(), constraints(nonzero={a.Infinity : 'a_infinite'}), b)
 31    if branch == 1:
 32      return (constraints(), constraints(zero={a.Infinity : 'a_finite'}, nonzero={b.Infinity : 'b_infinite'}), a)
 33    z22 = b.Z^2
 34    z12 = a.Z^2
 35    u1 = a.X * z22
 36    u2 = b.X * z12
 37    s1 = a.Y * z22
 38    s1 = s1 * b.Z
 39    s2 = b.Y * z12
 40    s2 = s2 * a.Z
 41    h = -u1
 42    h = h + u2
 43    i = -s2
 44    i = i + s1
 45    if branch == 2:
 46      r = formula_secp256k1_gej_double_var(a)
 47      return (constraints(), constraints(zero={h : 'h=0', i : 'i=0', a.Infinity : 'a_finite', b.Infinity : 'b_finite'}), r)
 48    if branch == 3:
 49      return (constraints(), constraints(zero={h : 'h=0', a.Infinity : 'a_finite', b.Infinity : 'b_finite'}, nonzero={i : 'i!=0'}), point_at_infinity())
 50    t = h * b.Z
 51    rz = a.Z * t
 52    h2 = h^2
 53    h2 = -h2
 54    h3 = h2 * h
 55    t = u1 * h2
 56    rx = i^2
 57    rx = rx + h3
 58    rx = rx + t
 59    rx = rx + t
 60    t = t + rx
 61    ry = t * i
 62    h3 = h3 * s1
 63    ry = ry + h3
 64    return (constraints(), constraints(zero={a.Infinity : 'a_finite', b.Infinity : 'b_finite'}, nonzero={h : 'h!=0'}), jacobianpoint(rx, ry, rz))
 65  
 66  def formula_secp256k1_gej_add_ge_var(branch, a, b):
 67    """libsecp256k1's secp256k1_gej_add_ge_var, which assume bz==1"""
 68    if branch == 0:
 69      return (constraints(zero={b.Z - 1 : 'b.z=1'}), constraints(nonzero={a.Infinity : 'a_infinite'}), b)
 70    if branch == 1:
 71      return (constraints(zero={b.Z - 1 : 'b.z=1'}), constraints(zero={a.Infinity : 'a_finite'}, nonzero={b.Infinity : 'b_infinite'}), a)
 72    z12 = a.Z^2
 73    u1 = a.X
 74    u2 = b.X * z12
 75    s1 = a.Y
 76    s2 = b.Y * z12
 77    s2 = s2 * a.Z
 78    h = -u1
 79    h = h + u2
 80    i = -s2
 81    i = i + s1
 82    if (branch == 2):
 83      r = formula_secp256k1_gej_double_var(a)
 84      return (constraints(zero={b.Z - 1 : 'b.z=1'}), constraints(zero={a.Infinity : 'a_finite', b.Infinity : 'b_finite', h : 'h=0', i : 'i=0'}), r)
 85    if (branch == 3):
 86      return (constraints(zero={b.Z - 1 : 'b.z=1'}), constraints(zero={a.Infinity : 'a_finite', b.Infinity : 'b_finite', h : 'h=0'}, nonzero={i : 'i!=0'}), point_at_infinity())
 87    rz = a.Z * h
 88    h2 = h^2
 89    h2 = -h2
 90    h3 = h2 * h
 91    t = u1 * h2
 92    rx = i^2
 93    rx = rx + h3
 94    rx = rx + t
 95    rx = rx + t
 96    t = t + rx
 97    ry = t * i
 98    h3 = h3 * s1
 99    ry = ry + h3
100    return (constraints(zero={b.Z - 1 : 'b.z=1'}), constraints(zero={a.Infinity : 'a_finite', b.Infinity : 'b_finite'}, nonzero={h : 'h!=0'}), jacobianpoint(rx, ry, rz))
101  
102  def formula_secp256k1_gej_add_zinv_var(branch, a, b):
103    """libsecp256k1's secp256k1_gej_add_zinv_var"""
104    bzinv = b.Z^(-1)
105    if branch == 0:
106      rinf = b.Infinity
107      bzinv2 = bzinv^2
108      bzinv3 = bzinv2 * bzinv
109      rx = b.X * bzinv2
110      ry = b.Y * bzinv3
111      rz = 1
112      return (constraints(), constraints(nonzero={a.Infinity : 'a_infinite'}), jacobianpoint(rx, ry, rz, rinf))
113    if branch == 1:
114      return (constraints(), constraints(zero={a.Infinity : 'a_finite'}, nonzero={b.Infinity : 'b_infinite'}), a)
115    azz = a.Z * bzinv
116    z12 = azz^2
117    u1 = a.X
118    u2 = b.X * z12
119    s1 = a.Y
120    s2 = b.Y * z12
121    s2 = s2 * azz
122    h = -u1
123    h = h + u2
124    i = -s2
125    i = i + s1
126    if branch == 2:
127      r = formula_secp256k1_gej_double_var(a)
128      return (constraints(), constraints(zero={a.Infinity : 'a_finite', b.Infinity : 'b_finite', h : 'h=0', i : 'i=0'}), r)
129    if branch == 3:
130      return (constraints(), constraints(zero={a.Infinity : 'a_finite', b.Infinity : 'b_finite', h : 'h=0'}, nonzero={i : 'i!=0'}), point_at_infinity())
131    rz = a.Z * h
132    h2 = h^2
133    h2 = -h2
134    h3 = h2 * h
135    t = u1 * h2
136    rx = i^2
137    rx = rx + h3
138    rx = rx + t
139    rx = rx + t
140    t = t + rx
141    ry = t * i
142    h3 = h3 * s1
143    ry = ry + h3
144    return (constraints(), constraints(zero={a.Infinity : 'a_finite', b.Infinity : 'b_finite'}, nonzero={h : 'h!=0'}), jacobianpoint(rx, ry, rz))
145  
146  def formula_secp256k1_gej_add_ge(branch, a, b):
147    """libsecp256k1's secp256k1_gej_add_ge"""
148    zeroes = {}
149    nonzeroes = {}
150    a_infinity = False
151    if (branch & 2) != 0:
152      nonzeroes.update({a.Infinity : 'a_infinite'})
153      a_infinity = True
154    else:
155      zeroes.update({a.Infinity : 'a_finite'})
156    zz = a.Z^2
157    u1 = a.X
158    u2 = b.X * zz
159    s1 = a.Y
160    s2 = b.Y * zz
161    s2 = s2 * a.Z
162    t = u1
163    t = t + u2
164    m = s1
165    m = m + s2
166    rr = t^2
167    m_alt = -u2
168    tt = u1 * m_alt
169    rr = rr + tt
170    degenerate = (branch & 1) != 0
171    if degenerate:
172      zeroes.update({m : 'm_zero'})
173    else:
174      nonzeroes.update({m : 'm_nonzero'})
175    rr_alt = s1
176    rr_alt = rr_alt * 2
177    m_alt = m_alt + u1
178    if not degenerate:
179      rr_alt = rr
180      m_alt = m
181    n = m_alt^2
182    q = -t
183    q = q * n
184    n = n^2
185    if degenerate:
186      n = m
187    t = rr_alt^2
188    rz = a.Z * m_alt
189    t = t + q
190    rx = t
191    t = t * 2
192    t = t + q
193    t = t * rr_alt
194    t = t + n
195    ry = -t
196    ry = ry / 2
197    if a_infinity:
198      rx = b.X
199      ry = b.Y
200      rz = 1
201    if (branch & 4) != 0:
202      zeroes.update({rz : 'r.z = 0'})
203      return (constraints(zero={b.Z - 1 : 'b.z=1', b.Infinity : 'b_finite'}), constraints(zero=zeroes, nonzero=nonzeroes), point_at_infinity())
204    else:
205      nonzeroes.update({rz : 'r.z != 0'})
206    return (constraints(zero={b.Z - 1 : 'b.z=1', b.Infinity : 'b_finite'}), constraints(zero=zeroes, nonzero=nonzeroes), jacobianpoint(rx, ry, rz))
207  
208  def formula_secp256k1_gej_add_ge_old(branch, a, b):
209    """libsecp256k1's old secp256k1_gej_add_ge, which fails when ay+by=0 but ax!=bx"""
210    a_infinity = (branch & 1) != 0
211    zero = {}
212    nonzero = {}
213    if a_infinity:
214      nonzero.update({a.Infinity : 'a_infinite'})
215    else:
216      zero.update({a.Infinity : 'a_finite'})
217    zz = a.Z^2
218    u1 = a.X
219    u2 = b.X * zz
220    s1 = a.Y
221    s2 = b.Y * zz
222    s2 = s2 * a.Z
223    z = a.Z
224    t = u1
225    t = t + u2
226    m = s1
227    m = m + s2
228    n = m^2
229    q = n * t
230    n = n^2
231    rr = t^2
232    t = u1 * u2
233    t = -t
234    rr = rr + t
235    t = rr^2
236    rz = m * z
237    infinity = False
238    if (branch & 2) != 0:
239      if not a_infinity:
240        infinity = True
241      else:
242        return (constraints(zero={b.Z - 1 : 'b.z=1', b.Infinity : 'b_finite'}), constraints(nonzero={z : 'conflict_a'}, zero={z : 'conflict_b'}), point_at_infinity())
243      zero.update({rz : 'r.z=0'})
244    else:
245      nonzero.update({rz : 'r.z!=0'})
246    rz = rz * (0 if a_infinity else 2)
247    rx = t
248    q = -q
249    rx = rx + q
250    q = q * 3
251    t = t * 2
252    t = t + q
253    t = t * rr
254    t = t + n
255    ry = -t
256    rx = rx * (0 if a_infinity else 4)
257    ry = ry * (0 if a_infinity else 4)
258    t = b.X
259    t = t * (1 if a_infinity else 0)
260    rx = rx + t
261    t = b.Y
262    t = t * (1 if a_infinity else 0)
263    ry = ry + t
264    t = (1 if a_infinity else 0)
265    rz = rz + t
266    if infinity:
267      return (constraints(zero={b.Z - 1 : 'b.z=1', b.Infinity : 'b_finite'}), constraints(zero=zero, nonzero=nonzero), point_at_infinity())
268    return (constraints(zero={b.Z - 1 : 'b.z=1', b.Infinity : 'b_finite'}), constraints(zero=zero, nonzero=nonzero), jacobianpoint(rx, ry, rz))
269  
270  if __name__ == "__main__":
271    success = True
272    success = success & check_symbolic_jacobian_weierstrass("secp256k1_gej_add_var", 0, 7, 5, formula_secp256k1_gej_add_var)
273    success = success & check_symbolic_jacobian_weierstrass("secp256k1_gej_add_ge_var", 0, 7, 5, formula_secp256k1_gej_add_ge_var)
274    success = success & check_symbolic_jacobian_weierstrass("secp256k1_gej_add_zinv_var", 0, 7, 5, formula_secp256k1_gej_add_zinv_var)
275    success = success & check_symbolic_jacobian_weierstrass("secp256k1_gej_add_ge", 0, 7, 8, formula_secp256k1_gej_add_ge)
276    success = success & (not check_symbolic_jacobian_weierstrass("secp256k1_gej_add_ge_old [should fail]", 0, 7, 4, formula_secp256k1_gej_add_ge_old))
277  
278    if len(sys.argv) >= 2 and sys.argv[1] == "--exhaustive":
279      success = success & check_exhaustive_jacobian_weierstrass("secp256k1_gej_add_var", 0, 7, 5, formula_secp256k1_gej_add_var, 43)
280      success = success & check_exhaustive_jacobian_weierstrass("secp256k1_gej_add_ge_var", 0, 7, 5, formula_secp256k1_gej_add_ge_var, 43)
281      success = success & check_exhaustive_jacobian_weierstrass("secp256k1_gej_add_zinv_var", 0, 7, 5, formula_secp256k1_gej_add_zinv_var, 43)
282      success = success & check_exhaustive_jacobian_weierstrass("secp256k1_gej_add_ge", 0, 7, 8, formula_secp256k1_gej_add_ge, 43)
283      success = success & (not check_exhaustive_jacobian_weierstrass("secp256k1_gej_add_ge_old [should fail]", 0, 7, 4, formula_secp256k1_gej_add_ge_old, 43))
284  
285    sys.exit(int(not success))