-
Notifications
You must be signed in to change notification settings - Fork 85
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
212b193
commit a005da2
Showing
27 changed files
with
987 additions
and
1,940 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -56,6 +56,9 @@ chains | |
# tox/pytest cache | ||
.cache | ||
|
||
# mypy | ||
.mypy_cache/ | ||
|
||
# Test output logs | ||
logs | ||
### JetBrains template | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,291 @@ | ||
from abc import ( | ||
abstractmethod, | ||
) | ||
|
||
from typing import ( | ||
cast, | ||
) | ||
|
||
from py_ecc.field_elements import ( | ||
FQP, | ||
) | ||
|
||
from py_ecc.optimized_field_elements import ( | ||
FQP as optimized_FQP, | ||
) | ||
|
||
from py_ecc.new_typing import ( | ||
Field, | ||
GeneralPoint, | ||
Point2D, | ||
) | ||
from py_ecc.new_typing import ( | ||
Optimized_Field, | ||
Optimized_Point2D, | ||
Optimized_Point3D, | ||
) | ||
|
||
|
||
class BaseCurve: | ||
# Name of the curve can be "bn128" or "bls12_381" | ||
curve_name = None | ||
curve_order = None | ||
# Curve is y**2 = x**3 + b | ||
b = None | ||
# Twisted curve over FQ**2 | ||
b2 = None | ||
# Extension curve over FQ**12; same b value as over FQ | ||
b12 = None | ||
# Generator for curve over FQ | ||
G1 = None | ||
# Generator for twisted curve over FQ2 | ||
G2 = None | ||
# Generator for twisted curve over FQ12 | ||
G12 = None | ||
# Point at infinity over FQ | ||
Z1 = None | ||
# Point at infinity for twisted curve over FQ2 | ||
Z2 = None | ||
|
||
def __init__(self, curve_properties, curve_name): | ||
self.curve_name = curve_name | ||
self.curve_order = curve_properties[curve_name]["curve_order"] | ||
self.b = curve_properties[curve_name]["b"] | ||
self.b2 = curve_properties[curve_name]["b2"] | ||
self.b12 = curve_properties[curve_name]["b12"] | ||
self.G1 = curve_properties[curve_name]["G1"] | ||
self.G2 = curve_properties[curve_name]["G2"] | ||
self.G12 = self.twist(cast(Point2D[FQP], self.G2)) | ||
self.Z1 = curve_properties[curve_name]["Z1"] | ||
self.Z2 = curve_properties[curve_name]["Z2"] | ||
|
||
def is_inf(self, pt: GeneralPoint[Field]) -> bool: | ||
""" | ||
Check if a point is the point at infinity | ||
""" | ||
return pt is None | ||
|
||
def is_on_curve(self, pt: Point2D[Field], b: Field) -> bool: | ||
""" | ||
Check that a point is on the curve | ||
""" | ||
if self.is_inf(pt): | ||
return True | ||
x, y = pt | ||
return y**2 == x**3 + b | ||
|
||
def double(self, pt: Point2D[Field]) -> Point2D[Field]: | ||
""" | ||
Elliptic Curve Doubling (P+P). | ||
""" | ||
x, y = pt | ||
m = (3 * x**2) / (2 * y) | ||
newx = m**2 - 2 * x | ||
newy = -m * newx + m * x - y | ||
return (newx, newy) | ||
|
||
def add(self, | ||
p1: Point2D[Field], | ||
p2: Point2D[Field]) -> Point2D[Field]: | ||
""" | ||
Elliptic curve addition. | ||
""" | ||
if p1 is None or p2 is None: | ||
return p1 if p2 is None else p2 | ||
x1, y1 = p1 | ||
x2, y2 = p2 | ||
if x2 == x1 and y2 == y1: | ||
return self.double(p1) | ||
elif x2 == x1: | ||
return None | ||
else: | ||
m = (y2 - y1) / (x2 - x1) | ||
newx = m**2 - x1 - x2 | ||
newy = -m * newx + m * x1 - y1 | ||
assert newy == (-m * newx + m * x2 - y2) | ||
return (newx, newy) | ||
|
||
def multiply(self, pt: Point2D[Field], n: int) -> Point2D[Field]: | ||
""" | ||
Elliptic curve point multiplication. | ||
""" | ||
if n == 0: | ||
return None | ||
elif n == 1: | ||
return pt | ||
elif not n % 2: | ||
# print(n//2) | ||
return self.multiply(self.double(pt), n // 2) | ||
else: | ||
# print(n//2) | ||
return self.add(self.multiply(self.double(pt), n // 2), pt) | ||
|
||
def eq(self, p1: GeneralPoint[Field], p2: GeneralPoint[Field]) -> bool: | ||
""" | ||
Check if 2 points are equal. | ||
""" | ||
return p1 == p2 | ||
|
||
def neg(self, pt: Point2D[Field]) -> Point2D[Field]: | ||
""" | ||
Gives the reflection of point wrt x-axis (P => -P). | ||
""" | ||
if pt is None: | ||
return None | ||
x, y = pt | ||
return (x, -y) | ||
|
||
@abstractmethod | ||
def twist(self, pt: Point2D[FQP]) -> Point2D[FQP]: | ||
""" | ||
'Twist' a point in E(FQ2) into a point in E(FQ12) | ||
""" | ||
raise NotImplementedError("Must be implemented by subclasses") | ||
|
||
|
||
class BaseOptimizedCurve: | ||
# Name of the curve can be "bn128" or "bls12_381" | ||
curve_name = None | ||
curve_order = None | ||
# Curve is y**2 = x**3 + b | ||
b = None | ||
# Twisted curve over FQ**2 | ||
b2 = None | ||
# Extension curve over FQ**12; same b value as over FQ | ||
b12 = None | ||
# Generator for curve over FQ | ||
G1 = None | ||
# Generator for twisted curve over FQ2 | ||
G2 = None | ||
# Generator for curve over FQ12 | ||
G12 = None | ||
# Point at infinity over FQ | ||
Z1 = None | ||
# Point at infinity for twisted curve over FQ2 | ||
Z2 = None | ||
|
||
def __init__(self, curve_properties, curve_name): | ||
self.curve_name = curve_name | ||
self.curve_order = curve_properties[curve_name]["curve_order"] | ||
self.b = curve_properties[curve_name]["b"] | ||
self.b2 = curve_properties[curve_name]["b2"] | ||
self.b12 = curve_properties[curve_name]["b12"] | ||
self.G1 = curve_properties[curve_name]["G1"] | ||
self.G2 = curve_properties[curve_name]["G2"] | ||
self.G12 = self.twist(cast(Optimized_Point3D[optimized_FQP], self.G2)) | ||
self.Z1 = curve_properties[curve_name]["Z1"] | ||
self.Z2 = curve_properties[curve_name]["Z2"] | ||
|
||
def is_inf(self, pt: Optimized_Point3D[Optimized_Field]) -> bool: | ||
""" | ||
Check if a point is the point at infinity | ||
""" | ||
return pt[-1] == (type(pt[-1]).zero(self.curve_name)) | ||
|
||
def is_on_curve(self, pt: Optimized_Point3D[Optimized_Field], b: Field) -> bool: | ||
""" | ||
Check that a point is on the curve defined by y**2 == x**3 + b | ||
""" | ||
if self.is_inf(pt): | ||
return True | ||
x, y, z = pt | ||
return y**2 * z == x**3 + (b * z**3) | ||
|
||
def double(self, pt: Optimized_Point3D[Optimized_Field]) -> Optimized_Point3D[Optimized_Field]: | ||
""" | ||
Elliptic curve doubling | ||
""" | ||
x, y, z = pt | ||
W = 3 * x * x | ||
S = y * z | ||
B = x * y * S | ||
H = W * W - 8 * B | ||
S_squared = S * S | ||
newx = 2 * H * S | ||
newy = W * (4 * B - H) - 8 * y * y * S_squared | ||
newz = 8 * S * S_squared | ||
return (newx, newy, newz) | ||
|
||
def add(self, | ||
p1: Optimized_Point3D[Optimized_Field], | ||
p2: Optimized_Point3D[Optimized_Field]) -> Optimized_Point3D[Optimized_Field]: | ||
""" | ||
Elliptic curve addition | ||
""" | ||
one, zero = type(p1[0]).one(self.curve_name), type(p1[0]).zero(self.curve_name) | ||
if p1[2] == zero or p2[2] == zero: | ||
return p1 if p2[2] == zero else p2 | ||
x1, y1, z1 = p1 | ||
x2, y2, z2 = p2 | ||
U1 = y2 * z1 | ||
U2 = y1 * z2 | ||
V1 = x2 * z1 | ||
V2 = x1 * z2 | ||
if V1 == V2 and U1 == U2: | ||
return self.double(p1) | ||
elif V1 == V2: | ||
return (one, one, zero) | ||
U = U1 - U2 | ||
V = V1 - V2 | ||
V_squared = V * V | ||
V_squared_times_V2 = V_squared * V2 | ||
V_cubed = V * V_squared | ||
W = z1 * z2 | ||
A = U * U * W - V_cubed - 2 * V_squared_times_V2 | ||
newx = V * A | ||
newy = U * (V_squared_times_V2 - A) - V_cubed * U2 | ||
newz = V_cubed * W | ||
return (newx, newy, newz) | ||
|
||
def multiply(self, | ||
pt: Optimized_Point3D[Optimized_Field], | ||
n: int) -> Optimized_Point3D[Optimized_Field]: | ||
""" | ||
Elliptic curve point multiplication | ||
""" | ||
if n == 0: | ||
return ( | ||
type(pt[0]).one(self.curve_name), | ||
type(pt[0]).one(self.curve_name), | ||
type(pt[0]).zero(self.curve_name) | ||
) | ||
elif n == 1: | ||
return pt | ||
elif not n % 2: | ||
return self.multiply(self.double(pt), n // 2) | ||
else: | ||
return self.add(self.multiply(self.double(pt), int(n // 2)), pt) | ||
|
||
def eq(self, | ||
p1: Optimized_Point3D[Optimized_Field], | ||
p2: Optimized_Point3D[Optimized_Field]) -> bool: | ||
""" | ||
Check if 2 points are equal. | ||
""" | ||
x1, y1, z1 = p1 | ||
x2, y2, z2 = p2 | ||
return x1 * z2 == x2 * z1 and y1 * z2 == y2 * z1 | ||
|
||
def normalize(self, | ||
pt: Optimized_Point3D[Optimized_Field]) -> Optimized_Point2D[Optimized_Field]: | ||
""" | ||
Convert the Jacobian Point to a normal point | ||
""" | ||
x, y, z = pt | ||
return (x / z, y / z) | ||
|
||
def neg(self, pt: Optimized_Point3D[Optimized_Field]) -> Optimized_Point3D[Optimized_Field]: | ||
""" | ||
Gives the reflection of point wrt x-axis (P => -P). | ||
""" | ||
if pt is None: | ||
return None | ||
x, y, z = pt | ||
return (x, -y, z) | ||
|
||
@abstractmethod | ||
def twist(self, pt: Optimized_Point3D[optimized_FQP]) -> Optimized_Point3D[optimized_FQP]: | ||
""" | ||
'Twist' a point in E(FQ2) into a point in E(FQ12) | ||
""" | ||
raise NotImplementedError("Must be implemented by subclasses") |
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.