+
+ +

Elliptic Curve Cryptography

+ + +
+ + + + +
+ + + + + + + + + + +
+ + + + + + + + + +
+ + + +

+ Elliptic + + +

+ + +
+ + + +

This class generate a group for Elliptic Curve +An Elliptic Curve is a algebraic group from the Group theory branch.

+

An Elliptic Curve is a set of points from this equation (Weierstrass equations): $y2 = x3 + ax + b$

+

To generate points of $E(F_p)$, first, we need to generate all square modulos +The, for all X, we increment it until $X < n$ and if exist a square modulos +It's a point of the list $E(F_p)$

+ + + + + + + + + + + + + +
Attributes: +
    +
  • + n + (Integer) + – +
    +

    It's the modulo

    +
    +
  • +
  • + a + (Integer) + – +
    + +
    +
  • +
  • + b + (Integer) + – +
    + +
    +
  • +
  • + squares + (Dict) + – +
    +

    Dictionary which contain quadratic nonresidue. The key is the quadratic nonresidue and for each entry, we have a list of point for the quadratic nonresidue

    +
    +
  • +
  • + E + (List) + – +
    +

    List of all Points

    +
    +
  • +
  • + order + (Int) + – +
    +

    Order (length) of the group

    +
    +
  • +
+
+ + + + + + +
+ Source code in Cryptotools/Groups/elliptic.py +
  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
class Elliptic:
+    """
+        This class generate a group for Elliptic Curve
+        An Elliptic Curve is a algebraic group from the Group theory branch.
+
+        An Elliptic Curve is a set of points from this equation (Weierstrass equations): $y2 = x3 + ax + b$
+
+
+        To generate points of $E(F_p)$, first, we need to generate all square modulos
+        The, for all X, we increment it until $X < n$ and if exist a square modulos
+        It's a point of the list $E(F_p)$
+
+        Attributes:
+            n (Integer): It's the modulo
+            a (Integer): 
+            b (Integer): 
+            squares (Dict): Dictionary which contain quadratic nonresidue. The key is the quadratic nonresidue and for each entry, we have a list of point for the quadratic nonresidue
+            E (List): List of all Points
+            order (Int): Order (length) of the group
+    """
+    def __init__(self, n, a, b):
+        self._n = n
+        self._a = a
+        self._b = b
+
+        self._squares = dict()
+        self._E = list()
+        self._order = 0
+
+    def quadraticResidues(self):
+        """
+            This function generate all quadratic modulo of n.
+            A quadratic: if exist and satisfy $x^2 \equiv q mod n$, means it's a square modulo n and q is quadratic nonresidue modulo n
+            https://en.wikipedia.org/wiki/Quadratic_residue
+
+            For instance, n = 13, q = 9
+            For all x belongs to n
+                for x in n:
+                    if x ** 2 % n == q:
+                        print(x, q)
+        """
+        for q in range(self._n):
+            x2 = pow(q, 2) % self._n
+            if x2 not in self._squares:
+                self._squares[x2] = list()
+            self._squares[x2].append(q)
+
+    def getQuadraticResidues(self) -> dict:
+        """
+            This function return the dict contains all squares modulo of n
+
+            Returns:
+                Return a dictionary of squares modulo
+        """
+        return self._squares
+
+    def pointsE(self):
+        """
+            This function generate all points for $E(F_p)$. Each entry in the list contain another list of two entries: x and y
+
+            Returns:
+                Return the list of points of E(F_p)
+        """
+        self._E.append(Point(0, 0))
+        for x in range(self._n):
+            y = (pow(x, 3) + (x * self._a) + self._b) % self._n
+
+            # If not quadratic residue, no point in the curve
+            # and x not produce a point in the curve
+            if y in self._squares:
+                for e in self._squares[y]:
+                    self._E.append(Point(x, e))
+        return self._E
+
+    def additionTable(self):
+        raise NotImplementedError
+
+    def _slope(self):
+        raise NotImplementedError
+
+    def _curves(self):
+        self._curves = dict()
+        self._curves["weierstrass"] = weierstrass
+        self._curves["curve25519"] = curve25519
+        self._curves["curve448"] = curve448
+
+    def weierstrass(self, x):
+        raise NotImplementedError
+
+    def curve448(self, x):
+        raise NotImplementedError
+
+    def curve25519(self, x):
+        """
+            This function generate a curve based on the Montgomery's curve.
+            Using that formula: y2 = x^3 + 486662\times x^2 + x
+        """
+        y = pow(x, 3) + 486662 * pow(x, 2) + x
+        if y > 0:
+            return sqrt(y)
+        else:
+            return 0
+
+    def add(self, P, Q) -> Point:
+        """
+            This function operathe addition operation on two points P and Q
+
+            Args:
+                P (Object): The first Point on the curve
+                Q (Object): The second Point on the curve
+
+            Returns:
+                Return the Point object R
+        """
+
+        ## Check if P or Q are infinity
+        if (P.x, P.y) == (0, 0) and (Q.x, Q.y) == (0, 0):
+            return Point(0, 0)
+        elif (P.x, P.y) == (0, 0):
+            return Point(Q.x, Q.y)
+        elif (Q.x, Q.y) == (0, 0):
+            return Point(P.x, P.y)
+
+        # point doubling
+        if P.x == Q.x:
+            # Infinity
+            if P.y != Q.y or Q.y == 0:
+                return Point(0, 0)
+
+            # Point doubling
+            try:
+                inv = pow(2 * P.y, -1, self._n); # It's working with the inverse modular, WHY ???
+                m = ((3 * pow(P.x, 2)) + self._a) * inv % self._n
+            except ValueError:
+                return Point(0, 0)
+
+        else:
+            try:
+                inv = pow(Q.x - P.x, -1, self._n)
+                m = ((Q.y - P.y) * inv) % self._n
+            except ValueError:
+                # May call this Exception: base is not invertible for the given modulus
+                # I return an Infinity point until I fixed that
+                return Point(0, 0)
+
+        xr = int((pow(m, 2) - P.x - Q.x)) % self._n
+
+        yr = int((m * (P.x - xr)) - P.y) % self._n
+        return Point(xr, yr)
+
+    def scalar(self, P, n) -> Point:
+        """
+            This function compute a Scalar Multiplication of P, n time. This algorithm is also known as Double and Add.
+
+            Args:
+                P (point): the Point to multiplication
+                n (Integer): multiplicate n time P
+
+            Returns:
+                Return the result of the Scalar multiplication
+        """
+        binary = bin(n)[2:]
+        binary = binary[::-1] # We need to reverse the binary
+
+        nP = Point(0, 0)
+        Rtmp = P
+
+        for b in binary:
+            if b == '1':
+                nP = self.add(nP, Rtmp)
+            Rtmp = self.add(Rtmp, Rtmp)  # Double P
+
+        return nP
+
+    def pointExist(self, P) -> bool:
+        """
+            This function determine if the Point P(x, y) exist in the Curve
+            To identify if a point P (x, y) lies on the curve
+            We need to compute y ** 2 mod n
+            Then, we compute x ** 3 + ax + b mod n
+            If both are equal, the point exist, otherwise not
+
+            Args:
+                P (Point): The point to check if exist in the curve
+
+            Returns:
+                Return True if lies on the curve otherwise it's False
+        """
+        y2 = pow(P.y, 2) % self._n
+        x3 = (pow(P.x, 3) + (self._a * P.x) + self._b) % self._n
+        if y2 == x3:
+            return True
+
+        return False
+
+    def findOrder(self) -> int:
+        """
+            This function find the order of the Curve over Fp
+
+            Returns:
+                Return the order of the Curve
+        """
+        l = list()
+        l.append(Point(0, 0))
+
+        # It's the same of the function pointsE
+        for x in range(self._n):
+            r = (pow(x, 3) + (self._a * x) + self._b) % self._n
+            if r in self._squares:
+                for s in self._squares[r]:
+                    P = Point(x, s)
+                    l.append(P)
+
+        self._order = len(l)
+        return self._order
+
+    @property
+    def order(self) -> int:
+        """
+            This function return the order of the Group
+        """
+        return self._order
+
+    @property
+    def cofactor(self) -> int:
+        """
+            This function return the cofactor. A cofactor describe the relation between the number of points and the group.
+            It's based on the Lagrange's theorem.
+        """
+        if self._order == 0:
+            raise ValueError("You must generate the order of the group")
+        return self._order / self._n
+
+
+ + + +
+ + + + + + + +
+ + + +

+ cofactor + + + property + + +

+ + +
+ +

This function return the cofactor. A cofactor describe the relation between the number of points and the group. +It's based on the Lagrange's theorem.

+ +
+ +
+ +
+ + + +

+ order + + + property + + +

+ + +
+ +

This function return the order of the Group

+ +
+ +
+ + + + +
+ + +

+ add(P, Q) + +

+ + +
+ +

This function operathe addition operation on two points P and Q

+ + + + + + + + + + + + + +
Parameters: +
    +
  • + P + (Object) + – +
    +

    The first Point on the curve

    +
    +
  • +
  • + Q + (Object) + – +
    +

    The second Point on the curve

    +
    +
  • +
+
+ + + + + + + + + + + + +
Returns: +
    +
  • + Point + – +
    +

    Return the Point object R

    +
    +
  • +
+
+ +
+ Source code in Cryptotools/Groups/elliptic.py +
111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
def add(self, P, Q) -> Point:
+    """
+        This function operathe addition operation on two points P and Q
+
+        Args:
+            P (Object): The first Point on the curve
+            Q (Object): The second Point on the curve
+
+        Returns:
+            Return the Point object R
+    """
+
+    ## Check if P or Q are infinity
+    if (P.x, P.y) == (0, 0) and (Q.x, Q.y) == (0, 0):
+        return Point(0, 0)
+    elif (P.x, P.y) == (0, 0):
+        return Point(Q.x, Q.y)
+    elif (Q.x, Q.y) == (0, 0):
+        return Point(P.x, P.y)
+
+    # point doubling
+    if P.x == Q.x:
+        # Infinity
+        if P.y != Q.y or Q.y == 0:
+            return Point(0, 0)
+
+        # Point doubling
+        try:
+            inv = pow(2 * P.y, -1, self._n); # It's working with the inverse modular, WHY ???
+            m = ((3 * pow(P.x, 2)) + self._a) * inv % self._n
+        except ValueError:
+            return Point(0, 0)
+
+    else:
+        try:
+            inv = pow(Q.x - P.x, -1, self._n)
+            m = ((Q.y - P.y) * inv) % self._n
+        except ValueError:
+            # May call this Exception: base is not invertible for the given modulus
+            # I return an Infinity point until I fixed that
+            return Point(0, 0)
+
+    xr = int((pow(m, 2) - P.x - Q.x)) % self._n
+
+    yr = int((m * (P.x - xr)) - P.y) % self._n
+    return Point(xr, yr)
+
+
+
+ +
+ +
+ + +

+ curve25519(x) + +

+ + +
+ +

This function generate a curve based on the Montgomery's curve. +Using that formula: y2 = x^3 + 486662 imes x^2 + x

+ + +
+ Source code in Cryptotools/Groups/elliptic.py +
100
+101
+102
+103
+104
+105
+106
+107
+108
+109
def curve25519(self, x):
+    """
+        This function generate a curve based on the Montgomery's curve.
+        Using that formula: y2 = x^3 + 486662\times x^2 + x
+    """
+    y = pow(x, 3) + 486662 * pow(x, 2) + x
+    if y > 0:
+        return sqrt(y)
+    else:
+        return 0
+
+
+
+ +
+ +
+ + +

+ findOrder() + +

+ + +
+ +

This function find the order of the Curve over Fp

+ + + + + + + + + + + + + +
Returns: +
    +
  • + int + – +
    +

    Return the order of the Curve

    +
    +
  • +
+
+ +
+ Source code in Cryptotools/Groups/elliptic.py +
203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
def findOrder(self) -> int:
+    """
+        This function find the order of the Curve over Fp
+
+        Returns:
+            Return the order of the Curve
+    """
+    l = list()
+    l.append(Point(0, 0))
+
+    # It's the same of the function pointsE
+    for x in range(self._n):
+        r = (pow(x, 3) + (self._a * x) + self._b) % self._n
+        if r in self._squares:
+            for s in self._squares[r]:
+                P = Point(x, s)
+                l.append(P)
+
+    self._order = len(l)
+    return self._order
+
+
+
+ +
+ +
+ + +

+ getQuadraticResidues() + +

+ + +
+ +

This function return the dict contains all squares modulo of n

+ + + + + + + + + + + + + +
Returns: +
    +
  • + dict + – +
    +

    Return a dictionary of squares modulo

    +
    +
  • +
+
+ +
+ Source code in Cryptotools/Groups/elliptic.py +
55
+56
+57
+58
+59
+60
+61
+62
def getQuadraticResidues(self) -> dict:
+    """
+        This function return the dict contains all squares modulo of n
+
+        Returns:
+            Return a dictionary of squares modulo
+    """
+    return self._squares
+
+
+
+ +
+ +
+ + +

+ pointExist(P) + +

+ + +
+ +

This function determine if the Point P(x, y) exist in the Curve +To identify if a point P (x, y) lies on the curve +We need to compute y ** 2 mod n +Then, we compute x ** 3 + ax + b mod n +If both are equal, the point exist, otherwise not

+ + + + + + + + + + + + + +
Parameters: +
    +
  • + P + (Point) + – +
    +

    The point to check if exist in the curve

    +
    +
  • +
+
+ + + + + + + + + + + + +
Returns: +
    +
  • + bool + – +
    +

    Return True if lies on the curve otherwise it's False

    +
    +
  • +
+
+ +
+ Source code in Cryptotools/Groups/elliptic.py +
182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
def pointExist(self, P) -> bool:
+    """
+        This function determine if the Point P(x, y) exist in the Curve
+        To identify if a point P (x, y) lies on the curve
+        We need to compute y ** 2 mod n
+        Then, we compute x ** 3 + ax + b mod n
+        If both are equal, the point exist, otherwise not
+
+        Args:
+            P (Point): The point to check if exist in the curve
+
+        Returns:
+            Return True if lies on the curve otherwise it's False
+    """
+    y2 = pow(P.y, 2) % self._n
+    x3 = (pow(P.x, 3) + (self._a * P.x) + self._b) % self._n
+    if y2 == x3:
+        return True
+
+    return False
+
+
+
+ +
+ +
+ + +

+ pointsE() + +

+ + +
+ +

This function generate all points for $E(F_p)$. Each entry in the list contain another list of two entries: x and y

+ + + + + + + + + + + + + +
Returns: +
    +
  • + – +
    +

    Return the list of points of E(F_p)

    +
    +
  • +
+
+ +
+ Source code in Cryptotools/Groups/elliptic.py +
64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
def pointsE(self):
+    """
+        This function generate all points for $E(F_p)$. Each entry in the list contain another list of two entries: x and y
+
+        Returns:
+            Return the list of points of E(F_p)
+    """
+    self._E.append(Point(0, 0))
+    for x in range(self._n):
+        y = (pow(x, 3) + (x * self._a) + self._b) % self._n
+
+        # If not quadratic residue, no point in the curve
+        # and x not produce a point in the curve
+        if y in self._squares:
+            for e in self._squares[y]:
+                self._E.append(Point(x, e))
+    return self._E
+
+
+
+ +
+ +
+ + +

+ quadraticResidues() + +

+ + +
+ +

This function generate all quadratic modulo of n. +A quadratic: if exist and satisfy $x^2 \equiv q mod n$, means it's a square modulo n and q is quadratic nonresidue modulo n +https://en.wikipedia.org/wiki/Quadratic_residue

+

For instance, n = 13, q = 9 +For all x belongs to n + for x in n: + if x ** 2 % n == q: + print(x, q)

+ + +
+ Source code in Cryptotools/Groups/elliptic.py +
37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
def quadraticResidues(self):
+    """
+        This function generate all quadratic modulo of n.
+        A quadratic: if exist and satisfy $x^2 \equiv q mod n$, means it's a square modulo n and q is quadratic nonresidue modulo n
+        https://en.wikipedia.org/wiki/Quadratic_residue
+
+        For instance, n = 13, q = 9
+        For all x belongs to n
+            for x in n:
+                if x ** 2 % n == q:
+                    print(x, q)
+    """
+    for q in range(self._n):
+        x2 = pow(q, 2) % self._n
+        if x2 not in self._squares:
+            self._squares[x2] = list()
+        self._squares[x2].append(q)
+
+
+
+ +
+ +
+ + +

+ scalar(P, n) + +

+ + +
+ +

This function compute a Scalar Multiplication of P, n time. This algorithm is also known as Double and Add.

+ + + + + + + + + + + + + +
Parameters: +
    +
  • + P + (point) + – +
    +

    the Point to multiplication

    +
    +
  • +
  • + n + (Integer) + – +
    +

    multiplicate n time P

    +
    +
  • +
+
+ + + + + + + + + + + + +
Returns: +
    +
  • + Point + – +
    +

    Return the result of the Scalar multiplication

    +
    +
  • +
+
+ +
+ Source code in Cryptotools/Groups/elliptic.py +
158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
def scalar(self, P, n) -> Point:
+    """
+        This function compute a Scalar Multiplication of P, n time. This algorithm is also known as Double and Add.
+
+        Args:
+            P (point): the Point to multiplication
+            n (Integer): multiplicate n time P
+
+        Returns:
+            Return the result of the Scalar multiplication
+    """
+    binary = bin(n)[2:]
+    binary = binary[::-1] # We need to reverse the binary
+
+    nP = Point(0, 0)
+    Rtmp = P
+
+    for b in binary:
+        if b == '1':
+            nP = self.add(nP, Rtmp)
+        Rtmp = self.add(Rtmp, Rtmp)  # Double P
+
+    return nP
+
+
+
+ +
+ + + +
+ +
+ + +
+ + + + +
+ +
+ +
+ +
+