Exemple #1
0
 def rand(self):
     r = Fp()
     r.rand()
     self.a = r.copy()
     r.rand()
     self.b = r.copy()
     return self
Exemple #2
0
class ECp:
    A = Fp(curve.A)
    B = Fp(curve.B)

    def __init__(self):
        self.x = Fp(0)
        self.y = Fp(1)
        if curve.CurveType == EDWARDS:
            self.z = Fp(1)
        else:
            self.z = Fp(0)

    def copy(self):
        return copy.deepcopy(self)

# convert to affine coordinates

    def affine(self):
        if self.isinf() or self.z.isone():
            return
        iz = self.z.inverse()  # iz / self.z
        self.x *= iz
        if curve.CurveType != MONTGOMERY:
            self.y *= iz
        self.z = Fp(1)
        return self

# check if point-at-infinity

    def isinf(self):
        if curve.CurveType == WEIERSTRASS:
            if self.x.iszero() and self.z.iszero():
                return True
        if curve.CurveType == EDWARDS:
            if self.x.iszero() and self.y == self.z:
                return True
        if curve.CurveType == MONTGOMERY:
            if self.z.iszero():
                return True
        return False

# set to point-at-infinity

    def inf(self):
        self.x = Fp(0)
        self.y = Fp(1)
        if curve.CurveType == EDWARDS:
            self.z = Fp(1)
        else:
            self.z = Fp(0)
        return self

    def set(self, x, s=0):  # set point from x and LSB of y
        mx = Fp(x)
        rhs = RHS(mx)
        if rhs.qr() != 1:
            return False
        self.x = mx
        self.z = Fp(1)

        if curve.CurveType != MONTGOMERY:
            self.y = rhs.sqrt()
            if big.bit(self.y.int(), 0) != s:
                self.y = -self.y
        return True

    def setxy(self, x, y):
        mx = Fp(x)
        my = Fp(y)
        if my * my != RHS(mx):
            return False
        self.x = mx
        self.y = my
        self.z = Fp(1)
        return True

    def get(self):  # return tuple Fp x and Fp y
        W = self.copy()
        if W.isinf():
            return (0, 0)
        W.affine()
        if curve.CurveType == MONTGOMERY:
            return W.x.int()
        return (W.x.int(), W.y.int())

    def getxs(self):  # return tuple integer x and LSB of y
        W = self.copy()
        if W.isinf():
            return (0, 0)
        W.affine()
        if curve.CurveType == MONTGOMERY:
            return (W.x.int(), 0)
        return (W.x.int(), big.bit(W.y.int(), 0))

    def getx(self):  # return just integer x
        W = self.copy()
        if W.isinf():
            return 0
        W.affine()
        return W.x.int()

# Return as Fps

    def getxy(self):
        W = self.copy()
        if (W.isinf()):
            return (Fp(0), Fp(0))
        W.affine()
        if curve.CurveType == MONTGOMERY:
            return W.x.copy()
        return (W.x.copy(), W.y.copy())

    def __eq__(self, other):
        zs = self.z
        zo = other.z
        if self.x * zo != other.x * zs:
            return False
        if curve.CurveType != MONTGOMERY:
            if self.y * zo != other.y * zs:
                return False
        return True

    def __ne__(self, other):
        return not (self == other)

    def __neg__(self):
        s = self.copy()
        if not s.isinf():
            if curve.CurveType == WEIERSTRASS:
                s.y = -s.y
            if curve.CurveType == EDWARDS:
                s.x = -s.x
        return s

# use exception-free formulae

    def dbl(self):
        if curve.CurveType == WEIERSTRASS:
            if ECp.A.iszero():
                t0 = self.y.copy()
                t0 = t0 * t0
                t1 = self.y.copy()
                t1 = t1 * self.z
                t2 = self.z.copy()
                t2 = t2 * t2
                self.z = t0 + t0

                self.z += self.z
                self.z += self.z
                t2 *= (ECp.B + ECp.B + ECp.B)
                x3 = t2 * self.z
                y3 = t0 + t2
                self.z *= t1
                t1 = t2 + t2
                t2 += t1
                t0 -= t2
                y3 *= t0
                y3 += x3
                t1 = self.x * self.y
                self.x = t0
                self.x *= t1
                self.x += self.x
                self.y = y3
            else:
                t0 = self.x.copy()
                t1 = self.y.copy()
                t2 = self.z.copy()
                t3 = self.x.copy()
                z3 = self.z.copy()
                #y3 = Fp(0)
                #x3 = Fp(0)
                b = ECp.B

                t0 *= t0
                t1 *= t1
                t2 *= t2

                t3 *= self.y
                t3 += t3

                z3 *= self.x
                z3 += z3

                y3 = t2 * b

                y3 -= z3
                x3 = y3 + y3

                y3 += x3
                x3 = t1 - y3
                y3 += t1
                y3 *= x3
                x3 *= t3
                t3 = t2 + t2
                t2 += t3
                z3 *= b

                z3 -= t2
                z3 -= t0
                t3 = z3 + z3

                z3 += t3
                t3 = t0 + t0
                t0 += t3
                t0 -= t2

                t0 *= z3
                y3 += t0
                t0 = self.y * self.z
                t0 += t0
                z3 *= t0
                x3 -= z3
                t0 += t0
                t1 += t1
                z3 = t0 * t1

                self.x = x3
                self.y = y3
                self.z = z3

        if curve.CurveType == EDWARDS:
            C = self.x.copy()
            D = self.y.copy()
            H = self.z.copy()
            #J = Fp(0)

            self.x *= self.y
            self.x += self.x
            C *= C
            D *= D

            if ECp.A == Fp(-1):
                C = -C

            self.y = C + D
            H *= H
            H += H

            self.z = self.y.copy()
            J = self.y.copy()

            J -= H
            self.x *= J

            C -= D
            self.y *= C
            self.z *= J

        if curve.CurveType == MONTGOMERY:
            A = self.x.copy()
            B = self.x.copy()
            #AA = Fp(0)
            #BB = Fp(0)
            #C = Fp(0)

            A += self.z
            AA = A * A
            B -= self.z
            BB = B * B
            #C = AA
            C = AA - BB
            self.x = AA * BB

            A = C * ((ECp.A + Fp(2)).div2().div2())

            BB += A
            self.z = BB * C

        return self

    def add(self, other):
        if curve.CurveType == WEIERSTRASS:
            if ECp.A.iszero():
                b = (ECp.B + ECp.B + ECp.B)
                t0 = self.x.copy()
                t0 *= other.x
                t1 = self.y.copy()
                t1 *= other.y
                t2 = self.z.copy()
                t2 = t2 * other.z
                t3 = self.x.copy()
                t3 += self.y
                t4 = other.x + other.y
                t3 *= t4
                t4 = t0 + t1

                t3 -= t4
                t4 = self.y + self.z
                x3 = other.y + other.z

                t4 *= x3
                x3 = t1 + t2

                t4 -= x3
                x3 = self.x + self.z
                y3 = other.x + other.z
                x3 *= y3
                y3 = t0 + t2
                y3 = x3 - y3
                x3 = t0 + t0
                t0 += x3
                t2 *= b

                z3 = t1 + t2
                t1 -= t2
                y3 *= b

                x3 = y3 * t4
                t2 = t3 * t1
                x3 = t2 - x3
                y3 *= t0
                t1 *= z3
                y3 += t1
                t0 *= t3
                z3 *= t4
                z3 += t0

                self.x = x3
                self.y = y3
                self.z = z3

            else:

                t0 = self.x.copy()
                t1 = self.y.copy()
                t2 = self.z.copy()
                t3 = self.x.copy()
                t4 = other.x.copy()
                #z3 = Fp(0)
                y3 = other.x.copy()
                x3 = other.y.copy()
                b = ECp.B

                t0 *= other.x
                t1 *= other.y
                t2 *= other.z

                t3 += self.y
                t4 += other.y
                t3 *= t4
                t4 = t0 + t1
                t3 -= t4

                t4 = self.y + self.z
                x3 += other.z
                t4 *= x3
                x3 = t1 + t2

                t4 -= x3
                x3 = self.x + self.z
                y3 += other.z

                x3 *= y3
                y3 = t0 + t2

                y3 = x3 - y3
                z3 = t2 * b

                x3 = y3 - z3
                z3 = x3 + x3

                x3 += z3
                z3 = t1 - x3
                x3 += t1

                y3 *= b

                t1 = t2 + t2
                t2 += t1

                y3 -= t2

                y3 -= t0
                t1 = y3 + y3
                y3 += t1

                t1 = t0 + t0
                t0 += t1
                t0 -= t2
                t1 = t4 * y3
                t2 = t0 * y3
                y3 = x3 * z3
                y3 += t2
                x3 *= t3
                x3 -= t1
                z3 *= t4
                t1 = t3 * t0
                z3 += t1
                self.x = x3
                self.y = y3
                self.z = z3

        if curve.CurveType == EDWARDS:
            A = self.z.copy()
            #B = Fp(0)
            C = self.x.copy()
            D = self.y.copy()
            #E = Fp(0)
            #F = Fp(0)
            #G = Fp(0)
            b = ECp.B

            # print(self.z.int())

            A *= (other.z)
            B = A * A
            C *= (other.x)
            D *= (other.y)
            # print(other.z.int())
            E = C * D
            E *= b

            F = B - E
            G = B + E

            if (ECp.A == Fp(1)):
                E = D - C

            C += D

            B = self.x + self.y
            D = other.x + other.y
            B *= D
            B -= C
            B *= F
            self.x = A * B

            if ECp.A == Fp(1):
                C = E * G
            if ECp.A == Fp(-1):
                C *= G

            self.y = A * C

            self.z = F
            self.z *= G

        return self

# For Montgomery use only

    def dadd(self, Q, W):
        A = self.x.copy()
        B = self.x.copy()
        C = Q.x.copy()
        D = Q.x.copy()
        #DA = Fp(0)
        #CB = Fp(0)

        A += self.z
        B -= self.z

        C += Q.z
        D -= Q.z

        DA = D * A

        CB = C * B

        A = DA + CB
        A *= A
        B = DA - CB
        B *= B

        self.x = A
        self.z = W.x * B

        return self

    def __rmul__(self, other):  # use NAF
        R = ECp()
        if curve.CurveType == MONTGOMERY:
            e = other
            #D = ECp()
            R0 = self.copy()
            R1 = self.copy()
            R1.dbl()

            D = self.copy()
            nb = e.bit_length()
            # nb=curve.r.bit_length()
            for i in range(nb - 2, -1, -1):
                b = big.bit(e, i)
                R = R1.copy()

                R.dadd(R0, D)
                if b == 1:
                    R0, R1 = R1, R0
                R1 = R.copy()
                R0.dbl()
                if b == 1:
                    R0, R1 = R1, R0
            R = R0.copy()

        else:
            b = other
            b3 = 3 * b
            k = b3.bit_length()
            # k=curve.r.bit_length()+2;

            mself = -self
            for i in range(k - 1, 0, -1):
                R.dbl()
                if big.bit(b3, i) == 1 and big.bit(b, i) == 0:
                    R.add(self)
                if big.bit(b3, i) == 0 and big.bit(b, i) == 1:
                    R.add(mself)
        return R

    def __str__(self):  # pretty print
        W = self.copy()
        if W.isinf():
            return "infinity"
        W.affine()
        if curve.CurveType == MONTGOMERY:
            return "(%x)" % (W.x.int())
        return "(%x,%x)" % (W.x.int(), W.y.int())

# convert from and to an array of bytes

    def fromBytes(self, W):
        if curve.CurveType == MONTGOMERY:
            x = big.from_bytes(W[0:curve.EFS])
            return self.set(x)

        t = W[0]  # ord(W[0])
        sp1 = curve.EFS + 1  # splits
        sp2 = sp1 + curve.EFS

        x = big.from_bytes(W[1:sp1])
        if t == 4:
            y = big.from_bytes(W[sp1:sp2])
            return self.setxy(x, y)
        else:
            if t == 2:
                return self.set(x, 0)
            if t == 3:
                return self.set(x, 1)
        self.inf()
        return False


# Can be compressed to just x

    def toBytes(self, compress):
        FS = curve.EFS
        if curve.CurveType == MONTGOMERY:
            PK = bytearray(FS)
            #PK[0] = 6
            x = self.get()
            W = big.to_bytes(x)
            for i in range(0, FS):
                PK[i] = W[i]
            return PK
        if compress:
            PK = bytearray(FS + 1)
            x, b = self.getxs()
            if b == 0:
                PK[0] = 2
            else:
                PK[0] = 3
            W = big.to_bytes(x)
            for i in range(0, FS):
                PK[1 + i] = W[i]
        else:
            PK = bytearray(2 * FS + 1)
            x, y = self.get()
            PK[0] = 4
            W = big.to_bytes(x)
            for i in range(0, FS):
                PK[1 + i] = W[i]
            W = big.to_bytes(y)
            for i in range(0, FS):
                PK[1 + i + FS] = W[i]

        return PK
Exemple #3
0
class Fp2:

    def __init__(self, a=None, b=None):
        if b is None:
            if a is None:
                self.a = Fp(0)
                self.b = Fp(0)
            else:
                self.a = a.copy()
                self.b = Fp(0)
        else:
            self.a = a.copy()
            self.b = b.copy()

    def copy(self):
        return copy.deepcopy(self)

    def get(self):
        return(self.a.int(), self.b.int())

    def set(self, a, b):
        self.a = Fp(a)
        self.b = Fp(b)
        return self

    def __add__(self, other):
        return Fp2(self.a + other.a, self.b + other.b)

    def __iadd__(self, other):
        self.a += other.a
        self.b += other.b
        return self

    def __sub__(self, other):
        return Fp2(self.a - other.a, self.b - other.b)

    def __isub__(self, other):
        self.a -= other.a
        self.b -= other.b
        return self

    def __eq__(self, other):
        return (self.a == other.a and self.b == other.b)

    def __ne__(self, other):
        return (self.a != other.a or self.b != other.b)

    def conj(self):
        return Fp2(self.a, -self.b)

    def sqr(self):
        newa = (self.a + self.b) * (self.a - self.b)
        self.b *= self.a
        self.b += self.b
        self.a = newa.copy()
        return self

    def times_i(self):
        return Fp2(-self.b,self.a)

    def __imul__(self, other):
        t1 = self.a * other.a
        t2 = self.b * other.b
        t3 = other.a + other.b
        self.b += self.a
        self.b *= t3
        self.b -= t1
        self.b -= t2
        self.a = t1 - t2
        return self

    def __mul__(self, other):
        R = self.copy()
        if R == other:
            R.sqr()
        else:
            R *= other
        return R

    def muli(self, other):
        return Fp2(self.a.muli(other), self.b.muli(other))

    def muls(self, other):
        return Fp2(self.a * other, self.b * other)

    def __neg__(self):
        return Fp2(-self.a, -self.b)

    def sign(self):
        p1=self.a.int()&1
        p2=self.b.int()&1
        u=1 if self.a.iszero() else 0
        p1^=(p1^p2)&u
        return p1

    def real(self):
        return self.a

    def imaginary(self):
        return self.b

    def iszero(self):
        if self.a.iszero() and self.b.iszero():
            return True
        return False

    def isone(self):
        if self.a.isone() and self.b.iszero():
            return True
        return False

    def rand(self):
        r = Fp()
        r.rand()
        self.a = r.copy()
        r.rand()
        self.b = r.copy()
        return self

    def __str__(self):			# pretty print
        return "[%x,%x]" % (self.a.int(), self.b.int())

    def mulQNR(self):				# assume QNR=2^i+sqrt(-1)
        return (self.times_i()+self.muli(1<<curve.QNRI))

    def inverse(self):
        w = self.conj()
        c = self.a * self.a + self.b * self.b
        c = c.inverse()
        w.a *= c
        w.b *= c
        return w

    def div2(self):
        newa = self.a.div2()
        newb = self.b.div2()
        return Fp2(newa, newb)

    def divQNR(self):				# assume QNR=2^i+sqrt(-1)
        z = Fp2(Fp(1<<curve.QNRI),Fp(1))
        return self*z.inverse()

    def pow(self, other):
        z=other
        r=Fp2(Fp(1))
        w=self.copy()
        while True :
            bt=z&1
            z >>= 1
            if bt == 1: 
                r *= w
            if z == 0 :
                break
            w.sqr()
        return r.copy()
    
    def qr(self):
        w=self.conj()
        w *= self
        return Fp.qr(w.a)

    def sqrt(self):
        w1=self.b.copy()
        w2=self.a.copy()
        w1 *= w1
        w2 *= w2
        w1 += w2
        w1=w1.sqrt()
        w2=self.a.copy()
        w2 += w1
        w2 = w2.div2()
        if w2.qr() != 1 :
            w2=self.a.copy()
            w2 -= w1
            w2 = w2.div2()
        w2=w2.sqrt()
        self.a = w2.copy()
        w2 += w2
        w2 = w2.inverse()
        self.b *= w2