def optimized_swu_G2(t: FQ2) -> Tuple[FQ2, FQ2, FQ2]: t2 = t ** 2 iso_3_z_t2 = ISO_3_Z * t2 temp = iso_3_z_t2 + iso_3_z_t2 ** 2 denominator = -(ISO_3_A * temp) # -a(Z * t^2 + Z^2 * t^4) temp = temp + FQ2.one() numerator = ISO_3_B * temp # b(Z * t^2 + Z^2 * t^4 + 1) # Exceptional case if denominator == FQ2.zero(): denominator = ISO_3_Z * ISO_3_A # v = D^3 v = denominator ** 3 # u = N^3 + a * N * D^2 + b* D^3 u = (numerator ** 3) + (ISO_3_A * numerator * (denominator ** 2)) + (ISO_3_B * v) # Attempt y = sqrt(u / v) (success, sqrt_candidate) = sqrt_division_FQ2(u, v) y = sqrt_candidate # Handle case where (u / v) is not square # sqrt_candidate(x1) = sqrt_candidate(x0) * t^3 sqrt_candidate = sqrt_candidate * t ** 3 # u(x1) = Z^3 * t^6 * u(x0) u = (iso_3_z_t2) ** 3 * u success_2 = False etas = ETAS for eta in etas: # Valid solution if (eta * sqrt_candidate(x1)) ** 2 * v - u == 0 eta_sqrt_candidate = eta * sqrt_candidate temp1 = eta_sqrt_candidate ** 2 * v - u if temp1 == FQ2.zero() and not success and not success_2: y = eta_sqrt_candidate success_2 = True if not success and not success_2: # Unreachable raise Exception("Hash to Curve - Optimized SWU failure") if not success: numerator = numerator * iso_3_z_t2 if t.sgn0 != y.sgn0: y = -y y = y * denominator return (numerator, y, denominator)
def iso_map_G2(x: FQ2, y: FQ2, z: FQ2) -> Optimized_Point3D[FQ2]: # x-numerator, x-denominator, y-numerator, y-denominator mapped_values = [FQ2.zero(), FQ2.zero(), FQ2.zero(), FQ2.zero()] z_powers = [z, z ** 2, z ** 3] # Horner Polynomial Evaluation for (i, k_i) in enumerate(ISO_3_MAP_COEFFICIENTS): mapped_values[i] = k_i[-1:][0] for (j, k_i_j) in enumerate(reversed(k_i[:-1])): mapped_values[i] = mapped_values[i] * x + z_powers[j] * k_i_j mapped_values[2] = mapped_values[2] * y # y-numerator * y mapped_values[3] = mapped_values[3] * z # y-denominator * z z_G2 = mapped_values[1] * mapped_values[3] # x-denominator * y-denominator x_G2 = mapped_values[0] * mapped_values[3] # x-numerator * y-denominator y_G2 = mapped_values[1] * mapped_values[2] # y-numerator * x-denominator return (x_G2, y_G2, z_G2)
def sqrt_division_FQ2(u: FQ2, v: FQ2) -> Tuple[bool, FQ2]: temp1 = u * v ** 7 temp2 = temp1 * v ** 8 # gamma = uv^7 * (uv^15)^((p^2 - 9) / 16) gamma = temp2 ** P_MINUS_9_DIV_16 gamma = gamma * temp1 # Verify there is a valid root is_valid_root = False result = gamma roots = POSITIVE_EIGTH_ROOTS_OF_UNITY for root in roots: # Valid if (root * gamma)^2 * v - u == 0 sqrt_candidate = (root * gamma) temp2 = sqrt_candidate ** 2 * v - u if temp2 == FQ2.zero() and not is_valid_root: is_valid_root = True result = sqrt_candidate return (is_valid_root, result)
# Generator for twisted curve over FQ2 G2 = ( FQ2(( 352701069587466618187139116011060144890029952792775240219908644239793785735715026873347600343865175952761926303160, # noqa: E501 3059144344244213709971259814753781636986470325476647558659373206291635324768958432433509563104347017837885763365758, # noqa: E501 )), FQ2(( 1985150602287291935568054521177171638300868978215655730859378665066344726373823718423869104263333984641494340347905, # noqa: E501 927553665492332455747201965776037880757740193453592970025027978793976877002675564980949289727957565575433344219582, # noqa: E501 )), FQ2.one(), ) # Point at infinity over FQ Z1 = (FQ.one(), FQ.one(), FQ.zero()) # Point at infinity for twisted curve over FQ2 Z2 = (FQ2.one(), FQ2.one(), FQ2.zero()) # Check if a point is the point at infinity def is_inf(pt: Optimized_Point3D[Optimized_Field]) -> bool: return pt[-1] == pt[-1].__class__.zero() # Check that a point is on the curve defined by y**2 == x**3 + b def is_on_curve(pt: Optimized_Point3D[Optimized_Field], b: Optimized_Field) -> bool: if is_inf(pt): return True x, y, z = pt return y**2 * z - x**3 == b * z**3
3557697382419259905260257622876359250272784728834673675850718343221361467102966990615722337003569479144794908942033, 0 ]) # noqa: E501 ISO_3_X_NUMERATOR = (ISO_3_K_1_0, ISO_3_K_1_1, ISO_3_K_1_2, ISO_3_K_1_3) # X Denominator ISO_3_K_2_0 = FQ2([ 0, 4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559715 ]) # noqa: E501 ISO_3_K_2_1 = FQ2([ 12, 4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559775 ]) # noqa: E501 ISO_3_K_2_2 = FQ2.one() ISO_3_K_2_3 = FQ2.zero() ISO_3_X_DENOMINATOR = (ISO_3_K_2_0, ISO_3_K_2_1, ISO_3_K_2_2, ISO_3_K_2_3) # Y Numerator ISO_3_K_3_0_VAL = 3261222600550988246488569487636662646083386001431784202863158481286248011511053074731078808919938689216061999863558 # noqa: E501 ISO_3_K_3_0 = FQ2([ISO_3_K_3_0_VAL, ISO_3_K_3_0_VAL]) # noqa: E501 ISO_3_K_3_1 = FQ2([ 0, 889424345604814976315064405719089812568196182208668418962679585805340366775741747653930584250892369786198727235518 ]) # noqa: E501 ISO_3_K_3_2 = FQ2([ 2668273036814444928945193217157269437704588546626005256888038757416021100327225242961791752752677109358596181706524, 1334136518407222464472596608578634718852294273313002628444019378708010550163612621480895876376338554679298090853263 ]) # noqa: E501 ISO_3_K_3_3 = FQ2([ 2816510427748580758331037284777117739799287910327449993381818688383577828123182200904113516794492504322962636245776,