diff options
Diffstat (limited to 'pyecsca/ec/params.py')
| -rw-r--r-- | pyecsca/ec/params.py | 96 |
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 |
