diff options
| author | J08nY | 2018-12-18 18:28:25 +0100 |
|---|---|---|
| committer | J08nY | 2019-03-21 11:00:14 +0100 |
| commit | 70636c48d6177b50cb6237c2649b3e36d04eaaf4 (patch) | |
| tree | f56f16bf6cdd6325ddbd981d4cc9b9330799df87 | |
| parent | 2fb59321e1b12afee26cccab216d7587940e9aee (diff) | |
| download | pyecsca-70636c48d6177b50cb6237c2649b3e36d04eaaf4.tar.gz pyecsca-70636c48d6177b50cb6237c2649b3e36d04eaaf4.tar.zst pyecsca-70636c48d6177b50cb6237c2649b3e36d04eaaf4.zip | |
| -rw-r--r-- | pyecsca/ec/coordinates.py | 32 | ||||
| -rw-r--r-- | pyecsca/ec/curve.py | 12 | ||||
| -rw-r--r-- | pyecsca/ec/formula.py | 2 | ||||
| -rw-r--r-- | pyecsca/ec/model.py | 31 | ||||
| -rw-r--r-- | pyecsca/ec/mult.py | 72 | ||||
| -rw-r--r-- | pyecsca/ec/naf.py | 17 | ||||
| -rw-r--r-- | pyecsca/ec/point.py | 4 | ||||
| -rw-r--r-- | pyecsca/sca/trace.py | 19 | ||||
| -rw-r--r-- | pyecsca/sca/trace_set/inspector.py | 8 |
9 files changed, 125 insertions, 72 deletions
diff --git a/pyecsca/ec/coordinates.py b/pyecsca/ec/coordinates.py index 61ee5bf..e8f4710 100644 --- a/pyecsca/ec/coordinates.py +++ b/pyecsca/ec/coordinates.py @@ -16,6 +16,35 @@ class CoordinateModel(object): assumptions: List[Expression] formulas: MutableMapping[str, Formula] + def __repr__(self): + return f"{self.__class__.__name__}(\"{self.name}\" on {self.curve_model.name})" + + +class AffineCoordinateModel(CoordinateModel): + name = "affine" + full_name = "Affine coordinates" + + def __init__(self, curve_model: Any): + self.curve_model = curve_model + self.variables = ["x", "y"] + self.satisfying = [] + self.parameters = [] + self.assumptions = [] + self.formulas = {} + + def from_other(self, point): + if point.coordinate_model.curve_model != self.curve_model: + raise ValueError + # TODO + pass + + def to_other(self, other: CoordinateModel, point): + # TODO + pass + + +class EFDCoordinateModel(CoordinateModel): + def __init__(self, dir_path: str, name: str, curve_model: Any): self.name = name self.curve_model = curve_model @@ -69,6 +98,3 @@ class CoordinateModel(object): self.assumptions.append( parse(line[7:].replace("=", "==").replace("^", "**"), mode="eval")) line = f.readline().decode("ascii") - - def __repr__(self): - return "CoordinateModel(\"{}\" on {})".format(self.name, self.curve_model.name) diff --git a/pyecsca/ec/curve.py b/pyecsca/ec/curve.py index bf2cb36..4c9d401 100644 --- a/pyecsca/ec/curve.py +++ b/pyecsca/ec/curve.py @@ -1,8 +1,8 @@ from typing import Mapping -from .point import Point from .coordinates import CoordinateModel from .model import CurveModel +from .point import Point class EllipticCurve(object): @@ -23,3 +23,13 @@ class EllipticCurve(object): self.coordinate_model = coordinate_model self.parameters = dict(parameters) self.neutral = neutral + + def is_on_curve(self, point: Point) -> bool: + pass + + def is_neutral(self, point: Point) -> bool: + return self.neutral == point + + def __repr__(self): + params = ", ".join((f"{key}={val}" for key, val in self.parameters.items())) + return f"EllipticCurve([{params}] on {self.model} using {self.coordinate_model})" diff --git a/pyecsca/ec/formula.py b/pyecsca/ec/formula.py index 80139b7..897a44b 100644 --- a/pyecsca/ec/formula.py +++ b/pyecsca/ec/formula.py @@ -50,7 +50,7 @@ class Formula(object): return self._outputs def __repr__(self): - return self.__class__.__name__ + "({} for {})".format(self.name, self.coordinate_model) + return f"{self.__class__.__name__}({self.name} for {self.coordinate_model})" class AdditionFormula(Formula): diff --git a/pyecsca/ec/model.py b/pyecsca/ec/model.py index 749dbbf..40c19e9 100644 --- a/pyecsca/ec/model.py +++ b/pyecsca/ec/model.py @@ -3,12 +3,10 @@ from pkg_resources import resource_listdir, resource_isdir, resource_stream from public import public from typing import List, MutableMapping -from .coordinates import CoordinateModel +from .coordinates import EFDCoordinateModel, CoordinateModel class CurveModel(object): - _efd_name: str - _loaded: bool = False name: str coordinates: MutableMapping[str, CoordinateModel] parameter_names: List[str] @@ -22,6 +20,11 @@ class CurveModel(object): to_weierstrass: List[Module] from_weierstrass: List[Module] + +class EFDCurveModel(CurveModel): + _efd_name: str + _loaded: bool = False + def __init__(self, efd_name: str): self._efd_name = efd_name if self._loaded: @@ -43,7 +46,7 @@ class CurveModel(object): for fname in files: file_path = "efd/" + efd_name + "/" + fname if resource_isdir(__name__, file_path): - self.__read_coordinate_dir(file_path, fname) + self.__read_coordinate_dir(self.__class__, file_path, fname) else: self.__read_curve_file(self.__class__, file_path) @@ -79,33 +82,41 @@ class CurveModel(object): cls.full_weierstrass.append(format_eq(line)) line = f.readline() - def __read_coordinate_dir(self, dir_path, name): - self.coordinates[name] = CoordinateModel(dir_path, name, self) + def __read_coordinate_dir(self, cls, dir_path, name): + 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 __repr__(self): + return f"{self.__class__.__name__}()" @public -class ShortWeierstrassModel(CurveModel): +class ShortWeierstrassModel(EFDCurveModel): def __init__(self): super().__init__("shortw") @public -class MontgomeryModel(CurveModel): +class MontgomeryModel(EFDCurveModel): def __init__(self): super().__init__("montgom") @public -class EdwardsModel(CurveModel): +class EdwardsModel(EFDCurveModel): def __init__(self): super().__init__("edwards") @public -class TwistedEdwardsModel(CurveModel): +class TwistedEdwardsModel(EFDCurveModel): def __init__(self): super().__init__("twisted") diff --git a/pyecsca/ec/mult.py b/pyecsca/ec/mult.py index 9870296..a623fd0 100644 --- a/pyecsca/ec/mult.py +++ b/pyecsca/ec/mult.py @@ -12,7 +12,7 @@ class ScalarMultiplier(object): curve: EllipticCurve formulas: Mapping[str, Formula] context: Context - _point: Optional[Point] = None + _point: Point = None def __init__(self, curve: EllipticCurve, ctx: Context = None, **formulas: Optional[Formula]): for formula in formulas.values(): @@ -53,13 +53,22 @@ class ScalarMultiplier(object): **self.curve.parameters) def _neg(self, point: Point) -> Point: - #TODO + # TODO raise NotImplementedError def init(self, point: Point): - raise NotImplementedError + self._point = point + + def _init_multiply(self, point: Optional[Point]) -> Point: + if point is None: + if self._point is None: + raise ValueError + else: + if self._point != point: + self.init(point) + return self._point - def multiply(self, scalar: int, point: Optional[Point]) -> Point: + def multiply(self, scalar: int, point: Optional[Point] = None) -> Point: raise NotImplementedError @@ -72,19 +81,15 @@ class LTRMultiplier(ScalarMultiplier): super().__init__(curve, ctx, add=add, dbl=dbl, scl=scl) self.always = always - def init(self, point: Point): - self._point = point - - def multiply(self, scalar: int, point: Optional[Point]) -> Point: - if point is not None and self._point != point: - self.init(point) + def multiply(self, scalar: int, point: Optional[Point] = None) -> Point: + q = self._init_multiply(point) r = copy(self.curve.neutral) for i in range(scalar.bit_length(), -1, -1): r = self._dbl(r) if scalar & (1 << i) != 0: - r = self._add(r, self._point) + r = self._add(r, q) elif self.always: - self._add(r, self._point) + self._add(r, q) if "scl" in self.formulas: r = self._scl(r) return r @@ -99,20 +104,15 @@ class RTLMultiplier(ScalarMultiplier): super().__init__(curve, ctx, add=add, dbl=dbl, scl=scl) self.always = always - def init(self, point: Point): - self._point = point - - def multiply(self, scalar: int, point: Optional[Point]) -> Point: - if point is not None and self._point != point: - self.init(point) + def multiply(self, scalar: int, point: Optional[Point] = None) -> Point: + q = self._init_multiply(point) r = copy(self.curve.neutral) - point = self._point while scalar > 0: if scalar & 1 != 0: - r = self._add(r, point) + r = self._add(r, q) elif self.always: - self._add(r, point) - point = self._dbl(point) + self._add(r, q) + q = self._dbl(q) scalar >>= 1 if "scl" in self.formulas: r = self._scl(r) @@ -125,19 +125,15 @@ class LadderMultiplier(ScalarMultiplier): ctx: Context = None): super().__init__(curve, ctx, ladd=ladd, scl=scl) - def init(self, point: Point): - self._point = point - - def multiply(self, scalar: int, point: Optional[Point]) -> Point: - if point is not None and self._point != point: - self.init(point) - p0 = copy(self._point) - p1 = self._ladd(self.curve.neutral, self._point, self._point)[1] + def multiply(self, scalar: int, point: Optional[Point] = None) -> Point: + q = self._init_multiply(point) + p0 = copy(q) + p1 = self._ladd(self.curve.neutral, q, q)[1] for i in range(scalar.bit_length(), -1, -1): if scalar & i != 0: - p0, p1 = self._ladd(self._point, p1, p0) + p0, p1 = self._ladd(q, p1, p0) else: - p0, p1 = self._ladd(self._point, p0, p1) + p0, p1 = self._ladd(q, p0, p1) if "scl" in self.formulas: p0 = self._scl(p0) return p0 @@ -152,12 +148,11 @@ class BinaryNAFMultiplier(ScalarMultiplier): super().__init__(curve, ctx, add=add, dbl=dbl, scl=scl) def init(self, point: Point): - self._point = point + super().init(point) self._point_neg = self._neg(point) - def multiply(self, scalar: int, point: Optional[Point]) -> Point: - if point is not None and self._point != point: - self.init(point) + def multiply(self, scalar: int, point: Optional[Point] = None) -> Point: + self._init_multiply(point) bnaf = naf(scalar) q = copy(self.curve.neutral) for val in bnaf: @@ -183,9 +178,8 @@ class WindowNAFMultiplier(ScalarMultiplier): self._point = point # TODO: precompute {1, 3, 5, upto 2^(w-1)-1} - def multiply(self, scalar: int, point: Optional[Point]): - if point is not None and self._point != point: - self.init(point) + def multiply(self, scalar: int, point: Optional[Point] = None): + self._init_multiply(point) naf = wnaf(scalar, self._width) q = copy(self.curve.neutral) for val in naf: diff --git a/pyecsca/ec/naf.py b/pyecsca/ec/naf.py index 855ffd1..8f07c9f 100644 --- a/pyecsca/ec/naf.py +++ b/pyecsca/ec/naf.py @@ -4,16 +4,23 @@ from typing import List @public def wnaf(k: int, w: int) -> List[int]: + """ + Compute width `w` NAF (Non-Adjacent Form) of the scalar `k`. + + :param k: + :param w: + :return: + """ half_width = 2 ** (w - 1) full_width = half_width * 2 - def mods(val: int): + def mods(val: int) -> int: val_mod = val % full_width if val_mod > half_width: val_mod -= full_width return val_mod - result = [] + result: List[int] = [] while k >= 1: if k & 1: k_val = mods(k) @@ -27,4 +34,10 @@ def wnaf(k: int, w: int) -> List[int]: @public def naf(k: int) -> List[int]: + """ + Compute the NAF (Non-Adjacent Form) of the scalar `k`. + + :param k: + :return: + """ return wnaf(k, 2) diff --git a/pyecsca/ec/point.py b/pyecsca/ec/point.py index e81b028..265a0ea 100644 --- a/pyecsca/ec/point.py +++ b/pyecsca/ec/point.py @@ -20,5 +20,5 @@ class Point(object): return self.coordinate_model == other.coordinate_model and self.coords == other.coords def __repr__(self): - args = ", ".join(["{}={}".format(key, value) for key, value in self.coords.items()]) - return "Point([{}] in {})".format(args, self.coordinate_model) + args = ", ".join([f"{key}={val}" for key, val in self.coords.items()]) + return f"Point([{args}] in {self.coordinate_model})" diff --git a/pyecsca/sca/trace.py b/pyecsca/sca/trace.py index a9d6892..5324a37 100644 --- a/pyecsca/sca/trace.py +++ b/pyecsca/sca/trace.py @@ -1,37 +1,38 @@ import weakref from numpy import ndarray -from typing import Optional, Sequence - from public import public +from typing import Optional, Sequence, Any @public class Trace(object): """A power trace, which has an optional title, optional data bytes and mandatory samples.""" + title: Optional[str] + data: Optional[bytes] + samples: ndarray def __init__(self, title: Optional[str], data: Optional[bytes], - samples: ndarray, trace_set=None): + samples: ndarray, trace_set: Any = None): self.title = title self.data = data self.samples = samples self.trace_set = trace_set @property - def trace_set(self): + def trace_set(self) -> Any: if self._trace_set is None: return None return self._trace_set() @trace_set.setter - def trace_set(self, trace_set): + def trace_set(self, trace_set: Any): if trace_set is None: self._trace_set = None else: self._trace_set = weakref.ref(trace_set) def __repr__(self): - return "Trace(title={!r}, data={!r}, samples={!r}, trace_set={!r})".format( - self.title, self.data, self.samples, self.trace_set) + return f"Trace(title={self.title!r}, data={self.data!r}, samples={self.samples!r}, trace_set={self.trace_set!r})" @public @@ -46,6 +47,4 @@ class CombinedTrace(Trace): self.parents = weakref.WeakSet(parents) def __repr__(self): - return "CombinedTrace(title={!r}, data={!r}, samples={!r}, trace_set={!r}, parents={})".format( - self.title, self.data, self.samples, self.trace_set, - self.parents) + return f"CombinedTrace(title={self.title!r}, data={self.data!r}, samples={self.samples!r}, trace_set={self.trace_set!r}, parents={self.parents})" diff --git a/pyecsca/sca/trace_set/inspector.py b/pyecsca/sca/trace_set/inspector.py index 634b960..067d348 100644 --- a/pyecsca/sca/trace_set/inspector.py +++ b/pyecsca/sca/trace_set/inspector.py @@ -267,7 +267,7 @@ class InspectorTraceSet(TraceSet): return int(1 / self.x_scale) def __repr__(self): - args = ", ".join(["{}={!r}".format(self._tag_parsers[set_tag][0], - getattr(self, self._tag_parsers[set_tag][0])) - for set_tag in self._set_tags]) - return "InspectorTraceSet({})".format(args) + args = ", ".join( + [f"{self._tag_parsers[set_tag][0]}={getattr(self, self._tag_parsers[set_tag][0])!r}" + for set_tag in self._set_tags]) + return f"InspectorTraceSet({args})" |
