# Arguments: # - F, a field object, e.g., F = GF(2^521 - 1) # - A and B, the coefficients of the curve y^2 = x^3 + A * x + B def find_z_svdw(F, A, B, init_ctr=1): g = lambda x: F(x)^3 + F(A) * F(x) + F(B) h = lambda Z: -(F(3) * Z^2 + F(4) * A) / (F(4) * g(Z)) # NOTE: if init_ctr=1 fails to find Z, try setting it to F.gen() ctr = init_ctr while True: for Z_cand in (F(ctr), F(-ctr)): # Criterion 1: # g(Z) != 0 in F. if g(Z_cand) == F(0): continue # Criterion 2: # -(3 * Z^2 + 4 * A) / (4 * g(Z)) != 0 in F. if h(Z_cand) == F(0): continue # Criterion 3: # -(3 * Z^2 + 4 * A) / (4 * g(Z)) is square in F. if not is_square(h(Z_cand)): continue # Criterion 4: # At least one of g(Z) and g(-Z / 2) is square in F. if is_square(g(Z_cand)) or is_square(g(-Z_cand / F(2))): return Z_cand ctr += 1