Add Elliptic Curve Cryptography
This commit is contained in:
parent
be5f872019
commit
16efeaec2d
240
Cryptotools/Groups/elliptic.py
Normal file
240
Cryptotools/Groups/elliptic.py
Normal file
@ -0,0 +1,240 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
from Cryptotools.Groups.point import Point
|
||||||
|
from math import sqrt
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
33
examples/elliptic/ecc.py
Normal file
33
examples/elliptic/ecc.py
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
from Cryptotools.Groups.elliptic import Point, Elliptic
|
||||||
|
|
||||||
|
|
||||||
|
a = 3
|
||||||
|
b = 8
|
||||||
|
n = 89 # Must be prime number
|
||||||
|
|
||||||
|
E = Elliptic(n, a, b)
|
||||||
|
E.quadraticResidues()
|
||||||
|
Ep = E.pointsE()
|
||||||
|
#print(E.getQuadraticResidues())
|
||||||
|
|
||||||
|
# For the graphic
|
||||||
|
MAX=n
|
||||||
|
|
||||||
|
fig, ax = plt.subplots()
|
||||||
|
ax.legend(fontsize=14)
|
||||||
|
ax.grid()
|
||||||
|
|
||||||
|
# We generate x for the graphic
|
||||||
|
x = list()
|
||||||
|
x = [i for i in range(0, MAX)]
|
||||||
|
|
||||||
|
# Drawing the point.
|
||||||
|
for p in Ep:
|
||||||
|
ax.plot(p.x, p.y, 'bo')
|
||||||
|
|
||||||
|
# Draw a line for the symmetry
|
||||||
|
plt.axline([0, 45], [45, 45], linestyle="--", color="red")
|
||||||
|
plt.show()
|
||||||
65
examples/elliptic/ecc_generator.py
Normal file
65
examples/elliptic/ecc_generator.py
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
from Cryptotools.Groups.elliptic import Elliptic
|
||||||
|
from Cryptotools.Groups.point import Point
|
||||||
|
|
||||||
|
# https://course.ece.cmu.edu/~ece733/lectures/21-intro-ecc.pdf
|
||||||
|
|
||||||
|
|
||||||
|
a = 3
|
||||||
|
b = 7
|
||||||
|
n = 53 # Must be prime number
|
||||||
|
|
||||||
|
E = Elliptic(n, a, b)
|
||||||
|
E.quadraticResidues()
|
||||||
|
Ep = E.pointsE()
|
||||||
|
#print(E.getQuadraticResidues())
|
||||||
|
|
||||||
|
# Now, we can make the Addition Table
|
||||||
|
#for p in Ep:
|
||||||
|
# for q in Ep:
|
||||||
|
# nP = E.add(p, q)
|
||||||
|
# print(f"({p.x}, {p.y}), ({q.x}, {q.y}) {nP.x, nP.y}")
|
||||||
|
# print()
|
||||||
|
#
|
||||||
|
#print()
|
||||||
|
|
||||||
|
# In cryptography, where is the public key and where is the private key on the elliptic curve ???
|
||||||
|
# For the graphic
|
||||||
|
MAX=n
|
||||||
|
|
||||||
|
fig, ax = plt.subplots()
|
||||||
|
ax.legend(fontsize=14)
|
||||||
|
ax.grid()
|
||||||
|
|
||||||
|
# We generate x for the graphic
|
||||||
|
x = list()
|
||||||
|
x = [i for i in range(0, MAX)]
|
||||||
|
|
||||||
|
# Drawing the point.
|
||||||
|
for p in Ep:
|
||||||
|
ax.plot(p.x, p.y, 'bo')
|
||||||
|
|
||||||
|
# Find the order of the Curve
|
||||||
|
order = E.findOrder()
|
||||||
|
cofactor = E.cofactor
|
||||||
|
print(f"Order: {order}")
|
||||||
|
print(f"Cofactor: {cofactor}")
|
||||||
|
|
||||||
|
# Lets make an example, here, G is the first element of all points (except the point at infinity)
|
||||||
|
G = Ep[1]
|
||||||
|
|
||||||
|
for i in range(1, 15):
|
||||||
|
P = E.scalar(G, i)
|
||||||
|
|
||||||
|
plt.plot(P.x, P.y, marker='o', color="red")
|
||||||
|
plt.annotate(f'P{i}', (P.x, P.y + 0.5))
|
||||||
|
|
||||||
|
# Check if the point exist in the curve
|
||||||
|
if E.pointExist(P):
|
||||||
|
print(f"The point P ({P.x}, {P.y}) lies on the Curve")
|
||||||
|
else:
|
||||||
|
print(f"The point P ({P.x}, {P.y}) doesn't lies on the Curve")
|
||||||
|
|
||||||
|
plt.show()
|
||||||
307
examples/elliptic/ecdlp.py
Normal file
307
examples/elliptic/ecdlp.py
Normal file
@ -0,0 +1,307 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
from math import sqrt
|
||||||
|
from Cryptotools.Groups.point import Point
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
# https://course.ece.cmu.edu/~ece733/lectures/21-intro-ecc.pdf
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
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)
|
||||||
|
print(self._squares)
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
# Why quadratic residues ????
|
||||||
|
# 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))
|
||||||
|
# print(y, x, e)
|
||||||
|
# print(self._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
|
||||||
|
# print(binary)
|
||||||
|
|
||||||
|
for b in binary:
|
||||||
|
if b == '1':
|
||||||
|
nP = self.add(nP, Rtmp)
|
||||||
|
# print(b, nP.x, nP.y)
|
||||||
|
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) % n
|
||||||
|
# print(y2)
|
||||||
|
x3 = (pow(P.x, 3) + (a * P.x) + b) % n
|
||||||
|
# print(x3)
|
||||||
|
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
|
||||||
|
|
||||||
|
a = 3
|
||||||
|
b = 7
|
||||||
|
n = 97
|
||||||
|
|
||||||
|
E = Elliptic(n, a, b)
|
||||||
|
E.quadraticResidues()
|
||||||
|
Ep = E.pointsE()
|
||||||
|
|
||||||
|
# In cryptography, where is the public key and where is the private key on the elliptic curve ???
|
||||||
|
|
||||||
|
# Need to generate public/private key
|
||||||
|
## - First, we need to generate the private key.
|
||||||
|
## This key must be a random value between d = {1, n - 1}
|
||||||
|
## - Second, for the public key Q, we need to compute Q = d * G
|
||||||
|
## - d a random value; Q = {x, y}
|
||||||
|
##
|
||||||
|
## For encrypting,
|
||||||
|
|
||||||
|
G = Ep[1]
|
||||||
|
privkey = 48
|
||||||
|
pubkey = E.scalar(G, privkey)
|
||||||
|
if not E.pointExist(pubkey):
|
||||||
|
raise ValueError("The public key is not in the Curve")
|
||||||
|
|
||||||
|
print(f"Private key: {privkey}")
|
||||||
|
print(f"Public key: ({pubkey.x}, {pubkey.y})")
|
||||||
|
|
||||||
|
from math import log
|
||||||
|
|
||||||
|
# For testing
|
||||||
|
def test():
|
||||||
|
g = 4
|
||||||
|
k = 6
|
||||||
|
print(g ** k)
|
||||||
|
r = 1
|
||||||
|
for _ in range(k):
|
||||||
|
r *= g
|
||||||
|
print(r)
|
||||||
|
# DLP
|
||||||
|
print(log(r, g)) # = 6, we resolved the DLP
|
||||||
|
|
||||||
|
#test()
|
||||||
|
|
||||||
|
# We can brute-force until we found Q
|
||||||
|
# We know the poing G, because it's in the domain parameters and it's public
|
||||||
|
# Same for the public key, Q which is public
|
||||||
|
# And we know the prime number
|
||||||
|
# Need to find the private key, k
|
||||||
|
|
||||||
|
# Here, we brute force until we match with the public key
|
||||||
|
for x in range(n):
|
||||||
|
Q = E.scalar(G, x)
|
||||||
|
if Q.x == pubkey.x and Q.y == pubkey.y:
|
||||||
|
print(f"We found the private key {privkey}")
|
||||||
|
break
|
||||||
Loading…
Reference in New Issue
Block a user