Пример #1
0
 def to_affine(self) -> AffinePoint:
     if self.infinity:
         return AffinePoint(Fq.zero(self.ec.q), Fq.zero(self.ec.q),
                            self.infinity, self.ec)
     new_x = self.x / (self.z**2)
     new_y = self.y / (self.z**3)
     return AffinePoint(new_x, new_y, self.infinity, self.ec)
Пример #2
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
Пример #3
0
 def to_affine(self):
     if self.infinity:
         return AffinePoint(Fq.zero(self.ec.q), Fq.zero(self.ec.q),
                            self.infinity, self.ec)
     new_x = self.x / pow(self.z, 2)
     new_y = self.y / pow(self.z, 3)
     return AffinePoint(new_x, new_y, self.infinity, self.ec)
Пример #4
0
def test_ec():
    q = default_ec.q
    g = G1Generator()

    assert g.is_on_curve()
    assert 2 * g == g + g
    assert (3 * g).is_on_curve()
    assert 3 * g == g + g + g

    g2 = G2Generator()
    assert g2.x * (Fq(q, 2) * g2.y) == Fq(q, 2) * (g2.x * g2.y)
    assert g2.is_on_curve()
    s = g2 + g2
    assert untwist(twist(s.to_affine())) == s.to_affine()
    assert untwist(5 * twist(s.to_affine())) == (5 * s).to_affine()
    assert 5 * twist(s.to_affine()) == twist((5 * s).to_affine())
    assert s.is_on_curve()
    assert g2.is_on_curve()
    assert g2 + g2 == 2 * g2
    assert g2 * 5 == (g2 * 2) + (2 * g2) + g2
    y = y_for_x(g2.x, default_ec_twist, Fq2)
    assert y == g2.y or -y == g2.y

    g_j = G1Generator()
    g2_j = G2Generator()
    g2_j2 = G2Generator() * 2
    assert g.to_affine().to_jacobian() == g
    assert (g_j * 2).to_affine() == g.to_affine() * 2
    assert (g2_j + g2_j2).to_affine() == g2.to_affine() * 3
Пример #5
0
def double_point_jacobian(p1: JacobianPoint,
                          ec=default_ec,
                          FE=Fq) -> JacobianPoint:
    """
    Jacobian elliptic curve point doubling
    http://www.hyperelliptic.org/EFD/oldefd/jacobian.html
    """
    X, Y, Z = p1.x, p1.y, p1.z
    if Y == FE.zero(ec.q) or p1.infinity:
        return JacobianPoint(FE.one(ec.q), FE.one(ec.q), FE.zero(ec.q), True,
                             ec)

    # S = 4*X*Y^2
    S = Fq(ec.q, 4) * X * Y * Y

    Z_sq = Z * Z
    Z_4th = Z_sq * Z_sq
    Y_sq = Y * Y
    Y_4th = Y_sq * Y_sq

    # M = 3*X^2 + a*Z^4
    M = Fq(ec.q, 3) * X * X
    M += ec.a * Z_4th

    # X' = M^2 - 2*S
    X_p = M * M - Fq(ec.q, 2) * S
    # Y' = M*(S - X') - 8*Y^4
    Y_p = M * (S - X_p) - Fq(ec.q, 8) * Y_4th
    # Z' = 2*Y*Z
    Z_p = Fq(ec.q, 2) * Y * Z
    return JacobianPoint(X_p, Y_p, Z_p, False, ec)
Пример #6
0
    def lagrange_coeffs_at_zero(X: List[int], ec=default_ec) -> List[Fq]:
        """
        We have k+1 integers X[i], all less than ec.n and non-zero.
        The points (X[i], P(X[i])) interpolate into P(X), a degree k polynomial.
        Returns coefficients L_i such that P(0) = sum L_i * P(X[i]).
        """
        N = len(X)

        # Check all x values are different, less than ec.n, and non-zero.
        assert len(set(X)) == N and all(0 != x < ec.n for x in X)

        def weight(j):
            ans = Fq(ec.n, 1)
            for i in range(N):
                if i != j:
                    ans *= Fq(ec.n, X[j] - X[i])
            return ~ans

        # Using the second barycentric form,
        # P(0) = (sum_j (y_j * w_j / x_j)) / (sum_j w_j/x_j)
        # If desired, the weights can be precomputed.

        ans = []
        denominator = Fq(ec.n, 0)
        for j in range(N):
            shift = weight(j) * ~Fq(ec.n, -X[j])
            ans.append(shift)
            denominator += shift
        denominator = ~denominator
        for i in range(len(ans)):
            ans[i] *= denominator
        return ans
Пример #7
0
def hash_to_point_prehashed_Fq(m, ec=default_ec):
    if type(m) != bytes:
        m = m.encode("utf-8")
    t0 = Fq(ec.q, int.from_bytes(hash512(m + b"G1_0"), "big"))
    t1 = Fq(ec.q, int.from_bytes(hash512(m + b"G1_1"), "big"))

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

    return P * ec.h  # Scaling by cofactor
Пример #8
0
def test_ec():
    g = generator_Fq(default_ec)

    assert g.is_on_curve()
    assert 2 * g == g + g
    assert (3 * g).is_on_curve()
    assert 3 * g == g + g + g
    P = hash_to_point_Fq(bytes([]))
    assert P.is_on_curve()
    assert P.serialize() == bytes.fromhex(
        "12fc5ad5a2fbe9d4b6eb0bc16d530e5f263b6d59cbaf26c3f2831962924aa588ab84d46cc80d3a433ce064adb307f256"
    )

    g2 = generator_Fq2(default_ec_twist)
    assert g2.x * (2 * g2.y) == 2 * (g2.x * g2.y)
    assert g2.is_on_curve()
    s = g2 + g2
    assert untwist(twist(s)) == s
    assert untwist(5 * twist(s)) == 5 * s
    assert 5 * twist(s) == twist(5 * s)
    assert s.is_on_curve()
    assert g2.is_on_curve()
    assert g2 + g2 == 2 * g2
    assert g2 * 5 == (g2 * 2) + (2 * g2) + g2
    y = y_for_x(g2.x, default_ec_twist, Fq2)
    assert y[0] == g2.y or y[1] == g2.y
    assert hash_to_point_Fq2("chia") == hash_to_point_Fq2("chia")

    g_j = generator_Fq(default_ec_twist).to_jacobian()
    g2_j = generator_Fq2(default_ec_twist).to_jacobian()
    g2_j2 = (generator_Fq2(default_ec_twist) * 2).to_jacobian()
    assert g.to_jacobian().to_affine() == g
    assert (g_j * 2).to_affine() == g * 2
    assert (g2_j + g2_j2).to_affine() == g2 * 3

    assert sw_encode(Fq(default_ec.q, 0)).infinity
    assert sw_encode(Fq(default_ec.q, 1)) == sw_encode(Fq(default_ec.q, -1)).negate()
    assert (
        sw_encode(
            Fq(
                default_ec.q,
                0x019CFABA0C258165D092F6BCA9A081871E62A126C499340DC71C0E9527F923F3B299592A7A9503066CC5362484D96DD7,
            )
        )
        == generator_Fq()
    )
    assert (
        sw_encode(
            Fq(
                default_ec.q,
                0x186417302D5A65347A88B0F999AB2B504614AA5E2EEBDEB1A014C40BCEB7D2306C12A6D436BEFCF94D39C9DB7B263CD4,
            )
        )
        == generator_Fq().negate()
    )
Пример #9
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)
Пример #10
0
def double_point(p1: AffinePoint, ec=default_ec, FE=Fq) -> AffinePoint:
    """
    Basic elliptic curve point doubling
    """
    x, y = p1.x, p1.y
    left = Fq(ec.q, 3) * x * x
    left = left + ec.a
    s = left / (Fq(ec.q, 2) * y)
    new_x = s * s - x - x
    new_y = s * (x - new_x) - y
    return AffinePoint(new_x, new_y, False, ec)
Пример #11
0
    def from_bytes(buffer):
        bit1 = buffer[0] & 0x80
        buffer = bytes([buffer[0] & 0x1f]) + buffer[1:]
        x = Fq(default_ec.q, int.from_bytes(buffer, "big"))
        y_values = y_for_x(Fq(default_ec.q, x))
        y_values.sort()
        y = y_values[0]

        if bit1:
            y = y_values[1]

        return PublicKey(AffinePoint(x, y, False, default_ec).to_jacobian())
Пример #12
0
def double_line_eval(R: AffinePoint, P: AffinePoint, ec=default_ec):
    """
    Creates an equation for a line tangent to R,
    and evaluates this at the point P. f(x) = y - sv - v.
    f(P).
    """
    R12 = untwist(R)

    slope = (Fq(ec.q, 3) * (R12.x**2) + ec.a) / (Fq(ec.q, 2) * R12.y)
    v = R12.y - slope * R12.x

    return P.y - P.x * slope - v
Пример #13
0
    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)
Пример #14
0
 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)
Пример #15
0
    def verify(self):
        """
        This implementation of verify has several steps. First, it
        reorganizes the pubkeys and messages into groups, where
        each group corresponds to a message. Then, it checks if the
        siganture has info on how it was aggregated. If so, we
        exponentiate each pk based on the exponent in the AggregationInfo.
        If not, we find public keys that share messages with others,
        and aggregate all of these securely (with exponents.).
        Finally, since each public key now corresponds to a unique
        message (since we grouped them), we can verify using the
        distinct verification procedure.
        """
        message_hashes = self.aggregation_info.message_hashes
        public_keys = self.aggregation_info.public_keys
        assert (len(message_hashes) == len(public_keys))

        hash_to_public_keys = {}
        for i in range(len(message_hashes)):
            if message_hashes[i] in hash_to_public_keys:
                hash_to_public_keys[message_hashes[i]].append(public_keys[i])
            else:
                hash_to_public_keys[message_hashes[i]] = [public_keys[i]]

        final_message_hashes = []
        final_public_keys = []
        ec = public_keys[0].value.ec
        for message_hash, mapped_keys in hash_to_public_keys.items():
            dedup = list(set(mapped_keys))
            public_key_sum = JacobianPoint(Fq.one(ec.q), Fq.one(ec.q),
                                           Fq.zero(ec.q), True, ec)
            for public_key in dedup:
                try:
                    exponent = self.aggregation_info.tree[(message_hash,
                                                           public_key)]
                    public_key_sum += (public_key.value * exponent)
                except KeyError:
                    return False
            final_message_hashes.append(message_hash)
            final_public_keys.append(public_key_sum.to_affine())

        mapped_hashes = [
            hash_to_point_prehashed_Fq2(mh) for mh in final_message_hashes
        ]

        g1 = Fq(default_ec.n, -1) * generator_Fq()
        Ps = [g1] + final_public_keys
        Qs = [self.value.to_affine()] + mapped_hashes
        res = ate_pairing_multi(Ps, Qs, default_ec)
        return res == Fq12.one(default_ec.q)
Пример #16
0
def test_ec():
    g = generator_Fq(default_ec)

    assert (g.is_on_curve())
    assert (2 * g == g + g)
    assert ((3 * g).is_on_curve())
    assert (3 * g == g + g + g)
    P = hash_to_point_Fq(bytes([]))
    assert (P.is_on_curve())
    assert (P.serialize() == bytes.fromhex(
        "12fc5ad5a2fbe9d4b6eb0bc16d530e5f263b6d59cbaf26c3f2831962924aa588ab84d46cc80d3a433ce064adb307f256"
    ))

    g2 = generator_Fq2(default_ec_twist)
    assert (g2.x * (2 * g2.y) == 2 * (g2.x * g2.y))
    assert (g2.is_on_curve())
    s = g2 + g2
    assert (untwist(twist(s)) == s)
    assert (untwist(5 * twist(s)) == 5 * s)
    assert (5 * twist(s) == twist(5 * s))
    assert (s.is_on_curve())
    assert (g2.is_on_curve())
    assert (g2 + g2 == 2 * g2)
    assert (g2 * 5 == (g2 * 2) + (2 * g2) + g2)
    y = y_for_x(g2.x, default_ec_twist, Fq2)
    assert (y[0] == g2.y or y[1] == g2.y)
    assert (hash_to_point_Fq2("chia") == hash_to_point_Fq2("chia"))

    g_j = generator_Fq(default_ec_twist).to_jacobian()
    g2_j = generator_Fq2(default_ec_twist).to_jacobian()
    g2_j2 = (generator_Fq2(default_ec_twist) * 2).to_jacobian()
    assert (g.to_jacobian().to_affine() == g)
    assert ((g_j * 2).to_affine() == g * 2)
    assert ((g2_j + g2_j2).to_affine() == g2 * 3)

    assert (sw_encode(Fq(default_ec.q, 0)).infinity)
    assert (sw_encode(Fq(default_ec.q, 1)) == sw_encode(Fq(default_ec.q,
                                                           -1)).negate())
    assert (sw_encode(
        Fq(
            default_ec.q,
            0x019cfaba0c258165d092f6bca9a081871e62a126c499340dc71c0e9527f923f3b299592a7a9503066cc5362484d96dd7
        )) == generator_Fq())
    assert (sw_encode(
        Fq(
            default_ec.q,
            0x186417302d5a65347a88b0f999ab2b504614aa5e2eebdeb1a014c40bceb7d2306c12a6d436befcf94d39c9db7b263cd4
        )) == generator_Fq().negate())
Пример #17
0
    def create(T, N):
        """
        Create a new private key with associated data suitable for
        T of N threshold signatures under a Joint-Feldman scheme.

        After the dealing phase, one needs cooperation of T players
        out of N in order to sign a message with the master key pair.

        Return:
          - poly[0] - your share of the master secret key
          - commitments to your polynomial P
          - secret_fragments[j] = P(j), to be sent to player j
            (All N secret_fragments[j] can be combined to make a secret share.)
        """
        assert 1 <= T <= N
        g1 = generator_Fq()
        poly = [
            Fq(default_ec.n, RNG.randint(1, default_ec.n - 1))
            for _ in range(T)
        ]
        commitments = [g1 * c for c in poly]
        secret_fragments = [
            sum(c * pow(x, i, default_ec.n) for i, c in enumerate(poly))
            for x in range(1, N + 1)
        ]

        return PrivateKey(poly[0]), commitments, secret_fragments
Пример #18
0
    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')
Пример #19
0
def sw_encode(t, ec=default_ec, FE=Fq):
    if t == 0:  # Maps t=0 to the point at infinity
        return JacobianPoint(FE.one(ec.q), FE.one(ec.q), FE.zero(ec.q), True,
                             ec)
    # Parity will ensure that sw_encode(t) = -sw_encode(-t)
    parity = False
    if FE == Fq:
        if t > -t:
            parity = True
    elif FE == Fq2:
        if t[1] > (-t)[1]:
            parity = True

    # w = t^2 + b + 1
    w = t * t + ec.b + 1

    # Map w=0 to generator and its negation
    if w == 0:
        if FE == Fq:
            ret = generator_Fq(ec)
        else:
            return generator_Fq2(ec)
        if parity:
            ret = ret.negate()
        return ret

    w = ~w * ec.sqrt_n3 * t

    # At least 1 of x1, x2, x3 is guaranteed to be a valid x
    # x1 = -wt + sqrt(-3)
    x1 = -w * t + ec.sqrt_n3m1o2

    # x2 = -x1 - 1
    x2 = FE.from_fq(ec.q, Fq(ec.q, -1)) - x1

    # x3 = 1/w^2 + 1
    x3 = ~(w * w) + 1

    # Constant time algorithm for finding the correct x, from
    # FT paper.
    Xx1 = 1
    Xx2 = 1
    try:
        y_for_x(x1, ec, FE)
    except:  # noqa: E772
        Xx1 = -1
    try:
        y_for_x(x2, ec, FE)
    except:  # noqa: E772
        Xx2 = -1

    index = (((Xx1 - 1) * Xx2) % 3)

    xs = [x1, x2, x3]
    ys = y_for_x(xs[index], ec, FE)
    ret = AffinePoint(xs[index], ys[0], False, ec)
    if ret.lex_gt_neg() is not parity:
        ret = ret.negate()
    return ret
Пример #20
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)
Пример #21
0
def _from_bytes_F1(data):
    assert len(data) == 48
    ret = 0
    for d in data:
        ret = ret << 8
        ret += d
    if ret >= p:
        raise DeserError("invalid encoded value: not a residue mod p")
    return Fq(p, ret)
Пример #22
0
class TestFields(unittest.TestCase):
    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)

    def test_Fq(self):
        self.assertEqual(self.a1 + self.a1, self.a1 * 2)
        self.assertTrue((self.a1 - self.a1).is_zero())
        self.assertEqual(self.a1 + self.a1 + self.a1 + self.b1 + self.b1,
                         3 * self.a1 + 2 * self.b1)
        self.assertTrue((self.a1 * self.b1 / self.b1 / self.a1).is_one())
        self.assertEqual(self.a1.sqrt().square(), self.a1)
        self.assertEqual(self.a1**3, self.a1 * self.a1 * self.a1)

    def test_Fq2(self):
        self.assertEqual(self.a2 + self.a2, self.a2 * 2)
        self.assertTrue((self.a2 - self.a2).is_zero())
        self.assertEqual(self.a2 + self.a2 + self.a2 + self.b2 + self.b2,
                         3 * self.a2 + 2 * self.b2)
        self.assertTrue((self.a2 * self.b2 / self.b2 / self.a2).is_one())
        self.assertEqual(self.a2.sqrt().square(), self.a2)
        self.assertEqual(self.a2**3, self.a2 * self.a2 * self.a2)

    def test_Fq6(self):
        self.assertEqual(self.a6 + self.a6, self.a6 * 2)
        self.assertTrue((self.a6 - self.a6).is_zero())
        self.assertEqual(self.a6 + self.a6 + self.a6 + self.b6 + self.b6,
                         3 * self.a6 + 2 * self.b6)
        self.assertTrue((self.a6 * self.b6 / self.b6 / self.a6).is_one())
        self.assertEqual(self.a6**3, self.a6 * self.a6 * self.a6)

    def test_Fq12(self):
        self.assertEqual(self.a12 + self.a12, self.a12 * 2)
        self.assertTrue((self.a12 - self.a12).is_zero())
        self.assertEqual(self.a12 + self.a12 + self.a12 + self.b12 + self.b12,
                         3 * self.a12 + 2 * self.b12)
        self.assertTrue((self.a12 * self.b12 / self.b12 / self.a12).is_one())
        self.assertEqual(self.a12**3, self.a12 * self.a12 * self.a12)
Пример #23
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())
Пример #24
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))
Пример #25
0
 def interpolate_at_zero(X: List[int], Y: List[Fq], ec=default_ec) -> Fq:
     """
     The k+1 points (X[i], Y[i]) interpolate into P(X),
     a degree k polynomial.
     Returns P(0).
     """
     ans = Fq(ec.n, 0)
     for lamb, y in zip(Threshold.lagrange_coeffs_at_zero(X, ec), Y):
         ans += lamb * y
     return ans
Пример #26
0
    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)
Пример #27
0
    def aggregate(public_keys, secure):
        """
        Aggregates public keys together
        """
        if len(public_keys) < 1:
            raise Exception("Invalid number of keys")
        public_keys.sort()

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

        ec = public_keys[0].value.ec
        sum_keys = JacobianPoint(Fq.one(ec.q), Fq.one(ec.q),
                                 Fq.zero(ec.q), True, ec)
        for i in range(len(public_keys)):
            addend = public_keys[i].value
            if secure:
                addend *= computed_Ts[i]
            sum_keys += addend

        return PublicKey.from_g1(sum_keys)
Пример #28
0
 def run_tests():
     import random
     for _ in range(0, 128):
         t1 = Fq(p, random.getrandbits(380))
         t2 = Fq(p, random.getrandbits(380))
         # test helpers individually
         for t in (t1, t2):
             P = osswu_help(t)
             Pp = from_jacobian(P)
             assert Pp[0]**3 + EllP_a * Pp[0] + EllP_b == Pp[1]**2
             P = iso11(P)
             Pp = from_jacobian(P)
             assert Pp[0]**3 + 4 == Pp[1]**2
             P = clear_h(P)
             Pp = from_jacobian(P)
             assert Pp[0]**3 + 4 == Pp[1]**2
         # now test end-to-end
         P = from_jacobian(opt_swu_map(t1, t2))
         assert P[0]**3 + 4 == P[1]**2
         sys.stdout.write('.')
         sys.stdout.flush()
     sys.stdout.write("\n")
Пример #29
0
def osswu2_help(t):
    assert isinstance(t, Fq2)

    # first, compute X0(t), detecting and handling exceptional case
    num_den_common = xi_2**2 * t**4 + xi_2 * t**2
    x0_num = Ell2p_b * (num_den_common + Fq(q, 1))
    x0_den = -Ell2p_a * num_den_common
    x0_den = Ell2p_a * xi_2 if x0_den == 0 else x0_den

    # compute num and den of g(X0(t))
    gx0_den = pow(x0_den, 3)
    gx0_num = Ell2p_b * gx0_den
    gx0_num += Ell2p_a * x0_num * pow(x0_den, 2)
    gx0_num += pow(x0_num, 3)

    # try taking sqrt of g(X0(t))
    # this uses the trick for combining division and sqrt from Section 5 of
    # Bernstein, Duif, Lange, Schwabe, and Yang, "High-speed high-security signatures."
    # J Crypt Eng 2(2):77--89, Sept. 2012. http://ed25519.cr.yp.to/ed25519-20110926.pdf
    tmp1 = pow(gx0_den, 7)  # v^7
    tmp2 = gx0_num * tmp1  # u v^7
    tmp1 = tmp1 * tmp2 * gx0_den  # u v^15
    sqrt_candidate = tmp2 * pow(tmp1, (q**2 - 9) // 16)

    # check if g(X0(t)) is square and return the sqrt if so
    for root in roots_of_unity:
        y0 = sqrt_candidate * root
        if y0**2 * gx0_den == gx0_num:
            # found sqrt(g(X0(t))). force sign of y to equal sign of t
            if sgn0(y0) != sgn0(t):
                y0 = -y0
            assert sgn0(y0) == sgn0(t)
            return JacobianPoint(x0_num * x0_den, y0 * pow(x0_den, 3), x0_den,
                                 False, default_ec_twist)

    # if we've gotten here, then g(X0(t)) is not square. convert srqt_candidate to sqrt(g(X1(t)))
    (x1_num, x1_den) = (xi_2 * t**2 * x0_num, x0_den)
    (gx1_num, gx1_den) = (xi_2**3 * t**6 * gx0_num, gx0_den)
    sqrt_candidate *= t**3
    for eta in etas:
        y1 = eta * sqrt_candidate
        if y1**2 * gx1_den == gx1_num:
            # found sqrt(g(X1(t))). force sign of y to equal sign of t
            if sgn0(y1) != sgn0(t):
                y1 = -y1
            assert sgn0(y1) == sgn0(t)
            return JacobianPoint(x1_num * x1_den, y1 * pow(x1_den, 3), x1_den,
                                 False, default_ec_twist)

    # if we got here, something is wrong
    raise RuntimeError("osswu2_help failed for unknown reasons")
Пример #30
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