def check_pairing(participantG1, participantG2, previousParticipantG1): # G1 point for participant participant_g1_x = FQ(int(participantG1['x'])) participant_g1_y = FQ(int(participantG1['y'])) participant_g1 = (participant_g1_x, participant_g1_y) # G2 point for participant participant_g2_x = FQ2( [int(participantG2['x']['c0']), int(participantG2['x']['c1'])]) participant_g2_y = FQ2( [int(participantG2['y']['c0']), int(participantG2['y']['c1'])]) participant_g2 = (participant_g2_x, participant_g2_y) # G1 point for previous participant previous_participant_g1_x = FQ(int(previousParticipantG1['x'])) previous_participant_g1_y = FQ(int(previousParticipantG1['y'])) previous_participant_g1 = (previous_participant_g1_x, previous_participant_g1_y) e1 = bn128.final_exponentiate(bn128.pairing(G2, participant_g1)) e2 = bn128.final_exponentiate( bn128.pairing(participant_g2, previous_participant_g1)) pairing_result = (e1 == e2) assert (pairing_result == True)
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 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 point_from_eth(p): """ Convert a tuple point in G1 to a point in G1 compatible with py-ecc. Args: p (Tuple(int,int,int,int)): A tuple representing the point in G1 Returns: A point in G1 which is compatible with py-ecc """ x, y = p return (FQ(x), FQ(y), FQ(1))
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_G1_Neg(arg): op = json.loads(arg) a_x = to_int(op['a_x']) a_y = to_int(op['a_y']) if (a_x % MOD, a_y % MOD) == (0, 0): return A = [FQ(a_x), FQ(a_y), FQ.one()] result = neg(A) result = [str(result[0] / result[2]), str(result[1] / result[2])] r = json.dumps(result) return bytes(r, 'utf-8')
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 OpBLS_G1_IsEq(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()] r = json.dumps(A == B) return bytes(r, 'utf-8')
def test_FQ_sgn0(degree, value, expected): if degree == 1: x = FQ(value) elif degree == 2: x = FQ2([value, 0]) elif degree == 12: x = FQ12([value] + [0] * 11) assert x.sgn0 == expected if value != 0: assert x.sgn0 != (-x).sgn0
def decompress_G1(z: G1Compressed) -> G1Uncompressed: """ Recovers x and y coordinates from the compressed point. """ # b_flag == 1 indicates the infinity point b_flag = (z % POW_2_383) // POW_2_382 if b_flag == 1: return Z1 x = z % POW_2_381 # Try solving y coordinate from the equation Y^2 = X^3 + b # using quadratic residue y = pow((x**3 + b.n) % q, (q + 1) // 4, q) if pow(y, 2, q) != (x**3 + b.n) % q: raise ValueError("The given point is not on G1: y**2 = x**3 + b") # Choose the y whose leftmost bit is equal to the a_flag a_flag = (z % POW_2_382) // POW_2_381 if (y * 2) // q != a_flag: y = q - y return (FQ(x), FQ(y), FQ(1))
def decompress_G1(z: G1Compressed) -> G1Uncompressed: """ Recovers x and y coordinates from the compressed point. """ c_flag, b_flag, a_flag = get_flags(z) # c_flag == 1 indicates the compressed form # MSB should be 1 if not c_flag: raise ValueError("c_flag should be 1") is_inf_pt = is_point_at_infinity(z) if b_flag != 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_flag: raise ValueError("a point at infinity should have a_flag == 0") return Z1 # Else, not point at infinity # 3 MSBs should be 100 or 101 x = z % POW_2_381 if x >= q: raise ValueError( "Point value should be less than field modulus. Got %d", x) # Try solving y coordinate from the equation Y^2 = X^3 + b # using quadratic residue y = pow((x**3 + b.n) % q, (q + 1) // 4, q) if pow(y, 2, q) != (x**3 + b.n) % q: raise ValueError("The given point is not on G1: y**2 = x**3 + b") # Choose the y whose leftmost bit is equal to the a_flag if (y * 2) // q != int(a_flag): y = q - y return (FQ(x), FQ(y), FQ(1))
if pt is None: return None x, y, z = pt return (FQ12([x.n] + [0] * 11), FQ12([y.n] + [0] * 11), FQ12([z.n] + [0] * 11)) # Check consistency of the "line function" one, two, three = G1, double(G1), multiply(G1, 3) negone, negtwo, negthree = ( multiply(G1, curve_order - 1), multiply(G1, curve_order - 2), multiply(G1, curve_order - 3), ) assert linefunc(one, two, one)[0] == FQ(0) assert linefunc(one, two, two)[0] == FQ(0) assert linefunc(one, two, three)[0] != FQ(0) assert linefunc(one, two, negthree)[0] == FQ(0) assert linefunc(one, negone, one)[0] == FQ(0) assert linefunc(one, negone, negone)[0] == FQ(0) assert linefunc(one, negone, two)[0] != FQ(0) assert linefunc(one, one, one)[0] == FQ(0) assert linefunc(one, one, two)[0] != FQ(0) assert linefunc(one, one, negtwo)[0] == FQ(0) # Main miller loop def miller_loop(Q: Optimized_Point3D[FQ12], P: Optimized_Point3D[FQ12], final_exponentiate: bool = True) -> FQ12:
bls12_381_FQ2 as FQ2, bls12_381_FQ12 as FQ12, ) from .bls12_381_field_elements import ( field_modulus, ) curve_order = 52435875175126190479447740508185965837690552500527637822603658699938581184513 # Curve order should be prime assert pow(2, curve_order, curve_order) == 2 # Curve order should be a factor of field_modulus**12 - 1 assert (field_modulus**12 - 1) % curve_order == 0 # Curve is y**2 = x**3 + 4 b = FQ(4) # Twisted curve over FQ**2 b2 = FQ2((4, 4)) # Extension curve over FQ**12; same b value as over FQ b12 = FQ12((4, ) + (0, ) * 11) # Generator for curve over FQ G1 = ( FQ(3685416753713387016781088315183077757961620795782546409894578378688607592378376318836054947676345821548104185464507 ), # noqa: E501 FQ(1339506544944476473020471379941921221584933875938349620426543736416511423956333506472724655353366534992391756441569 ), # noqa: E501 ) # Generator for twisted curve over FQ2 G2 = ( FQ2([
GeneralPoint, Point2D, ) from .bn128_field_elements import ( field_modulus, ) curve_order = 21888242871839275222246405745257275088548364400416034343698204186575808495617 # Curve order should be prime assert pow(2, curve_order, curve_order) == 2 # Curve order should be a factor of field_modulus**12 - 1 assert (field_modulus**12 - 1) % curve_order == 0 # Curve is y**2 = x**3 + 3 b = FQ(3) # Twisted curve over FQ**2 b2 = FQ2([3, 0]) / FQ2([9, 1]) # Extension curve over FQ**12; same b value as over FQ b12 = FQ12([3] + [0] * 11) # Generator for curve over FQ G1 = cast(Point2D[FQ], (FQ(1), FQ(2))) # Generator for twisted curve over FQ2 G2 = ( FQ2([ 10857046999023057135944570762232829481370756359578518086990519993285655852781, 11559732032986387107991004021392285783925812861821192530917403151452391805634, ]), FQ2([ 8495653923123431417604973247489272438418190587263600148770280649306958101930,
def test_decompress_G2_with_no_modular_square_root_found(): with pytest.raises(ValueError, match="Failed to find a modular squareroot"): signature_to_G2(b'\x11' * 96) @pytest.mark.parametrize( 'pt,on_curve,is_infinity', [ # On curve points (G1, True, False), (multiply(G1, 5), True, False), # Infinity point but still on curve (Z1, True, True), # Not on curve ((FQ(5566), FQ(5566), FQ.one()), False, None), ]) 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:
def to_point(self) -> G1Uncompressed: x = int.from_bytes(self.value[:48], 'big') y = int.from_bytes(self.value[48:], 'big') point = FQ(x), FQ(y), FQ(1) return cast(G1Uncompressed, point)
from py_ecc.typing import ( Optimized_Field, Optimized_Point2D, Optimized_Point3D, ) field_modulus = field_properties["bn128"]["field_modulus"] curve_order = 21888242871839275222246405745257275088548364400416034343698204186575808495617 # Curve order should be prime assert pow(2, curve_order, curve_order) == 2 # Curve order should be a factor of field_modulus**12 - 1 assert (field_modulus**12 - 1) % curve_order == 0 # Curve is y**2 = x**3 + 3 b = FQ(3) # Twisted curve over FQ**2 b2 = FQ2([3, 0]) / FQ2([9, 1]) # Extension curve over FQ**12; same b value as over FQ b12 = FQ12([3] + [0] * 11) # Generator for curve over FQ G1 = (FQ(1), FQ(2), FQ(1)) # Generator for twisted curve over FQ2 G2 = ( FQ2([ 10857046999023057135944570762232829481370756359578518086990519993285655852781, 11559732032986387107991004021392285783925812861821192530917403151452391805634 ]), FQ2([ 8495653923123431417604973247489272438418190587263600148770280649306958101930,
return None x, y = pt fq12_point = (FQ12([x.n] + [0] * 11), FQ12([y.n] + [0] * 11)) return fq12_point # Check consistency of the "line function" one, two, three = G1, double(G1), multiply(G1, 3) negone, negtwo, negthree = ( multiply(G1, curve_order - 1), multiply(G1, curve_order - 2), multiply(G1, curve_order - 3), ) assert linefunc(one, two, one) == FQ(0) assert linefunc(one, two, two) == FQ(0) assert linefunc(one, two, three) != FQ(0) assert linefunc(one, two, negthree) == FQ(0) assert linefunc(one, negone, one) == FQ(0) assert linefunc(one, negone, negone) == FQ(0) assert linefunc(one, negone, two) != FQ(0) assert linefunc(one, one, one) == FQ(0) assert linefunc(one, one, two) != FQ(0) assert linefunc(one, one, negtwo) == FQ(0) # Main miller loop def miller_loop(Q: Point2D[FQ12], P: Point2D[FQ12]) -> FQ12: if Q is None or P is None:
def of_hex(hexstr: str) -> G1Point: xxx_bytes = bytes.fromhex(hexstr[2:98]) yyy_bytes = bytes.fromhex(hexstr[98:]) xxx = int.from_bytes(xxx_bytes, byteorder='big') yyy = int.from_bytes(yyy_bytes, byteorder='big') return (FQ(xxx), FQ(yyy), FQ(1))
from py_ecc.fields import optimized_bn128_FQ as FQ from Crypto.Cipher import Salsa20 from Crypto.Hash import SHA256 from Crypto.Protocol.KDF import HKDF H2 = (FQ2(( 9110522554455888802745409460679507850660709404525090688071718755658817738702, 14120302265976430476300156362541817133873389322564306174224598966336605751189 )), FQ2(( 8015061597608194114184122605728732604411275728909990814600934336120589400179, 21550838471174089343030649382112381550278244756451022825185015902639198926789 )), FQ2.one()) H1 = ( FQ(9727523064272218541460723335320998459488975639302513747055235660443850046724 ), FQ(5031696974169251245229961296941447383441169981934237515842977230762345915487 ), FQ(1), ) class IntPoly: def __init__(self, coeffs): self.coeffs = [coeff % CURVE_ORDER for coeff in coeffs] def evaluate(self, x): return sum([ coeff * pow(x, i, CURVE_ORDER) for i, coeff in enumerate(self.coeffs) ]) % CURVE_ORDER