def miller_loop(Q, P): if Q is None or P is None: return FQ12.one() R = Q f_num, f_den = FQ12.one(), FQ12.one() for b in pseudo_binary_encoding[63::-1]: #for i in range(log_ate_loop_count, -1, -1): _n, _d = linefunc(R, R, P) f_num = f_num * f_num * _n f_den = f_den * f_den * _d R = double(R) #if ate_loop_count & (2**i): if b == 1: _n, _d = linefunc(R, Q, P) f_num = f_num * _n f_den = f_den * _d R = add(R, Q) elif b == -1: nQ = neg(Q) _n, _d = linefunc(R, nQ, P) f_num = f_num * _n f_den = f_den * _d R = add(R, nQ) # assert R == multiply(Q, ate_loop_count) Q1 = (Q[0]**field_modulus, Q[1]**field_modulus, Q[2]**field_modulus) # assert is_on_curve(Q1, b12) nQ2 = (Q1[0]**field_modulus, -Q1[1]**field_modulus, Q1[2]**field_modulus) # assert is_on_curve(nQ2, b12) _n1, _d1 = linefunc(R, Q1, P) R = add(R, Q1) _n2, _d2 = linefunc(R, nQ2, P) f = f_num * _n1 * _n2 / (f_den * _d1 * _d2) # R = add(R, nQ2) This line is in many specifications but it technically does nothing return f**((field_modulus**12 - 1) // curve_order)
def pairing(Q, P, final_exponentiate=True): assert is_on_curve(Q, b2) assert is_on_curve(P, b) if P[-1] == P[-1].__class__.zero() or Q[-1] == Q[-1].__class__.zero(): return FQ12.one() return miller_loop(twist(Q), cast_point_to_fq12(P), final_exponentiate=final_exponentiate)
def miller_loop(Q, P): if Q is None or P is None: return FQ12.one() R = Q f = FQ12.one() for i in range(log_ate_loop_count, -1, -1): f = f * f * linefunc(R, R, P) R = double(R) if ate_loop_count & (2**i): f = f * linefunc(R, Q, P) R = add(R, Q) # assert R == multiply(Q, ate_loop_count) Q1 = (Q[0]**field_modulus, Q[1]**field_modulus) # assert is_on_curve(Q1, b12) nQ2 = (Q1[0]**field_modulus, -Q1[1]**field_modulus) # assert is_on_curve(nQ2, b12) f = f * linefunc(R, Q1, P) R = add(R, Q1) f = f * linefunc(R, nQ2, P) # R = add(R, nQ2) This line is in many specifications but it technically does nothing return f**((field_modulus**12 - 1) // curve_order)