Example #1
0
 def order(self, base_field=False):
     a, b = self.curve[0].value[0].value, self.curve[1].value[0].value
     p = self.field.p
     e = self.field.e
     if base_field:
         count = 1
         for x in range(p):
             y_squared = (x**3+a*x+b) % p
             if y_squared == 0:
                 count += 1
             elif nt.legendre_symbol(y_squared, p) == 1:
                 count += 2
         return count
     else:
         base_order = self.order(True)
         t = p + 1 - base_order
         a = (t + sqrt(t**2 - 4*p))/2
         b = (t - sqrt(t**2 - 4*p))/2
         return round((1 + p**e - a**e - b**e).real)
Example #2
0
    def weil_pairing(self, P, Q):
        m = P.order()
        assert(m == Q.order())

        def g(R, S):
            x_1, y_1 = R.value
            x_2, y_2 = S.value
            if R == -S:
                def h(T):
                    return T.value[0] - x_1
            else:
                if R == S:
                    m = (3*x_1**2 + self.curve[0]) * (2*y_1).inverse()
                else:
                    m = (y_2 - y_1)*(x_2 - x_1).inverse()

                def h(T):
                    num = T.value[1] - y_1 - m*(T.value[0] - x_1)
                    den = T.value[0] + x_1 + x_2 - m**2

                    if not den.inverse() and num == 0:
                        return self.field.elt(1)
                    elif not den.inverse():
                        return 'inf'
                    return num * den.inverse()
            return h

        binary_m = bin(m)
        n = len(binary_m) - 2
        ms = [int(binary_m[i]) for i in range(n+1, 1, -1)]

        def f(R, x):
            if R == x:
                return self.field.elt(0)
            T = R
            ops = []
            for i in range(n-2, -1, -1):
                ops.append((True, 2))
                ops.append((False, T, T))
                T = T+T
                if ms[i] == 1:
                    ops.append((False, T, R))
                    T = T+R
            out = self.field.elt(1)

            for op in ops:
                if op[0]:
                    out = out**2
                else:
                    # zeroes and infinity cancel
                    if type(g(op[1], op[2])(x)) is str or g(op[1], op[2])(x) == 0:
                        continue
                    out = (out * g(op[1], op[2])(x))
            return out

        a, b = self.curve[0].value[0].value, self.curve[1].value[0].value
        x = randint(1, self.field.p)

        while True:
            x = randint(1, self.field.p)
            f_x = self.field.elt(x)
            if f_x == P.value[0] or f_x == -Q.value[0]:
                continue
            elif P-Q != 0 and f_x == (P-Q).value[0]:
                continue
            elif nt.legendre_symbol(x**3+a*x+b, self.field.p) != 1:
                continue
            y = nt.modular_sqrt(x**3+a*x+b, self.field.p)
            S = self.point(x, y)

            break

        out = f(P, Q+S)*f(P, S).inverse() * (f(Q, P-S)*f(Q, -S).inverse()).inverse()
        return out