def OpBLS_G2_Add(arg): op = json.loads(arg) a_v = to_int(op['a_v']) a_w = to_int(op['a_w']) a_x = to_int(op['a_x']) a_y = to_int(op['a_y']) b_v = to_int(op['b_v']) b_w = to_int(op['b_w']) b_x = to_int(op['b_x']) b_y = to_int(op['b_y']) A = (FQ2((a_v, a_x)), FQ2((a_w, a_y)), FQ2.one()) B = (FQ2((b_v, b_x)), FQ2((b_w, b_y)), FQ2.one()) if not (is_on_curve(A, b2) and subgroup_check(A)): return if not (is_on_curve(B, b2) and subgroup_check(B)): return result = add(A, B) x = result[0] / result[2] y = result[1] / result[2] result = [[str(x.coeffs[0]), str(y.coeffs[0])], [str(x.coeffs[1]), str(y.coeffs[1])]] r = json.dumps(result) return bytes(r, 'utf-8')
def OpBLS_G1_Add(arg): op = json.loads(arg) a_x = to_int(op['a_x']) a_y = to_int(op['a_y']) b_x = to_int(op['b_x']) b_y = to_int(op['b_y']) if (a_x % MOD, a_y % MOD) == (0, 0): return if (b_x % MOD, b_y % MOD) == (0, 0): return A = [FQ(a_x), FQ(a_y), FQ.one()] B = [FQ(b_x), FQ(b_y), FQ.one()] if not (is_on_curve(A, b) and subgroup_check(A)): return if not (is_on_curve(B, b) and subgroup_check(B)): return result = add(A, B) result = [str(result[0] / result[2]), str(result[1] / result[2])] r = json.dumps(result) return bytes(r, 'utf-8')
def decompress_G2(p: G2Compressed) -> G2Uncompressed: """ Recovers x and y coordinates from the compressed point (z1, z2). """ z1, z2 = p # b_flag == 1 indicates the infinity point b_flag1 = (z1 % POW_2_383) // POW_2_382 if b_flag1 == 1: return Z2 x1 = z1 % POW_2_381 x2 = z2 # x1 is the imaginary part, x2 is the real part x = FQ2([x2, x1]) y = modular_squareroot_in_FQ2(x**3 + b2) if y is None: raise ValueError("Failed to find a modular squareroot") # Choose the y whose leftmost bit of the imaginary part is equal to the a_flag1 # If y_im happens to be zero, then use the bit of y_re a_flag1 = (z1 % POW_2_382) // POW_2_381 y_re, y_im = y.coeffs if (y_im > 0 and (y_im * 2) // q != a_flag1) or (y_im == 0 and (y_re * 2) // q != a_flag1): y = FQ2((y * -1).coeffs) if not is_on_curve((x, y, FQ2([1, 0])), b2): raise ValueError( "The given point is not on the twisted curve over FQ**2") return (x, y, FQ2([1, 0]))
def OpBLS_Verify(arg): op = json.loads(arg) verified = False g1_x = to_int(op['g1_x']) g1_y = to_int(op['g1_y']) g1 = [FQ(g1_x), FQ(g1_y), FQ.one()] if is_on_curve(g1, b) == False: r = json.dumps(verified) return bytes(r, 'utf-8') g1 = G1_to_pubkey(g1) g2_v = to_int(op['g2_v']) g2_w = to_int(op['g2_w']) g2_x = to_int(op['g2_x']) g2_y = to_int(op['g2_y']) g2 = (FQ2((g2_v, g2_x)), FQ2((g2_w, g2_y)), FQ2.one()) try: g2 = G2_to_signature(g2) except: r = json.dumps(verified) return bytes(r, 'utf-8') msg = bytes.fromhex(op['cleartext']) verified = bls_pop.Verify(g1, msg, g2) r = json.dumps(verified) return bytes(r, 'utf-8')
def test_hash_to_G2(): message_hash = b'\x12' * 32 domain_1 = 1 domain_in_bytes = domain_1.to_bytes(8, 'big') result_1 = hash_to_G2(message_hash, domain_in_bytes) assert is_on_curve(result_1, b2)
def compress_G2(pt: G2Uncompressed) -> G2Compressed: """ The compressed point (z1, z2) has the bit order: z1: (c_flag1, b_flag1, a_flag1, x1) z2: (c_flag2, b_flag2, a_flag2, x2) where - c_flag1 is always set to 1 - b_flag1 indicates infinity when set to 1 - a_flag1 helps determine the y-coordinate when decompressing, - a_flag2, b_flag2, and c_flag2 are always set to 0 """ if not is_on_curve(pt, b2): raise ValueError( "The given point is not on the twisted curve over FQ**2") if is_inf(pt): return G2Compressed((POW_2_383 + POW_2_382, 0)) x, y = normalize(pt) x_re, x_im = x.coeffs y_re, y_im = y.coeffs # Record the leftmost bit of y_im to the a_flag1 # If y_im happens to be zero, then use the bit of y_re a_flag1 = (y_im * 2) // q if y_im > 0 else (y_re * 2) // q # Imaginary part of x goes to z1, real part goes to z2 # c_flag1 = 1, b_flag1 = 0 z1 = x_im + a_flag1 * POW_2_381 + POW_2_383 # a_flag2 = b_flag2 = c_flag2 = 0 z2 = x_re return G2Compressed((z1, z2))
def mk_generator_points(count): points = [] x = b.FQ(1) while len(points) < count: y = (x**3 + b.b)**((b.field_modulus + 1) // 4) if b.is_on_curve((x, y, b.FQ(1)), b.b): points.append(b.multiply((x, y, b.FQ(1)), BLS12_381_COFACTOR)) x += b.FQ(1) return points
def test_hash_to_G2(msg, x, y, H): point = hash_to_G2(msg, DST, H) assert is_on_curve(point, b2) # Affine result_x = point[0] / point[2] # X / Z result_y = point[1] / point[2] # Y / Z assert x == result_x assert y == result_y
def decompress_G2(p: G2Compressed) -> G2Uncompressed: """ Recovers x and y coordinates from the compressed point (z1, z2). """ z1, z2 = p c_flag1, b_flag1, a_flag1 = get_flags(z1) # c_flag == 1 indicates the compressed form # MSB should be 1 if not c_flag1: raise ValueError("c_flag should be 1") is_inf_pt = is_point_at_infinity(z1, z2) if b_flag1 != is_inf_pt: raise ValueError("b_flag should be %d" % int(is_inf_pt)) if is_inf_pt: # 3 MSBs should be 110 if a_flag1: raise ValueError("a point at infinity should have a_flag == 0") return Z2 # Else, not point at infinity # 3 MSBs should be 100 or 101 x1 = z1 % POW_2_381 # Ensure that x1 is less than the field modulus. if x1 >= q: raise ValueError("x1 value should be less than field modulus. Got %d", x1) # Ensure that z2 is less than the field modulus. if z2 >= q: raise ValueError( "z2 point value should be less than field modulus. Got %d", z2) x2 = z2 # x1 is the imaginary part, x2 is the real part x = FQ2([x2, x1]) y = modular_squareroot_in_FQ2(x**3 + b2) if y is None: raise ValueError("Failed to find a modular squareroot") # Choose the y whose leftmost bit of the imaginary part is equal to the a_flag1 # If y_im happens to be zero, then use the bit of y_re y_re, y_im = y.coeffs if ((y_im > 0 and (y_im * 2) // q != int(a_flag1)) or (y_im == 0 and (y_re * 2) // q != int(a_flag1))): y = FQ2((y * -1).coeffs) if not is_on_curve((x, y, FQ2([1, 0])), b2): raise ValueError( "The given point is not on the twisted curve over FQ**2") return (x, y, FQ2([1, 0]))
def OpBLS_IsG1OnCurve(arg): op = json.loads(arg) x = to_int(op['g1_x']) y = to_int(op['g1_y']) g1 = [FQ(x), FQ(y), FQ.one()] if is_valid([x, y]) == False: return #r = json.dumps(is_on_curve(g2, b2)) r = json.dumps(is_on_curve(g1, b) and subgroup_check(g1)) return bytes(r, 'utf-8')
def OpBLS_IsG2OnCurve(arg): op = json.loads(arg) v = to_int(op['g2_v']) w = to_int(op['g2_w']) x = to_int(op['g2_x']) y = to_int(op['g2_y']) g2 = (FQ2((v, x)), FQ2((w, y)), FQ2.one()) if is_valid([v, w, x, y]) == False: return r = json.dumps(is_on_curve(g2, b2) and subgroup_check(g2)) return bytes(r, 'utf-8')
def decompress_G2(p: Tuple[int, int]) -> Tuple[FQP, FQP, FQP]: x1 = p[0] % 2**383 y1_mod_2 = p[0] // 2**383 x2 = p[1] x = FQ2([x1, x2]) if x == FQ2([0, 0]): return FQ2([1, 0]), FQ2([1, 0]), FQ2([0, 0]) y = modular_squareroot(x**3 + b2) if y.coeffs[0] % 2 != y1_mod_2: y = FQ2((y * -1).coeffs) if not is_on_curve((x, y, FQ2([1, 0])), b2): raise ValueError( "The given point is not on the twisted curve over FQ**2") return x, y, FQ2([1, 0])
def OpBLS_Compress_G1(arg): op = json.loads(arg) x = to_int(op['g1_x']) y = to_int(op['g1_y']) if (x % MOD, y % MOD) == (0, 0): return g1 = [FQ(x), FQ(y), FQ.one()] compressed = compress_G1(g1) if is_valid([x, y]) == True and is_on_curve(g1, b): decompressed = decompress_G1(compressed) assert g1[0] == decompressed[0] and g1[1] == decompressed[1] r = json.dumps(str(compressed)) return bytes(r, 'utf-8')
def test_G1_compress_and_decompress_flags(pt, on_curve, is_infinity): assert on_curve == is_on_curve(pt, b) z = compress_G1(pt) if on_curve: x = z % POW_2_381 c_flag = (z % 2**384) // POW_2_383 b_flag = (z % POW_2_383) // POW_2_382 a_flag = (z % POW_2_382) // POW_2_381 assert x < q assert c_flag == 1 if is_infinity: assert b_flag == 1 assert a_flag == x == 0 else: assert b_flag == 0 pt_x, pt_y = normalize(pt) assert a_flag == (pt_y.n * 2) // q assert x == pt_x.n # Correct flags should decompress correct x, y normalize(decompress_G1(z)) == normalize(pt) else: with pytest.raises(ValueError): decompress_G1(z)
def is_on_curve(xxx: G1Point) -> bool: return bls12_381.is_on_curve(xxx, bls12_381.b)
def compress_G2(pt: Tuple[FQP, FQP, FQP]) -> Tuple[int, int]: if not is_on_curve(pt, b2): raise ValueError( "The given point is not on the twisted curve over FQ**2") x, y = normalize(pt) return (int(x.coeffs[0] + 2**383 * (y.coeffs[0] % 2)), int(x.coeffs[1]))
def test_hash_to_G2(): message = b'helloworld' domain_1 = 1 result_1 = hash_to_G2(message, domain_1) assert is_on_curve(result_1, b2)
def test_hash_to_G2(): message_hash = b'\x12' * 32 domain_1 = 1 result_1 = hash_to_G2(message_hash, domain_1) assert is_on_curve(result_1, b2)