Skip to content

Commit ac71020

Browse files
real-or-randomsipa
andcommitted
group: Save a normalize_to_zero in gej_add_ge
The code currently switches to the alternative formula for lambda only if (R,M) = (0,0) but the alternative formula works whenever M = 0: Specifically, M = 0 implies y1 = -y2. If x1 = x2, then a = -b this is the r = infinity case that we handle separately. If x1 != x2, then the denominator in the alternative formula is non-zero, so this formula is well-defined. One needs to carefully check that the infinity assignment is still correct because now the definition of m_alt at this point in the code has changed. But this is true: Case y1 = -y2: Then degenerate = true and infinity = ((x1 - x2)Z == 0) & ~a->infinity . a->infinity is handled separately. And if ~a->infinity, then Z = Z1 != 0, so infinity = (x1 - x2 == 0) = (a == -b) by case condition. Case y1 != -y2: Then degenerate = false and infinity = ((y1 + y2)Z == 0) & ~a->infinity . a->infinity is handled separately. And if ~a->infinity, then Z = Z1 != 0, so infinity = (y1 + y2 == 0) = false by case condition. Co-Authored-By: Pieter Wuille <[email protected]>
1 parent 1253a27 commit ac71020

File tree

2 files changed

+12
-18
lines changed

2 files changed

+12
-18
lines changed

sage/prove_group_implementations.sage

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ def formula_secp256k1_gej_add_ge(branch, a, b):
157157
zeroes = {}
158158
nonzeroes = {}
159159
a_infinity = False
160-
if (branch & 4) != 0:
160+
if (branch & 2) != 0:
161161
nonzeroes.update({a.Infinity : 'a_infinite'})
162162
a_infinity = True
163163
else:
@@ -176,15 +176,11 @@ def formula_secp256k1_gej_add_ge(branch, a, b):
176176
m_alt = -u2
177177
tt = u1 * m_alt
178178
rr = rr + tt
179-
degenerate = (branch & 3) == 3
180-
if (branch & 1) != 0:
179+
degenerate = (branch & 1) != 0
180+
if degenerate:
181181
zeroes.update({m : 'm_zero'})
182182
else:
183183
nonzeroes.update({m : 'm_nonzero'})
184-
if (branch & 2) != 0:
185-
zeroes.update({rr : 'rr_zero'})
186-
else:
187-
nonzeroes.update({rr : 'rr_nonzero'})
188184
rr_alt = s1
189185
rr_alt = rr_alt * 2
190186
m_alt = m_alt + u1
@@ -200,12 +196,11 @@ def formula_secp256k1_gej_add_ge(branch, a, b):
200196
t = rr_alt^2
201197
rz = a.Z * m_alt
202198
infinity = False
203-
if (branch & 8) != 0:
204-
if not a_infinity:
205-
infinity = True
206-
zeroes.update({rz : 'r.z=0'})
199+
if (branch & 4) != 0:
200+
infinity = True
201+
zeroes.update({rz : 'r.z = 0'})
207202
else:
208-
nonzeroes.update({rz : 'r.z!=0'})
203+
nonzeroes.update({rz : 'r.z != 0'})
209204
t = t + q
210205
rx = t
211206
t = t * 2
@@ -289,14 +284,14 @@ if __name__ == "__main__":
289284
success = success & check_symbolic_jacobian_weierstrass("secp256k1_gej_add_var", 0, 7, 5, formula_secp256k1_gej_add_var)
290285
success = success & check_symbolic_jacobian_weierstrass("secp256k1_gej_add_ge_var", 0, 7, 5, formula_secp256k1_gej_add_ge_var)
291286
success = success & check_symbolic_jacobian_weierstrass("secp256k1_gej_add_zinv_var", 0, 7, 5, formula_secp256k1_gej_add_zinv_var)
292-
success = success & check_symbolic_jacobian_weierstrass("secp256k1_gej_add_ge", 0, 7, 16, formula_secp256k1_gej_add_ge)
287+
success = success & check_symbolic_jacobian_weierstrass("secp256k1_gej_add_ge", 0, 7, 8, formula_secp256k1_gej_add_ge)
293288
success = success & (not check_symbolic_jacobian_weierstrass("secp256k1_gej_add_ge_old [should fail]", 0, 7, 4, formula_secp256k1_gej_add_ge_old))
294289

295290
if len(sys.argv) >= 2 and sys.argv[1] == "--exhaustive":
296291
success = success & check_exhaustive_jacobian_weierstrass("secp256k1_gej_add_var", 0, 7, 5, formula_secp256k1_gej_add_var, 43)
297292
success = success & check_exhaustive_jacobian_weierstrass("secp256k1_gej_add_ge_var", 0, 7, 5, formula_secp256k1_gej_add_ge_var, 43)
298293
success = success & check_exhaustive_jacobian_weierstrass("secp256k1_gej_add_zinv_var", 0, 7, 5, formula_secp256k1_gej_add_zinv_var, 43)
299-
success = success & check_exhaustive_jacobian_weierstrass("secp256k1_gej_add_ge", 0, 7, 16, formula_secp256k1_gej_add_ge, 43)
294+
success = success & check_exhaustive_jacobian_weierstrass("secp256k1_gej_add_ge", 0, 7, 8, formula_secp256k1_gej_add_ge, 43)
300295
success = success & (not check_exhaustive_jacobian_weierstrass("secp256k1_gej_add_ge_old [should fail]", 0, 7, 4, formula_secp256k1_gej_add_ge_old, 43))
301296

302297
sys.exit(int(not success))

src/group_impl.h

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -558,10 +558,9 @@ static void secp256k1_gej_add_ge(secp256k1_gej *r, const secp256k1_gej *a, const
558558
secp256k1_fe_negate(&m_alt, &u2, 1); /* Malt = -X2*Z1^2 */
559559
secp256k1_fe_mul(&tt, &u1, &m_alt); /* tt = -U1*U2 (2) */
560560
secp256k1_fe_add(&rr, &tt); /* rr = R = T^2-U1*U2 (3) */
561-
/** If lambda = R/M = 0/0 we have a problem (except in the "trivial"
561+
/** If lambda = R/M = R/0 we have a problem (except in the "trivial"
562562
* case that Z = z1z2 = 0, and this is special-cased later on). */
563-
degenerate = secp256k1_fe_normalizes_to_zero(&m) &
564-
secp256k1_fe_normalizes_to_zero(&rr);
563+
degenerate = secp256k1_fe_normalizes_to_zero(&m);
565564
/* This only occurs when y1 == -y2 and x1^3 == x2^3, but x1 != x2.
566565
* This means either x1 == beta*x2 or beta*x1 == x2, where beta is
567566
* a nontrivial cube root of one. In either case, an alternate
@@ -573,7 +572,7 @@ static void secp256k1_gej_add_ge(secp256k1_gej *r, const secp256k1_gej *a, const
573572

574573
secp256k1_fe_cmov(&rr_alt, &rr, !degenerate);
575574
secp256k1_fe_cmov(&m_alt, &m, !degenerate);
576-
/* Now Ralt / Malt = lambda and is guaranteed not to be 0/0.
575+
/* Now Ralt / Malt = lambda and is guaranteed not to be Ralt / 0.
577576
* From here on out Ralt and Malt represent the numerator
578577
* and denominator of lambda; R and M represent the explicit
579578
* expressions x1^2 + x2^2 + x1x2 and y1 + y2. */

0 commit comments

Comments
 (0)