aboutsummaryrefslogtreecommitdiff
path: root/pyecsca/ec/params.py
diff options
context:
space:
mode:
Diffstat (limited to 'pyecsca/ec/params.py')
-rw-r--r--pyecsca/ec/params.py96
1 files changed, 94 insertions, 2 deletions
diff --git a/pyecsca/ec/params.py b/pyecsca/ec/params.py
index 2b0538e..7cf36a3 100644
--- a/pyecsca/ec/params.py
+++ b/pyecsca/ec/params.py
@@ -1,9 +1,16 @@
-from typing import Optional
+import json
+from os.path import join
+from typing import Optional, Dict, Union
+from pkg_resources import resource_listdir, resource_isdir, resource_stream
from public import public
+from .coordinates import AffineCoordinateModel
from .curve import EllipticCurve
-from .point import Point
+from .mod import Mod
+from .model import (CurveModel, ShortWeierstrassModel, MontgomeryModel, EdwardsModel,
+ TwistedEdwardsModel)
+from .point import Point, InfinityPoint
@public
@@ -47,3 +54,88 @@ class DomainParameters(object):
def __repr__(self):
return f"{self.__class__.__name__}({self.curve!r}, {self.generator!r}, {self.order}, {self.cofactor})"
+
+
+@public
+def get_params(category: str, name: str, coords: str, infty: bool = True) -> DomainParameters:
+ """
+ Retrieve a curve from a set of stored parameters. Uses the std-curves database at
+ https://github.com/J08nY/std-curves.
+
+ :param category: The category of the curve.
+ :param name: The name of the curve.
+ :param coords: The name of the coordinate system to use.
+ :param infty: Whether to use the special :py:class:InfinityPoint (`True`) or try to use the
+ point at infinity of the coordinate system.
+ :return: The curve.
+ """
+ listing = resource_listdir(__name__, "std")
+ categories = list(entry for entry in listing if resource_isdir(__name__, join("std", entry)))
+ if category not in categories:
+ raise ValueError("Category {} not found.".format(category))
+ json_path = join("std", category, "curves.json")
+ with resource_stream(__name__, json_path) as f:
+ category_json = json.load(f)
+ for curve in category_json["curves"]:
+ if curve["name"] == name:
+ break
+ else:
+ raise ValueError("Curve {} not found in category {}.".format(name, category))
+ if curve["field"]["type"] == "Binary":
+ raise ValueError("Binary field curves are currently not supported.")
+
+ # Get model and param names
+ model: CurveModel
+ field = int(curve["field"]["p"], 16)
+ order = int(curve["order"], 16)
+ cofactor = int(curve["cofactor"], 16)
+ if curve["form"] == "Weierstrass":
+ model = ShortWeierstrassModel()
+ param_names = ["a", "b"]
+ elif curve["form"] == "Montgomery":
+ model = MontgomeryModel()
+ param_names = ["a", "b"]
+ elif curve["form"] == "Edwards":
+ model = EdwardsModel()
+ param_names = ["c", "d"]
+ elif curve["form"] == "TwistedEdwards":
+ model = TwistedEdwardsModel()
+ param_names = ["a", "d"]
+ else:
+ raise ValueError("Unknown curve model.")
+
+ # Check coordinate model name and assumptions
+ if coords not in model.coordinates:
+ raise ValueError("Coordinate model not supported for curve.")
+ coord_model = model.coordinates[coords]
+ params = {name: Mod(int(curve["params"][name], 16), field) for name in param_names}
+ for assumption in coord_model.assumptions:
+ alocals: Dict[str, Union[Mod, int]] = {}
+ compiled = compile(assumption, "", mode="exec")
+ exec(compiled, None, alocals)
+ for param, value in alocals.items():
+ if params[param] != value:
+ raise ValueError(f"Coordinate model {coord_model} has an unsatisifed assumption on the {param} parameter (= {value}).")
+ # Construct the point at infinity
+ infinity: Point
+ if infty:
+ infinity = InfinityPoint(coord_model)
+ else:
+ ilocals: Dict[str, Union[Mod, int]] = {**params}
+ for line in coord_model.neutral:
+ compiled = compile(line, "", mode="exec")
+ exec(compiled, None, ilocals)
+ infinity_coords = {}
+ for coordinate in coord_model.variables:
+ if coordinate not in ilocals:
+ raise ValueError(f"Coordinate model {coord_model} requires infty option.")
+ value = ilocals[coordinate]
+ if isinstance(value, int):
+ value = Mod(value, field)
+ infinity_coords[coordinate] = value
+ infinity = Point(coord_model, **infinity_coords)
+ elliptic_curve = EllipticCurve(model, coord_model, field, infinity, params)
+ affine = Point(AffineCoordinateModel(model), x=Mod(int(curve["generator"]["x"], 16), field),
+ y=Mod(int(curve["generator"]["y"], 16), field))
+ generator = Point.from_affine(coord_model, affine)
+ return DomainParameters(elliptic_curve, generator, order, cofactor, name, category) \ No newline at end of file