Source code for pyecsca.ec.model

"""Provides curve model classes for the supported curve models."""
from ast import parse, Expression, Module
from typing import List, MutableMapping
from importlib_resources import files, as_file
from importlib_resources.abc import Traversable

from public import public

from .coordinates import EFDCoordinateModel, CoordinateModel


[docs] @public class CurveModel: """Model(form) of an elliptic curve.""" name: str shortname: str coordinates: MutableMapping[str, CoordinateModel] parameter_names: List[str] coordinate_names: List[str] equation: Expression ysquared: Expression base_addition: List[Module] base_doubling: List[Module] base_negation: List[Module] base_neutral: List[Module] full_weierstrass: List[Module] to_weierstrass: List[Module] from_weierstrass: List[Module]
class EFDCurveModel(CurveModel): """A curve model from [EFD]_ data.""" _efd_name: str _loaded: bool = False def __init__(self, efd_name: str): self._efd_name = efd_name self.shortname = efd_name if self._loaded: return self.__load(efd_name) def __load(self, efd_name: str): self.__class__._loaded = True # skipcq: PYL-W0212 self.__class__.coordinates = {} self.__class__.parameter_names = [] self.__class__.coordinate_names = [] self.__class__.base_addition = [] self.__class__.base_doubling = [] self.__class__.base_negation = [] self.__class__.base_neutral = [] self.__class__.full_weierstrass = [] self.__class__.to_weierstrass = [] self.__class__.from_weierstrass = [] for entry in files("pyecsca.ec").joinpath("efd", efd_name).iterdir(): with as_file(entry) as file_path: if entry.is_dir(): self.__read_coordinate_dir( self.__class__, file_path, file_path.stem ) else: self.__read_curve_file(self.__class__, file_path) def __read_curve_file(self, cls, file_path: Traversable): def format_eq(line, mode="exec"): return parse(line.replace("^", "**"), mode=mode) with file_path.open("rb") as f: for raw in f.readlines(): line = raw.decode("ascii").rstrip() if line.startswith("name"): cls.name = line[5:] elif line.startswith("parameter"): cls.parameter_names.append(line[10:]) elif line.startswith("coordinate"): cls.coordinate_names.append(line[11:]) elif line.startswith("satisfying"): cls.equation = format_eq(line[11:], mode="eval") elif line.startswith("ysquared"): cls.ysquared = format_eq(line[9:], mode="eval") elif line.startswith("addition"): cls.base_addition.append(format_eq(line[9:])) elif line.startswith("doubling"): cls.base_doubling.append(format_eq(line[9:])) elif line.startswith("negation"): cls.base_negation.append(format_eq(line[9:])) elif line.startswith("neutral"): cls.base_neutral.append(format_eq(line[8:])) elif line.startswith("toweierstrass"): cls.to_weierstrass.append(format_eq(line[14:])) elif line.startswith("fromweierstrass"): cls.from_weierstrass.append(format_eq(line[16:])) else: cls.full_weierstrass.append(format_eq(line)) def __read_coordinate_dir(self, cls, dir_path: Traversable, name: str): cls.coordinates[name] = EFDCoordinateModel(dir_path, name, self) def __eq__(self, other): if not isinstance(other, EFDCurveModel): return False return self._efd_name == other._efd_name def __getstate__(self): return self.__dict__.copy() def __setstate__(self, state): if not self.__class__._loaded: self.__load(state["_efd_name"]) self.__dict__.update(state) def __hash__(self): return hash(self._efd_name) def __str__(self): return f"{self.__class__.__name__.replace('Model', '')}" def __repr__(self): return f"{self.__class__.__name__}()"
[docs] @public class ShortWeierstrassModel(EFDCurveModel): """ Short-Weierstrass curve model. .. math:: y^2 = x^3 + a x + b """ def __init__(self): super().__init__("shortw")
[docs] @public class MontgomeryModel(EFDCurveModel): """ Montgomery curve model. .. math:: B y^2 = x^3 + A x^2 + x """ def __init__(self): super().__init__("montgom")
[docs] @public class EdwardsModel(EFDCurveModel): """ Edwards curve model. .. math:: x^2 + y^2 = c^2 (1 + d x^2 y^2) """ def __init__(self): super().__init__("edwards")
[docs] @public class TwistedEdwardsModel(EFDCurveModel): """ Twisted-Edwards curve model. .. math:: a x^2 + y^2 = 1 + d x^2 y^2 """ def __init__(self): super().__init__("twisted")