コード例 #1
0
    def divide_by(self, divisor_signatures):
        """
        Signature division (elliptic curve subtraction). This is useful if
        you have already verified parts of the tree, since verification
        of the resulting quotient signature will be faster (less pairings
        have to be perfomed).

        This function Divides an aggregate signature by other signatures
        in the aggregate trees. A signature can only be divided if it is
        part of the subset, and all message/public key pairs in the
        aggregationInfo for the divisor signature are unique. i.e you cannot
        divide s1 / s2, if s2 is an aggregate signature containing m1,pk1,
        which is also present somewhere else in s1's tree. Note, s2 itself
        does not have to be unique.
        """
        message_hashes_to_remove = []
        pubkeys_to_remove = []
        prod = JacobianPoint(Fq2.one(default_ec.q), Fq2.one(default_ec.q),
                             Fq2.zero(default_ec.q), True, default_ec)
        for divisor_sig in divisor_signatures:
            pks = divisor_sig.aggregation_info.public_keys
            message_hashes = divisor_sig.aggregation_info.message_hashes
            if len(pks) != len(message_hashes):
                raise Exception("Invalid aggregation info")

            for i in range(len(pks)):
                divisor = divisor_sig.aggregation_info.tree[
                        (message_hashes[i], pks[i])]
                try:
                    dividend = self.aggregation_info.tree[
                        (message_hashes[i], pks[i])]
                except KeyError:
                    raise Exception("Signature is not a subset")
                if i == 0:
                    quotient = (Fq(default_ec.n, dividend)
                                / Fq(default_ec.n, divisor))
                else:
                    # Makes sure the quotient is identical for each public
                    # key, which means message/pk pair is unique.
                    new_quotient = (Fq(default_ec.n, dividend)
                                    / Fq(default_ec.n, divisor))
                    if quotient != new_quotient:
                        raise Exception("Cannot divide by aggregate signature,"
                                        + "msg/pk pairs are not unique")
                message_hashes_to_remove.append(message_hashes[i])
                pubkeys_to_remove.append(pks[i])
            prod += (divisor_sig.value * -quotient)
        copy = Signature(deepcopy(self.value + prod),
                            deepcopy(self.aggregation_info))

        for i in range(len(message_hashes_to_remove)):
            a = message_hashes_to_remove[i]
            b = pubkeys_to_remove[i]
            if (a, b) in copy.aggregation_info.tree:
                del copy.aggregation_info.tree[(a, b)]
        sorted_keys = list(copy.aggregation_info.tree.keys())
        sorted_keys.sort()
        copy.aggregation_info.message_hashes = [t[0] for t in sorted_keys]
        copy.aggregation_info.public_keys = [t[1] for t in sorted_keys]
        return copy
コード例 #2
0
    def aggregate_sigs_secure(signatures, public_keys, message_hashes):
        """
        Aggregate signatures using the secure method, which calculates
        exponents based on public keys, and raises each signature to an
        exponent before multiplying them together. This is secure against
        rogue public key attack, but is slower than simple aggregation.
        """
        if (len(signatures) != len(public_keys)
                or len(public_keys) != len(message_hashes)):
            raise Exception("Invalid number of keys")
        mh_pub_sigs = [(message_hashes[i], public_keys[i], signatures[i])
                       for i in range(len(signatures))]

        # Sort by message hash + pk
        mh_pub_sigs.sort()

        computed_Ts = BLS.hash_pks(len(public_keys), public_keys)

        # Raise each sig to a power of each t,
        # and multiply all together into agg_sig
        ec = public_keys[0].ec
        agg_sig = JacobianPoint(Fq2.one(ec.q), Fq2.one(ec.q), Fq2.zero(ec.q),
                                True, ec)

        for i, (_, _, signature) in enumerate(mh_pub_sigs):
            agg_sig += signature * computed_Ts[i]

        return Signature.from_g2(agg_sig)
コード例 #3
0
ファイル: paring.py プロジェクト: CarlBeek/bls_sigs
def untwist(P):
    q = P.X.q
    root = Fq6(Fq2.zero(q), Fq2.one(q), Fq2.zero(q))
    zero = Fq6.zero(q)
    omega2 = Fq12(root, zero)
    omega3 = Fq12(zero, root)
    return EC.from_affine(omega2.inverse() * P.x, omega3.inverse() * P.y)
コード例 #4
0
ファイル: paring.py プロジェクト: CarlBeek/bls_sigs
def twist(P):
    q = P.X.q
    root = Fq6(Fq2.zero(q), Fq2.one(q), Fq2.zero(q))
    zero = Fq6.zero(q)
    omega2 = Fq12(root, zero)
    omega3 = Fq12(zero, root)
    c0 = omega2 * P.x
    c1 = omega3 * P.y
    return TwistedEC.from_affine(c0.c0.c0, c1.c0.c0)
コード例 #5
0
    def aggregate_unit_sigs(signatures: List[Signature],
                            players: List[int],
                            T: int,
                            ec=default_ec) -> Signature:

        lambs = Threshold.lagrange_coeffs_at_zero(players, ec)
        agg = AffinePoint(Fq2.zero(ec.q), Fq2.zero(ec.q), True,
                          ec).to_jacobian()
        for i, sig in enumerate(signatures):
            agg += sig.value * lambs[i]
        return Signature.from_g2(agg)
コード例 #6
0
def test_edge_case_sign_Fq2():
    q = default_ec.q
    a = Fq(q, 62323)
    test_case_1 = Fq2(q, a, Fq(q, 0))
    test_case_2 = Fq2(q, -a, Fq(q, 0))
    assert sign_Fq2(test_case_1) != sign_Fq2(test_case_2)

    test_case_3 = Fq2(q, Fq(q, 0), a)
    test_case_4 = Fq2(q, Fq(q, 0), -a)

    assert sign_Fq2(test_case_3) != sign_Fq2(test_case_4)
コード例 #7
0
    def aggregate(signatures):
        """
        Aggregate signatures by multiplying them together. This IS secure
        against rogue public key attacks, assuming these signatures were
        generated using sign_prepend.
        """
        q = default_ec.q
        agg_sig = (AffinePoint(Fq2.zero(q), Fq2.zero(q), True,
                               default_ec).to_jacobian())

        for sig in signatures:
            agg_sig += sig.value

        return PrependSignature.from_g2(agg_sig)
コード例 #8
0
    def aggregate_sigs_simple(signatures):
        """
        Aggregate signatures by multiplying them together. This is NOT secure
        against rogue public key attacks, so do not use this for signatures
        on the same message.
        """
        q = default_ec.q
        agg_sig = (AffinePoint(Fq2.zero(q), Fq2.zero(q), True,
                               default_ec).to_jacobian())

        for sig in signatures:
            agg_sig += sig.value

        return Signature.from_g2(agg_sig)
コード例 #9
0
ファイル: tests.py プロジェクト: CarlBeek/bls_sigs
 def test_frobenius_coefficients(self):
     self.assertEqual((Fq(1, q), Fq(-1, q)), FROB_FQ2)
     self.assertEqual(
         tuple(
             Fq2.all_one_poly(q)**(((q**i) - 1) // 3) for i in range(0, 6)),
         FROB_FQ6_C1)
     self.assertEqual(
         tuple(
             Fq2.all_one_poly(q)**(((2 * q**i) - 2) // 3)
             for i in range(0, 6)), FROB_FQ6_C2)
     self.assertEqual(
         tuple(
             Fq2.all_one_poly(q)**(((q**i) - 1) // 6)
             for i in range(0, 12)), FROB_FQ12_C1)
コード例 #10
0
ファイル: tests.py プロジェクト: CarlBeek/bls_sigs
    def setUp(self):
        self.a1 = Fq(48, 199)
        self.b1 = Fq(50, 199)
        self.c1 = Fq(62, 199)
        self.A1 = EC.get_point_from_x(self.a1)
        self.B1 = EC.get_point_from_x(self.b1)

        self.a2 = Fq2(self.b1, self.a1)
        self.b2 = Fq2(self.b1, self.c1)
        self.A2 = TwistedEC.get_point_from_x(self.a2)
        self.B2 = TwistedEC.get_point_from_x(self.b2)

        self.g1 = EC.from_affine(g1_x, g1_y)
        self.g2 = TwistedEC.from_affine(g2_x, g2_y)
コード例 #11
0
ファイル: serdesZ.py プロジェクト: algorand/bls_sigs_ref-fork
    def main():
        for Pinf in ((F1_zero, F1_one, F1_zero), (F2_zero, F2_one, F2_zero)):
            test_ell(Pinf)
            sys.stdout.write('.')
            sys.stdout.flush()

        for _ in range(0, 32):
            sys.stdout.write('.')
            sys.stdout.flush()
            test_ell(opt_swu_map(Fq(p, random.getrandbits(380))))
            test_ell(
                opt_swu2_map(
                    Fq2(p, random.getrandbits(380), random.getrandbits(380))))

        for (ell2, invals) in ((False, invalid_inputs_1), (True,
                                                           invalid_inputs_2)):
            curve_name = "E2" if ell2 else "E1"
            for (idx, inval) in enumerate(invals):
                try:
                    deserialize(binascii.unhexlify(inval), ell2)
                except DeserError:
                    sys.stdout.write('*')
                    sys.stdout.flush()
                else:
                    raise DeserError(
                        "expected failed deserialization of #%d on %s" %
                        (idx, curve_name))

        sys.stdout.write('\n')
コード例 #12
0
ファイル: opt_swu_g2.py プロジェクト: valerini/bls_sigs_ref
 def run_tests():
     import random
     from curve_ops import psi
     for _ in range(0, 128):
         t1 = Fq2(p, random.getrandbits(380), random.getrandbits(380))
         t2 = Fq2(p, random.getrandbits(380), random.getrandbits(380))
         # make sure each helper function actually returns a point on the curve
         for t in (t1, t2):
             P = osswu2_help(t)
             Pp = from_jacobian(P)
             assert Pp[0]**3 + Ell2p_a * Pp[0] + Ell2p_b == Pp[1]**2
             P = iso3(P)
             Pp = from_jacobian(P)
             assert Pp[0]**3 + Fq2(p, 4, 4) == Pp[1]**2
             P = psi(P)
             Pp = from_jacobian(P)
             assert Pp[0]**3 + Fq2(p, 4, 4) == Pp[1]**2
             P = clear_h2(P)
             Pp = from_jacobian(P)
             assert Pp[0]**3 + Fq2(p, 4, 4) == Pp[1]**2
         # now test end-to-end
         P = opt_swu2_map(t1, t2)
         Pp = from_jacobian(P)
         assert Pp[0]**3 + Fq2(p, 4, 4) == Pp[1]**2
         sys.stdout.write('.')
         sys.stdout.flush()
     sys.stdout.write("\n")
コード例 #13
0
def hash_to_point_prehashed_Fq2(m, ec=default_ec_twist):
    if type(m) != bytes:
        m = m.encode("utf-8")
    t0_0 = Fq(ec.q, int.from_bytes(hash512(m + b"G2_0_c0"), "big"))
    t0_1 = Fq(ec.q, int.from_bytes(hash512(m + b"G2_0_c1"), "big"))
    t1_0 = Fq(ec.q, int.from_bytes(hash512(m + b"G2_1_c0"), "big"))
    t1_1 = Fq(ec.q, int.from_bytes(hash512(m + b"G2_1_c1"), "big"))

    t0 = Fq2(ec.q, t0_0, t0_1)
    t1 = Fq2(ec.q, t1_0, t1_1)

    P = sw_encode(t0, ec, Fq2) + sw_encode(t1, ec, Fq2)

    # This is the cofactor multiplication, done in a more
    # efficient way. See page 11 of "Efficient hash maps
    # to G2 on BLS curves" by Budrioni and Pintore.
    x = -ec.x
    psi2P = psi(psi(2 * P, ec), ec)
    t0 = x * P
    t1 = x * t0
    t2 = (t1 + t0) - P
    t3 = psi((x + 1) * P, ec)
    return t2 - t3 + psi2P
コード例 #14
0
    def from_bytes(buffer, aggregation_info=None):
        use_big_y = buffer[0] & 0x80

        buffer = bytes([buffer[0] & 0x1f]) + buffer[1:]

        x0 = int.from_bytes(buffer[:48], "big")
        x1 = int.from_bytes(buffer[48:], "big")
        x = Fq2(default_ec.q, Fq(default_ec.q, x0), Fq(default_ec.q, x1))
        ys = y_for_x(x, default_ec_twist, Fq2)
        y = ys[0]
        if ((use_big_y and ys[1][1] > default_ec.q // 2) or
                (not use_big_y and ys[1][1] < default_ec.q // 2)):
            y = ys[1]

        return Signature(AffinePoint(x, y, False, default_ec_twist)
                            .to_jacobian(),
                            aggregation_info)
コード例 #15
0
def test_fields():
    a = Fq(17, 30)
    b = Fq(17, -18)
    c = Fq2(17, a, b)
    d = Fq2(17, a + a, -5)
    e = c * d
    f = e * d
    assert f != e
    e_sq = e * e
    e_sqrt = e_sq.modsqrt()
    assert pow(e_sqrt, 2) == e_sq

    a2 = Fq(
        172487123095712930573140951348,
        3012492130751239573498573249085723940848571098237509182375,
    )
    b2 = Fq(172487123095712930573140951348, 3432984572394572309458723045723849)
    c2 = Fq2(172487123095712930573140951348, a2, b2)
    assert b2 != c2

    g = Fq6(17, c, d, d * d * c)
    h = Fq6(17, a + a * c, c * b * a, b * b * d * 21)
    i = Fq12(17, g, h)
    assert ~(~i) == i
    assert (~(i.root)) * i.root == Fq6.one(17)
    x = Fq12(17, Fq6.zero(17), i.root)
    assert (~x) * x == Fq12.one(17)

    j = Fq6(17, a + a * c, Fq2.zero(17), Fq2.zero(17))
    j2 = Fq6(17, a + a * c, Fq2.zero(17), Fq2.one(17))
    assert j == (a + a * c)
    assert j2 != (a + a * c)
    assert j != j2

    # Test frob_coeffs
    one = Fq(default_ec.q, 1)
    two = one + one
    a = Fq2(default_ec.q, two, two)
    b = Fq6(default_ec.q, a, a, a)
    c = Fq12(default_ec.q, b, b)
    for base in (a, b, c):
        for expo in range(1, base.extension):
            assert base.qi_power(expo) == pow(base, pow(default_ec.q, expo))
コード例 #16
0
    def from_bytes(buffer):
        use_big_y = buffer[0] & 0x80
        prepend = buffer[0] & 0x40
        if not prepend:
            raise "Should have prepend bit set"

        buffer = bytes([buffer[0] & 0x1f]) + buffer[1:]

        x0 = int.from_bytes(buffer[:48], "big")
        x1 = int.from_bytes(buffer[48:], "big")
        x = Fq2(default_ec.q, Fq(default_ec.q, x0), Fq(default_ec.q, x1))
        ys = y_for_x(x, default_ec_twist, Fq2)
        y = ys[0]
        if ((use_big_y and ys[1][1] > default_ec.q // 2)
                or (not use_big_y and ys[1][1] < default_ec.q // 2)):
            y = ys[1]

        return PrependSignature(
            AffinePoint(x, y, False, default_ec_twist).to_jacobian())
コード例 #17
0
ファイル: signature.py プロジェクト: xazab/bls-signatures
    def from_bytes(buffer, aggregation_info=None):
        use_big_y = buffer[0] & 0x80
        prepend = buffer[0] & 0x40
        if prepend:
            raise Exception("Should not have prepend bit set")

        buffer = bytes([buffer[0] & 0x1F]) + buffer[1:]

        x0 = int.from_bytes(buffer[:48], "big")
        x1 = int.from_bytes(buffer[48:], "big")
        x = Fq2(default_ec.q, Fq(default_ec.q, x0), Fq(default_ec.q, x1))
        ys = y_for_x(x, default_ec_twist, Fq2)
        y = ys[0]
        if (use_big_y and ys[1][1] > default_ec.q // 2) or (
                not use_big_y and ys[1][1] < default_ec.q // 2):
            y = ys[1]

        return Signature(
            AffinePoint(x, y, False, default_ec_twist).to_jacobian(),
            aggregation_info)
コード例 #18
0
ファイル: tests.py プロジェクト: CarlBeek/bls_sigs
    def setUp(self):
        self.a1 = Fq(3, 11)
        self.b1 = Fq(4, 11)
        self.c1 = Fq(7, 11)
        self.d1 = Fq(12, 11)
        self.e1 = Fq(2, 11)
        self.f1 = Fq(9, 11)
        self.g1 = Fq(6, 11)

        self.a2 = Fq2(self.a1, self.b1)
        self.b2 = Fq2(self.b1, self.c1)
        self.c2 = Fq2(self.c1, self.d1)
        self.d2 = Fq2(self.d1, self.e1)
        self.e2 = Fq2(self.e1, self.f1)
        self.f2 = Fq2(self.f1, self.g1)

        self.a6 = Fq6(self.a2, self.b2, self.c2)
        self.b6 = Fq6(self.b2, self.c2, self.d2)
        self.c6 = Fq6(self.d2, self.e2, self.f2)

        self.a12 = Fq12(self.a6, self.b6)
        self.b12 = Fq12(self.b6, self.c6)
コード例 #19
0
import sys

from consts import p, q
from fields import Fq, Fq2

if sys.version_info[0] < 3:
    sys.exit("This script requires Python3 or PyPy3")

###
## generators for BLS signatures
###
# I'd rather have these in consts, but then we'd get an import cycle, consts <-> fields
g1gen = (Fq(p, 0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb),
         Fq(p, 0x08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1),
         Fq.one(p))
g2gen = (Fq2(p, 0x024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb8,
                0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e),
         Fq2(p, 0x0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801,
                0x0606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be),
         Fq2.one(p))

###
## Basic curve operations
###
# Jacobian coordinates
def from_jacobian(P):
    z3inv = ~(P[2] ** 3)
    return (P[0] * P[2] * z3inv, P[1] * z3inv)

# point equality or co-z repr
def _point_eq_coz(P, Q, coZ):
    (X1, Y1, Z1) = P
コード例 #20
0
ファイル: opt_swu_g2.py プロジェクト: kwantam/bls_sigs_ref
def map2curve_osswu2(alpha, dst=None):
    return opt_swu2_map(*(Fq2(p, *hh) for hh in Hp2(alpha, 2, dst)))
コード例 #21
0
from fields import Fq, Fq2

# BLS parameter used to generate the other parameters
# Spec is found here: https://github.com/zkcrypto/pairing/tree/master/src/bls12_381
x = -0xD201000000010000

# 381 bit prime
# Also see fields:bls12381_q
q = 0x1A0111EA397FE69A4B1BA7B6434BACD764774B84F38512BF6730D2A0F6B0F6241EABFFFEB153FFFFB9FEFFFFFFFFAAAB

# a,b and a2, b2, define the elliptic curve and twisted curve.
# y^2 = x^3 + 4
# y^2 = x^3 + 4(u + 1)
a = Fq(q, 0)
b = Fq(q, 4)
a_twist = Fq2(q, 0, 0)
b_twist = Fq2(q, 4, 4)

# The generators for g1 and g2
gx = Fq(
    q,
    0x17F1D3A73197D7942695638C4FA9AC0FC3688C4F9774B905A14E3A3F171BAC586C55E83FF97A1AEFFB3AF00ADB22C6BB,
)
gy = Fq(
    q,
    0x08B3F481E3AAA0F1A09E30ED741D8AE4FCF5E095D5D00AF600DB18CB2C04B3EDD03CC744A2888AE40CAA232946C5E7E1,
)

g2x = Fq2(
    q,
    352701069587466618187139116011060144890029952792775240219908644239793785735715026873347600343865175952761926303160,
コード例 #22
0
    q)

# G2
g2_x0 = Fq(
    352701069587466618187139116011060144890029952792775240219908644239793785735715026873347600343865175952761926303160,
    q)
g2_x1 = Fq(
    3059144344244213709971259814753781636986470325476647558659373206291635324768958432433509563104347017837885763365758,
    q)
g2_y0 = Fq(
    1985150602287291935568054521177171638300868978215655730859378665066344726373823718423869104263333984641494340347905,
    q)
g2_y1 = Fq(
    927553665492332455747201965776037880757740193453592970025027978793976877002675564980949289727957565575433344219582,
    q)
g2_x = Fq2(g2_x0, g2_x1)
g2_y = Fq2(g2_y0, g2_y1)

# BLS Params
BLS_x = 0xd201000000010000
BLS_negative = True

# Frobenius map coefficients
# Fq(-1)**(((q**0) - 1) // 2), Fq(-1)**(((q**1) - 1) // 2)
FROB_FQ2 = (
    Fq(1, q),
    Fq(
        4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559786,
        q))
# tuple(Fq2.all_one_poly(q) ** (((q ** i) - 1) // 3) for i in range(0, 6))
FROB_FQ6_C1 = (
コード例 #23
0
ファイル: curve_ops.py プロジェクト: matt783/bls12-381_hash
            Q = point_double(Q)
    return Q


###
## Fast cofactor clearing using the untwist-Frobenius-twist Endomorphism
###
# We use the version given in section 4.1 of
#    Budroni and Pintore, "Efficient hash maps to G2 on BLS curves,"
#    ePrint 2017/419 https://eprint.iacr.org/2017/419
# NOTE: this impl works for affine coordinates. See ../src/test/g2_test.sage for a version
#       that works for Jacobian projective coordinates without computing an inversion.
#
# constants for Psi, the untwist-Frobenius-twist endomorphism
iwsc = 0xd0088f51cbff34d258dd3db21a5d66bb23ba5c279c2895fb39869507b587b120f55ffff58a9ffffdcff7fffffffd556
iwsc = Fq2(p, iwsc, iwsc - 1)
k_qi_x = Fq(
    p,
    0x1a0111ea397fe699ec02408663d4de85aa0d857d89759ad4897d29650fb85f9b409427eb4f49fffd8bfd00000000aaad
)
k_qi_y = Fq(
    p,
    0x6af0e0437ff400b6831e36d6bd17ffe48395dabc2d3435e77f76e17009241c5ee67992f72ec05f4c81084fbede3cc09
)
onei = Fq2(p, 1, 1)


# shortcut Frobenius evaluations that avoid going all the way to Fq12
def qi_x(x):
    return Fq2(p, k_qi_x * x[0], p - k_qi_x * x[1])
コード例 #24
0
    def aggregate(signatures):
        """
        Aggregates many (aggregate) signatures, using a combination of simple
        and secure aggregation. Signatures are grouped based on which ones
        share common messages, and these are all merged securely.
        """
        public_keys = []  # List of lists
        message_hashes = []  # List of lists

        for signature in signatures:
            if signature.aggregation_info.empty():
                raise Exception(
                    "Each signature must have a valid aggregation " + "info")
            public_keys.append(signature.aggregation_info.public_keys)
            message_hashes.append(signature.aggregation_info.message_hashes)

        # Find colliding vectors, save colliding messages
        messages_set = set()
        colliding_messages_set = set()

        for msg_vector in message_hashes:
            messages_set_local = set()
            for msg in msg_vector:
                if msg in messages_set and msg not in messages_set_local:
                    colliding_messages_set.add(msg)
                messages_set.add(msg)
                messages_set_local.add(msg)

        if len(colliding_messages_set) == 0:
            # There are no colliding messages between the groups, so we
            # will just aggregate them all simply. Note that we assume
            # that every group is a valid aggregate signature. If an invalid
            # or insecure signature is given, and invalid signature will
            # be created. We don't verify for performance reasons.
            final_sig = Signature.aggregate_sigs_simple(signatures)
            aggregation_infos = [sig.aggregation_info for sig in signatures]
            final_agg_info = AggregationInfo.merge_infos(aggregation_infos)
            final_sig.set_aggregation_info(final_agg_info)
            return final_sig

        # There are groups that share messages, therefore we need
        # to use a secure form of aggregation. First we find which
        # groups collide, and securely aggregate these. Then, we
        # use simple aggregation at the end.
        colliding_sigs = []
        non_colliding_sigs = []
        colliding_message_hashes = []  # List of lists
        colliding_public_keys = []  # List of lists

        for i in range(len(signatures)):
            group_collides = False
            for msg in message_hashes[i]:
                if msg in colliding_messages_set:
                    group_collides = True
                    colliding_sigs.append(signatures[i])
                    colliding_message_hashes.append(message_hashes[i])
                    colliding_public_keys.append(public_keys[i])
                    break
            if not group_collides:
                non_colliding_sigs.append(signatures[i])

        # Arrange all signatures, sorted by their aggregation info
        colliding_sigs.sort(key=lambda s: s.aggregation_info)

        # Arrange all public keys in sorted order, by (m, pk)
        sort_keys_sorted = []
        for i in range(len(colliding_public_keys)):
            for j in range(len(colliding_public_keys[i])):
                sort_keys_sorted.append((colliding_message_hashes[i][j],
                                         colliding_public_keys[i][j]))
        sort_keys_sorted.sort()
        sorted_public_keys = [pk for (mh, pk) in sort_keys_sorted]

        computed_Ts = BLS.hash_pks(len(colliding_sigs), sorted_public_keys)

        # Raise each sig to a power of each t,
        # and multiply all together into agg_sig
        ec = sorted_public_keys[0].value.ec
        agg_sig = JacobianPoint(Fq2.one(ec.q), Fq2.one(ec.q), Fq2.zero(ec.q),
                                True, ec)

        for i, signature in enumerate(colliding_sigs):
            agg_sig += signature.value * computed_Ts[i]

        for signature in non_colliding_sigs:
            agg_sig += signature.value

        final_sig = Signature.from_g2(agg_sig)
        aggregation_infos = [sig.aggregation_info for sig in signatures]
        final_agg_info = AggregationInfo.merge_infos(aggregation_infos)
        final_sig.set_aggregation_info(final_agg_info)

        return final_sig
コード例 #25
0
ファイル: opt_swu_g2.py プロジェクト: valerini/bls_sigs_ref
#!/usr/bin/python
#
# (C) 2019 Riad S. Wahby <*****@*****.**>
#
# pure Python implementation of optimized simplified SWU map to BLS12-381 G2

from consts import g2suite, p
from curve_ops import clear_h2, eval_iso, from_jacobian, point_add
from fields import Fq2, sgn0, roots_of_unity
from hash_to_field import Hp2
from util import get_cmdline_options, print_g2_hex, print_tv_hash

# distinguished non-square in Fp2 for SWU map
xi_2 = Fq2(p, 1, 1)

# 3-isogenous curve parameters
Ell2p_a = Fq2(p, 0, 240)
Ell2p_b = Fq2(p, 1012, 1012)

# eta values, used for computing sqrt(g(X1(t)))
ev1 = 0x2c4a7244a026bd3e305cc456ad9e235ed85f8b53954258ec8186bb3d4eccef7c4ee7b8d4b9e063a6c88d0aa3e03ba01
ev2 = 0x85fa8cd9105715e641892a0f9a4bb2912b58b8d32f26594c60679cc7973076dc6638358daf3514d6426a813ae01f51a
etas = (Fq2(p, ev1, 0), Fq2(p, 0, ev1), Fq2(p, ev2, ev2), Fq2(p, ev2, p - ev2))
del ev1, ev2


###
## Simplified SWU map, optimized and adapted to Ell2'
###
# This function maps an element of Fp^2 to the curve Ell2', 3-isogenous to Ell2.
def osswu2_help(t):
コード例 #26
0
def qi_y(y):
    return Fq2(p, k_qi_y * (y[0] + y[1]), k_qi_y * (y[0] - y[1]))
コード例 #27
0
def qi_x(x):
    return Fq2(p, k_qi_x * x[0], p - k_qi_x * x[1])
コード例 #28
0
ファイル: opt_swu_g2.py プロジェクト: valerini/bls_sigs_ref
def map2curve_osswu2(alpha, dst=None):
    t1 = Fq2(p, *Hp2(alpha, 0, dst))
    t2 = Fq2(p, *Hp2(alpha, 1, dst))
    return opt_swu2_map(t1, t2)
コード例 #29
0
ファイル: test1.py プロジェクト: integritychain/ebs_sigs
import random
from fields import Fq1, Fq2
from curve import Curve, Point
from weil import miller_loop, weil_pairing

random.seed(1234)

print("\n\n1. Testing Fq1 and Fq2 inverse", end='')
Fq1.set_q(631)
Fq2.set_q(2**255 - 19)
for i in range(10):
    a1 = Fq1(random.randrange(1, Fq1.Q))
    b1 = Fq1.one() // a1
    assert a1 * b1 == Fq1.one()
    a2 = Fq2(random.randrange(1, Fq2.Q), random.randrange(1, Fq2.Q))
    b2 = Fq2.one() // a2
    res = a2 * b2
    assert a2 * b2 == Fq2.one()
print("...passed\n\n")

Curve.set_a_b(30, 34)
P = Point(x=Fq1(36), y=Fq1(60))
Q = Point(x=Fq1(121), y=Fq1(387))
S = Point(x=Fq1(0), y=Fq1(36))

print("group1 = [", end='')
for i in range(1, 5):
    g = Curve.multiply(P, i)
    print("(Affine {:3} {:3}), ".format(g.x.q, g.y.q), end='')
print("")
コード例 #30
0
def decompress(point):
    greatest = point >> 2 * q_bits
    x_c0 = Fq(point & (2**q_bits - 1), q)
    x_c1 = Fq((point >> q_bits) & (2**q_bits - 1), q)
    x = Fq2(x_c0, x_c1)
    return TwistedEC.get_point_from_x(x, greatest)