aboutsummaryrefslogtreecommitdiff
path: root/pyecsca/ec/curve.py
diff options
context:
space:
mode:
Diffstat (limited to 'pyecsca/ec/curve.py')
-rw-r--r--pyecsca/ec/curve.py89
1 files changed, 61 insertions, 28 deletions
diff --git a/pyecsca/ec/curve.py b/pyecsca/ec/curve.py
index 8a3c726..67feb60 100644
--- a/pyecsca/ec/curve.py
+++ b/pyecsca/ec/curve.py
@@ -1,4 +1,5 @@
"""Provides an elliptic curve class."""
+
from ast import Module
from astunparse import unparse
from copy import copy
@@ -68,21 +69,21 @@ class EllipticCurve:
"""The neutral point on the curve."""
def __init__(
- self,
- model: CurveModel,
- coordinate_model: CoordinateModel,
- prime: int,
- neutral: Point,
- parameters: MutableMapping[str, Union[Mod, int]],
+ self,
+ model: CurveModel,
+ coordinate_model: CoordinateModel,
+ prime: int,
+ neutral: Point,
+ parameters: MutableMapping[str, Union[Mod, int]],
):
if coordinate_model not in model.coordinates.values() and not isinstance(
- coordinate_model, AffineCoordinateModel
+ coordinate_model, AffineCoordinateModel
):
raise ValueError
if (
- set(model.parameter_names)
- .union(coordinate_model.parameters)
- .symmetric_difference(parameters.keys())
+ set(model.parameter_names)
+ .union(coordinate_model.parameters)
+ .symmetric_difference(parameters.keys())
):
raise ValueError
self.model = model
@@ -130,7 +131,7 @@ class EllipticCurve:
if k.from_sympy(expr) != 0:
raise_unsatisified_assumption(
getconfig().ec.unsatisfied_coordinate_assumption_action,
- f"Coordinate model {self.coordinate_model} has an unsatisifed assumption on the {param} parameter (0 = {expr})."
+ f"Coordinate model {self.coordinate_model} has an unsatisifed assumption on the {param} parameter (0 = {expr}).",
)
def _execute_base_formulas(self, formulas: List[Module], *points: Point) -> Point:
@@ -146,7 +147,9 @@ class EllipticCurve:
}
locls.update(self.parameters)
for line in formulas:
- exec(compile(line, "", mode="exec"), None, locls) # exec is OK here, skipcq: PYL-W0122
+ exec(
+ compile(line, "", mode="exec"), None, locls
+ ) # exec is OK here, skipcq: PYL-W0122
if not isinstance(locls["x"], Mod):
locls["x"] = mod(locls["x"], self.prime)
if not isinstance(locls["y"], Mod):
@@ -233,7 +236,9 @@ class EllipticCurve:
return None
locls = {**self.parameters}
for line in self.model.base_neutral:
- exec(compile(line, "", mode="exec"), None, locls) # exec is OK here, skipcq: PYL-W0122
+ exec(
+ compile(line, "", mode="exec"), None, locls
+ ) # exec is OK here, skipcq: PYL-W0122
if not isinstance(locls["x"], Mod):
locls["x"] = mod(locls["x"], self.prime)
if not isinstance(locls["y"], Mod):
@@ -269,7 +274,9 @@ class EllipticCurve:
loc = {**self.parameters, **point.coords}
else:
loc = {**self.parameters, **point.to_affine().coords}
- return eval(compile(self.model.equation, "", mode="eval"), loc) # eval is OK here, skipcq: PYL-W0123
+ return eval(
+ compile(self.model.equation, "", mode="eval"), loc
+ ) # eval is OK here, skipcq: PYL-W0123
def to_coords(self, coordinate_model: CoordinateModel) -> "EllipticCurve":
"""
@@ -280,8 +287,13 @@ class EllipticCurve:
"""
if not isinstance(self.coordinate_model, AffineCoordinateModel):
raise ValueError
- return EllipticCurve(self.model, coordinate_model, self.prime, self.neutral.to_model(coordinate_model, self),
- self.parameters) # type: ignore[arg-type]
+ return EllipticCurve(
+ self.model,
+ coordinate_model,
+ self.prime,
+ self.neutral.to_model(coordinate_model, self),
+ self.parameters,
+ ) # type: ignore[arg-type]
def to_affine(self) -> "EllipticCurve":
"""
@@ -290,8 +302,13 @@ class EllipticCurve:
:return: The transformed elliptic curve.
"""
coord_model = AffineCoordinateModel(self.model)
- return EllipticCurve(self.model, coord_model, self.prime, self.neutral.to_affine(),
- self.parameters) # type: ignore[arg-type]
+ return EllipticCurve(
+ self.model,
+ coord_model,
+ self.prime,
+ self.neutral.to_affine(),
+ self.parameters,
+ ) # type: ignore[arg-type]
def decode_point(self, encoded: bytes) -> Point:
"""
@@ -325,7 +342,9 @@ class EllipticCurve:
raise ValueError("Encoded point has bad length")
x = mod(int.from_bytes(data, "big"), self.prime)
loc = {**self.parameters, "x": x}
- rhs = eval(compile(self.model.ysquared, "", mode="eval"), loc) # eval is OK here, skipcq: PYL-W0123
+ rhs = eval(
+ compile(self.model.ysquared, "", mode="eval"), loc
+ ) # eval is OK here, skipcq: PYL-W0123
if not rhs.is_residue():
raise ValueError("Point not on curve")
sqrt = rhs.sqrt()
@@ -350,19 +369,25 @@ class EllipticCurve:
:return: Lifted (affine) points, if any.
"""
loc = {**self.parameters, "x": x}
- ysquared = eval(compile(self.model.ysquared, "", mode="eval"), loc) # eval is OK here, skipcq: PYL-W0123
+ ysquared = eval(
+ compile(self.model.ysquared, "", mode="eval"), loc
+ ) # eval is OK here, skipcq: PYL-W0123
if not ysquared.is_residue():
return set()
y = ysquared.sqrt()
- return {Point(AffineCoordinateModel(self.model), x=x, y=y),
- Point(AffineCoordinateModel(self.model), x=x, y=-y)}
+ return {
+ Point(AffineCoordinateModel(self.model), x=x, y=y),
+ Point(AffineCoordinateModel(self.model), x=x, y=-y),
+ }
def affine_random(self) -> Point:
"""Generate a random affine point on the curve."""
while True:
x = Mod.random(self.prime)
loc = {**self.parameters, "x": x}
- ysquared = eval(compile(self.model.ysquared, "", mode="eval"), loc) # eval is OK here, skipcq: PYL-W0123
+ ysquared = eval(
+ compile(self.model.ysquared, "", mode="eval"), loc
+ ) # eval is OK here, skipcq: PYL-W0123
if ysquared.is_residue():
y = ysquared.sqrt()
b = Mod.random(2)
@@ -374,14 +399,22 @@ class EllipticCurve:
if not isinstance(other, EllipticCurve):
return False
return (
- self.model == other.model
- and self.coordinate_model == other.coordinate_model
- and self.prime == other.prime
- and self.parameters == other.parameters
+ self.model == other.model
+ and self.coordinate_model == other.coordinate_model
+ and self.prime == other.prime
+ and self.parameters == other.parameters
)
def __hash__(self):
- return hash((self.model, self.coordinate_model, self.prime, tuple(self.parameters.keys()), tuple(self.parameters.values())))
+ return hash(
+ (
+ self.model,
+ self.coordinate_model,
+ self.prime,
+ tuple(self.parameters.keys()),
+ tuple(self.parameters.values()),
+ )
+ )
def __str__(self):
return "EllipticCurve"