diff options
71 files changed, 745 insertions, 481 deletions
diff --git a/pyecsca/ec/configuration.py b/pyecsca/ec/configuration.py index 0d96192..1a6f795 100644 --- a/pyecsca/ec/configuration.py +++ b/pyecsca/ec/configuration.py @@ -15,10 +15,10 @@ from typing import ( from public import public -from .coordinates import CoordinateModel -from .formula import Formula -from .model import CurveModel -from .mult import ScalarMultiplier +from pyecsca.ec.coordinates import CoordinateModel +from pyecsca.ec.formula import Formula +from pyecsca.ec.model import CurveModel +from pyecsca.ec.mult import ScalarMultiplier @public diff --git a/pyecsca/ec/coordinates.py b/pyecsca/ec/coordinates.py index 03aae77..ed347d9 100644 --- a/pyecsca/ec/coordinates.py +++ b/pyecsca/ec/coordinates.py @@ -6,8 +6,8 @@ from typing import List, Any, MutableMapping from public import public -from .formula.base import Formula -from .formula.efd import ( +from pyecsca.ec.formula.base import Formula +from pyecsca.ec.formula.efd import ( EFDFormula, AdditionEFDFormula, DoublingEFDFormula, @@ -61,6 +61,7 @@ class CoordinateModel: @public class AffineCoordinateModel(CoordinateModel): """An affine coordinate model (there is really only one per curve model).""" + name = "affine" full_name = "Affine coordinates" diff --git a/pyecsca/ec/curve.py b/pyecsca/ec/curve.py index 80bf9ab..bc2276c 100644 --- a/pyecsca/ec/curve.py +++ b/pyecsca/ec/curve.py @@ -6,14 +6,15 @@ from typing import MutableMapping, Union, List, Optional, Dict, Set from public import public from sympy import FF -from ..misc.cache import sympify -from .coordinates import CoordinateModel, AffineCoordinateModel -from .error import raise_unsatisified_assumption -from .mod import Mod -from .model import CurveModel -from .point import Point, InfinityPoint -from ..misc.cfg import getconfig +from pyecsca.misc.cache import sympify +from pyecsca.misc.cfg import getconfig + +from pyecsca.ec.coordinates import CoordinateModel, AffineCoordinateModel +from pyecsca.ec.error import raise_unsatisified_assumption +from pyecsca.ec.mod import Mod +from pyecsca.ec.model import CurveModel +from pyecsca.ec.point import Point, InfinityPoint @public diff --git a/pyecsca/ec/divpoly.py b/pyecsca/ec/divpoly.py index 798bffd..722ec97 100644 --- a/pyecsca/ec/divpoly.py +++ b/pyecsca/ec/divpoly.py @@ -7,9 +7,9 @@ from public import public from sympy import symbols, FF, Poly import networkx as nx -from .curve import EllipticCurve -from .mod import Mod -from .model import ShortWeierstrassModel +from pyecsca.ec.curve import EllipticCurve +from pyecsca.ec.mod import Mod +from pyecsca.ec.model import ShortWeierstrassModel has_pari = False try: diff --git a/pyecsca/ec/error.py b/pyecsca/ec/error.py index cf71c42..b9cd7e7 100644 --- a/pyecsca/ec/error.py +++ b/pyecsca/ec/error.py @@ -1,7 +1,7 @@ """Contains exceptions and warnings used in the library.""" import warnings from public import public -from ..misc.cfg import getconfig +from pyecsca.misc.cfg import getconfig @public diff --git a/pyecsca/ec/formula/base.py b/pyecsca/ec/formula/base.py index d0a3014..704ba11 100644 --- a/pyecsca/ec/formula/base.py +++ b/pyecsca/ec/formula/base.py @@ -10,13 +10,13 @@ from typing import List, Any, ClassVar, MutableMapping, Tuple, Union, Dict from public import public from sympy import FF, symbols, Poly, Rational -from ..context import ResultAction -from .. import context -from ..error import UnsatisfiedAssumptionError, raise_unsatisified_assumption -from ..mod import Mod, SymbolicMod -from ..op import CodeOp, OpType -from ...misc.cfg import getconfig -from ...misc.cache import sympify, simplify +from pyecsca.ec.context import ResultAction +from pyecsca.ec import context +from pyecsca.ec.error import UnsatisfiedAssumptionError, raise_unsatisified_assumption +from pyecsca.ec.mod import Mod, SymbolicMod +from pyecsca.ec.op import CodeOp, OpType +from pyecsca.misc.cfg import getconfig +from pyecsca.misc.cache import sympify, simplify @public @@ -237,7 +237,7 @@ class Formula(ABC): :param params: Parameters of the curve. :return: The resulting point(s). """ - from ..point import Point + from pyecsca.ec.point import Point self.__validate_params(field, params) self.__validate_points(field, points, params) diff --git a/pyecsca/ec/formula/code.py b/pyecsca/ec/formula/code.py index 8309bb8..f24cfc6 100644 --- a/pyecsca/ec/formula/code.py +++ b/pyecsca/ec/formula/code.py @@ -4,7 +4,7 @@ from ast import Expression from astunparse import unparse from public import public -from .base import ( +from pyecsca.ec.formula.base import ( Formula, AdditionFormula, DoublingFormula, @@ -14,8 +14,8 @@ from .base import ( ScalingFormula, DifferentialAdditionFormula, ) -from ..op import CodeOp -from ...misc.utils import peval +from pyecsca.ec.op import CodeOp +from pyecsca.misc.utils import peval @public diff --git a/pyecsca/ec/formula/efd.py b/pyecsca/ec/formula/efd.py index a56eb47..7796c11 100644 --- a/pyecsca/ec/formula/efd.py +++ b/pyecsca/ec/formula/efd.py @@ -6,8 +6,8 @@ from public import public from importlib_resources.abc import Traversable from typing import Any -from .code import CodeFormula -from .base import ( +from pyecsca.ec.formula.code import CodeFormula +from pyecsca.ec.formula.base import ( Formula, CodeOp, AdditionFormula, @@ -19,7 +19,7 @@ from .base import ( LadderFormula, ) -from ...misc.utils import pexec, peval +from pyecsca.misc.utils import pexec, peval @public @@ -74,7 +74,14 @@ class EFDFormula(Formula): def to_code(self) -> CodeFormula: for klass in CodeFormula.__subclasses__(): if self.shortname == klass.shortname: - return klass(self.name, copy(self.code), self.coordinate_model, copy(self.parameters), copy(self.assumptions), self.unified) + return klass( + self.name, + copy(self.code), + self.coordinate_model, + copy(self.parameters), + copy(self.assumptions), + self.unified, + ) raise TypeError(f"CodeFormula not found for {self.__class__}.") def __getnewargs__(self): diff --git a/pyecsca/ec/formula/expand.py b/pyecsca/ec/formula/expand.py index f3c9a56..2f631f7 100644 --- a/pyecsca/ec/formula/expand.py +++ b/pyecsca/ec/formula/expand.py @@ -2,15 +2,17 @@ from typing import Set, Callable, Any from public import public -from .base import Formula -from .efd import EFDFormula -from .fliparoo import recursive_fliparoo -from .metrics import ivs_norm -from .partitions import reduce_all_adds, expand_all_muls, expand_all_nopower2_muls -from .switch_sign import generate_switched_formulas +from pyecsca.ec.formula.base import Formula +from pyecsca.ec.formula.efd import EFDFormula +from pyecsca.ec.formula.fliparoo import recursive_fliparoo +from pyecsca.ec.formula.metrics import ivs_norm +from pyecsca.ec.formula.partitions import reduce_all_adds, expand_all_muls, expand_all_nopower2_muls +from pyecsca.ec.formula.switch_sign import generate_switched_formulas -def reduce_with_similarity(formulas: Set[Formula], norm: Callable[[Formula], Any]) -> Set[Formula]: +def reduce_with_similarity( + formulas: Set[Formula], norm: Callable[[Formula], Any] +) -> Set[Formula]: reduced = set(filter(lambda x: isinstance(x, EFDFormula), formulas)) similarities = list(map(norm, reduced)) for formula in formulas: @@ -42,7 +44,9 @@ def expand_formula_set( extended.update(fliparood) extended = reduce_with_similarity(extended, norm) - switch_signs: Set[Formula] = set().union(*(set(generate_switched_formulas(f)) for f in extended)) + switch_signs: Set[Formula] = set().union( + *(set(generate_switched_formulas(f)) for f in extended) + ) extended.update(switch_signs) extended = reduce_with_similarity(extended, norm) diff --git a/pyecsca/ec/formula/fake.py b/pyecsca/ec/formula/fake.py index 5c20dfb..253095a 100644 --- a/pyecsca/ec/formula/fake.py +++ b/pyecsca/ec/formula/fake.py @@ -4,7 +4,7 @@ from typing import Any, Tuple from public import public -from .base import ( +from pyecsca.ec.formula.base import ( AdditionFormula, FormulaAction, Formula, @@ -15,8 +15,8 @@ from .base import ( ScalingFormula, DifferentialAdditionFormula, ) -from ..mod import Mod, Undefined -from ..point import Point +from pyecsca.ec.mod import Mod, Undefined +from pyecsca.ec.point import Point @public @@ -27,6 +27,7 @@ class FakeFormula(Formula, ABC): Useful for computing with the scalar multipliers without having concrete formulas and points (for example to get the addition chain via the MultipleContext). """ + def __init__(self, coordinate_model): # TODO: This is missing all of the other attributes self.coordinate_model = coordinate_model diff --git a/pyecsca/ec/formula/fliparoo.py b/pyecsca/ec/formula/fliparoo.py index 6665e1e..4e1d221 100644 --- a/pyecsca/ec/formula/fliparoo.py +++ b/pyecsca/ec/formula/fliparoo.py @@ -2,9 +2,10 @@ from ast import parse from typing import Iterator, List, Type, Optional, Set from public import public -from ..op import OpType -from .base import Formula -from .graph import FormulaGraph, Node, CodeOpNode, CodeOp, CodeFormula + +from pyecsca.ec.op import OpType +from pyecsca.ec.formula.base import Formula +from pyecsca.ec.formula.graph import FormulaGraph, Node, CodeOpNode, CodeOp, CodeFormula @public diff --git a/pyecsca/ec/formula/graph.py b/pyecsca/ec/formula/graph.py index c7886bd..d4a79b1 100644 --- a/pyecsca/ec/formula/graph.py +++ b/pyecsca/ec/formula/graph.py @@ -1,7 +1,4 @@ """Provides tools for working with formulas as graphs.""" -from .base import Formula -from .code import CodeFormula -from ..op import CodeOp, OpType import matplotlib.pyplot as plt import networkx as nx from ast import parse, Expression @@ -10,6 +7,10 @@ from copy import deepcopy from public import public from abc import ABC, abstractmethod +from pyecsca.ec.formula.base import Formula +from pyecsca.ec.formula.code import CodeFormula +from pyecsca.ec.op import CodeOp, OpType + @public class Node(ABC): diff --git a/pyecsca/ec/formula/metrics.py b/pyecsca/ec/formula/metrics.py index f3c8487..f8dbb73 100644 --- a/pyecsca/ec/formula/metrics.py +++ b/pyecsca/ec/formula/metrics.py @@ -1,12 +1,14 @@ """Provides metrics for comparing formulas.""" -from public import public -from .unroll import unroll_formula -from .base import Formula import warnings + +from public import public from typing import Dict from operator import itemgetter, attrgetter -from ..curve import EllipticCurve -from ..context import DefaultContext, local + +from pyecsca.ec.formula.unroll import unroll_formula +from pyecsca.ec.formula.base import Formula +from pyecsca.ec.curve import EllipticCurve +from pyecsca.ec.context import DefaultContext, local @public diff --git a/pyecsca/ec/formula/partitions.py b/pyecsca/ec/formula/partitions.py index adfb4f8..363690b 100644 --- a/pyecsca/ec/formula/partitions.py +++ b/pyecsca/ec/formula/partitions.py @@ -1,12 +1,19 @@ from typing import List, Any, Generator from ast import parse from public import public -from .base import Formula -from ..op import OpType, CodeOp -from .graph import FormulaGraph, CodeOpNode, ConstantNode, Node, CodeFormula -from .fliparoo import find_fliparoos, AddFliparoo, MulFliparoo from copy import deepcopy +from pyecsca.ec.formula.base import Formula +from pyecsca.ec.op import OpType, CodeOp +from pyecsca.ec.formula.graph import ( + FormulaGraph, + CodeOpNode, + ConstantNode, + Node, + CodeFormula, +) +from pyecsca.ec.formula.fliparoo import find_fliparoos, AddFliparoo, MulFliparoo + @public def reduce_all_adds(formula: Formula, rename=True) -> CodeFormula: diff --git a/pyecsca/ec/formula/switch_sign.py b/pyecsca/ec/formula/switch_sign.py index f860c95..b5bc146 100644 --- a/pyecsca/ec/formula/switch_sign.py +++ b/pyecsca/ec/formula/switch_sign.py @@ -1,18 +1,17 @@ from typing import Dict, Iterator, List, Any from ast import parse from public import public -from ..op import OpType, CodeOp -from .base import Formula -from .graph import FormulaGraph, ConstantNode, CodeOpNode, CodeFormula from itertools import chain, combinations -from ..point import Point -from ..mod import Mod + +from pyecsca.ec.op import OpType, CodeOp +from pyecsca.ec.formula.base import Formula +from pyecsca.ec.formula.graph import FormulaGraph, ConstantNode, CodeOpNode, CodeFormula +from pyecsca.ec.point import Point +from pyecsca.ec.mod import Mod @public -def generate_switched_formulas( - formula: Formula, rename=True -) -> Iterator[CodeFormula]: +def generate_switched_formulas(formula: Formula, rename=True) -> Iterator[CodeFormula]: graph = FormulaGraph(formula, rename) for i, node_combination in enumerate(subnode_lists(graph)): try: @@ -57,7 +56,7 @@ def sign_test(output_signs: Dict[str, int], coordinate_model: Any): for out, sign in output_signs.items(): if not out.endswith(ind): continue - out_var = out[:out.index(ind)] + out_var = out[: out.index(ind)] if not out_var.isalpha(): continue point_dict[out_var] = Mod(sign, p) diff --git a/pyecsca/ec/formula/unroll.py b/pyecsca/ec/formula/unroll.py index 3b83e96..83a7517 100644 --- a/pyecsca/ec/formula/unroll.py +++ b/pyecsca/ec/formula/unroll.py @@ -5,9 +5,9 @@ from typing import List, Tuple from astunparse import unparse from public import public from sympy import Expr, symbols, Poly -from ...misc.cache import sympify -from .base import Formula +from pyecsca.misc.cache import sympify +from pyecsca.ec.formula.base import Formula @public diff --git a/pyecsca/ec/key_agreement.py b/pyecsca/ec/key_agreement.py index 555005f..fe07b1f 100644 --- a/pyecsca/ec/key_agreement.py +++ b/pyecsca/ec/key_agreement.py @@ -4,11 +4,11 @@ from typing import Optional, Any from public import public -from .context import ResultAction -from .mod import Mod -from .mult import ScalarMultiplier -from .params import DomainParameters -from .point import Point +from pyecsca.ec.context import ResultAction +from pyecsca.ec.mod import Mod +from pyecsca.ec.mult import ScalarMultiplier +from pyecsca.ec.params import DomainParameters +from pyecsca.ec.point import Point @public diff --git a/pyecsca/ec/key_generation.py b/pyecsca/ec/key_generation.py index 43a20cd..13bf6d8 100644 --- a/pyecsca/ec/key_generation.py +++ b/pyecsca/ec/key_generation.py @@ -3,11 +3,11 @@ from typing import Tuple from public import public -from .context import ResultAction -from .mod import Mod -from .mult import ScalarMultiplier -from .params import DomainParameters -from .point import Point +from pyecsca.ec.context import ResultAction +from pyecsca.ec.mod import Mod +from pyecsca.ec.mult import ScalarMultiplier +from pyecsca.ec.params import DomainParameters +from pyecsca.ec.point import Point @public diff --git a/pyecsca/ec/mod.py b/pyecsca/ec/mod.py index 972188a..07b2734 100644 --- a/pyecsca/ec/mod.py +++ b/pyecsca/ec/mod.py @@ -15,9 +15,9 @@ from typing import Type, Dict, Any, Tuple, Union from public import public from sympy import Expr, FF -from .error import raise_non_invertible, raise_non_residue -from .context import ResultAction -from ..misc.cfg import getconfig +from pyecsca.ec.error import raise_non_invertible, raise_non_residue +from pyecsca.ec.context import ResultAction +from pyecsca.misc.cfg import getconfig has_gmp = False try: @@ -317,18 +317,18 @@ class RawMod(Mod): m = s c = RawMod(z, self.n) ** q - t = self ** q + t = self**q r_exp = (q + 1) // 2 - r = self ** r_exp + r = self**r_exp while t != 1: i = 1 - while not (t ** (2 ** i)) == 1: + while not (t ** (2**i)) == 1: i += 1 two_exp = m - (i + 1) b = c ** int(RawMod(2, self.n) ** two_exp) m = int(RawMod(i, self.n)) - c = b ** 2 + c = b**2 t *= c r *= b return r @@ -374,6 +374,7 @@ _mod_classes["python"] = RawMod @public class Undefined(Mod): """A special undefined element.""" + __slots__ = ("x", "n") def __new__(cls, *args, **kwargs): @@ -598,7 +599,12 @@ if has_gmp: def __new__(cls, *args, **kwargs): return object.__new__(cls) - def __init__(self, x: Union[int, gmpy2.mpz], n: Union[int, gmpy2.mpz], ensure: bool = True): + def __init__( + self, + x: Union[int, gmpy2.mpz], + n: Union[int, gmpy2.mpz], + ensure: bool = True, + ): if ensure: self.n = gmpy2.mpz(n) self.x = gmpy2.mpz(x % self.n) @@ -657,12 +663,12 @@ if has_gmp: while t != 1: i = 1 - while not (t ** (2 ** i)) == 1: + while not (t ** (2**i)) == 1: i += 1 two_exp = m - (i + 1) b = c ** int(GMPMod(gmpy2.mpz(2), self.n, ensure=False) ** two_exp) m = int(GMPMod(gmpy2.mpz(i), self.n, ensure=False)) - c = b ** 2 + c = b**2 t *= c r *= b return r @@ -718,6 +724,8 @@ if has_gmp: return self.inverse() ** (-n) if n == 1: return GMPMod(self.x, self.n, ensure=False) - return GMPMod(gmpy2.powmod(self.x, gmpy2.mpz(n), self.n), self.n, ensure=False) + return GMPMod( + gmpy2.powmod(self.x, gmpy2.mpz(n), self.n), self.n, ensure=False + ) _mod_classes["gmp"] = GMPMod diff --git a/pyecsca/ec/model.py b/pyecsca/ec/model.py index 42025c5..d90f337 100644 --- a/pyecsca/ec/model.py +++ b/pyecsca/ec/model.py @@ -6,7 +6,7 @@ from importlib_resources.abc import Traversable from public import public -from .coordinates import EFDCoordinateModel, CoordinateModel +from pyecsca.ec.coordinates import EFDCoordinateModel, CoordinateModel @public diff --git a/pyecsca/ec/mult/base.py b/pyecsca/ec/mult/base.py index d66f810..537f43e 100644 --- a/pyecsca/ec/mult/base.py +++ b/pyecsca/ec/mult/base.py @@ -7,15 +7,16 @@ from enum import Enum from public import public from typing import Mapping, Tuple, Optional, ClassVar, Set, Type -from ..context import ResultAction, Action -from ..formula import Formula -from ..params import DomainParameters -from ..point import Point +from pyecsca.ec.context import ResultAction, Action +from pyecsca.ec.formula import Formula +from pyecsca.ec.params import DomainParameters +from pyecsca.ec.point import Point @public class ProcessingDirection(Enum): """Scalar processing direction.""" + LTR = "Left-to-right" RTL = "Right-to-left" @@ -23,6 +24,7 @@ class ProcessingDirection(Enum): @public class AccumulationOrder(Enum): """Accumulation order (makes a difference for the projective result).""" + PeqPR = "P = P + R" PeqRP = "P = R + P" @@ -87,14 +89,14 @@ class ScalarMultiplier(ABC): def __init__(self, short_circuit: bool = True, **formulas: Optional[Formula]): if ( - len( - { - formula.coordinate_model - for formula in formulas.values() - if formula is not None - } - ) - != 1 + len( + { + formula.coordinate_model + for formula in formulas.values() + if formula is not None + } + ) + != 1 ): raise ValueError("Formulas need to belong to the same coordinate model.") self.short_circuit = short_circuit @@ -129,10 +131,7 @@ class ScalarMultiplier(ABC): def _dbl(self, point: Point) -> Point: if "dbl" not in self.formulas: raise NotImplementedError - if ( - self.short_circuit - and point == self._params.curve.neutral - ): + if self.short_circuit and point == self._params.curve.neutral: return copy(point) return self.formulas["dbl"]( self._params.curve.prime, point, **self._params.curve.parameters @@ -181,12 +180,22 @@ class ScalarMultiplier(ABC): )[0] def __hash__(self): - return hash((ScalarMultiplier, tuple(self.formulas.keys()), tuple(self.formulas.values()), self.short_circuit)) + return hash( + ( + ScalarMultiplier, + tuple(self.formulas.keys()), + tuple(self.formulas.values()), + self.short_circuit, + ) + ) def __eq__(self, other): if not isinstance(other, ScalarMultiplier): return False - return self.formulas == other.formulas and self.short_circuit == other.short_circuit + return ( + self.formulas == other.formulas + and self.short_circuit == other.short_circuit + ) def __repr__(self): return f"{self.__class__.__name__}({', '.join(map(str, self.formulas.values()))}, short_circuit={self.short_circuit})" @@ -203,10 +212,12 @@ class ScalarMultiplier(ABC): """ coord_model = set(self.formulas.values()).pop().coordinate_model if ( - params.curve.coordinate_model != coord_model - or point.coordinate_model != coord_model + params.curve.coordinate_model != coord_model + or point.coordinate_model != coord_model ): - raise ValueError("Coordinate models of the parameters, formulas or point are not compatible.") + raise ValueError( + "Coordinate models of the parameters, formulas or point are not compatible." + ) self._params = params self._point = point self._initialized = True @@ -232,10 +243,16 @@ class AccumulatorMultiplier(ScalarMultiplier, ABC): :param accumulation_order: The order of accumulation of points. """ + accumulation_order: AccumulationOrder """The order of accumulation of points.""" - def __init__(self, *args, accumulation_order: AccumulationOrder = AccumulationOrder.PeqPR, **kwargs): + def __init__( + self, + *args, + accumulation_order: AccumulationOrder = AccumulationOrder.PeqPR, + **kwargs, + ): super().__init__(*args, **kwargs) self.accumulation_order = accumulation_order diff --git a/pyecsca/ec/mult/binary.py b/pyecsca/ec/mult/binary.py index 89c203c..9b6a07a 100644 --- a/pyecsca/ec/mult/binary.py +++ b/pyecsca/ec/mult/binary.py @@ -5,14 +5,15 @@ from typing import Optional from public import public -from .base import ScalarMultiplier, ProcessingDirection, AccumulationOrder, ScalarMultiplicationAction, \ - AccumulatorMultiplier -from ..formula import ( - AdditionFormula, - DoublingFormula, - ScalingFormula, +from pyecsca.ec.mult.base import ( + ScalarMultiplier, + ProcessingDirection, + AccumulationOrder, + ScalarMultiplicationAction, + AccumulatorMultiplier, ) -from ..point import Point +from pyecsca.ec.formula import AdditionFormula, DoublingFormula, ScalingFormula +from pyecsca.ec.point import Point @public @@ -30,6 +31,7 @@ class DoubleAndAddMultiplier(AccumulatorMultiplier, ScalarMultiplier, ABC): :param accumulation_order: The order of accumulation of points. :param complete: Whether it starts processing at full order-bit-length. """ + requires = {AdditionFormula, DoublingFormula} optionals = {ScalingFormula} always: bool @@ -40,28 +42,50 @@ class DoubleAndAddMultiplier(AccumulatorMultiplier, ScalarMultiplier, ABC): """Whether it starts processing at full order-bit-length.""" def __init__( - self, - add: AdditionFormula, - dbl: DoublingFormula, - scl: Optional[ScalingFormula] = None, - always: bool = False, - direction: ProcessingDirection = ProcessingDirection.LTR, - accumulation_order: AccumulationOrder = AccumulationOrder.PeqPR, - complete: bool = True, - short_circuit: bool = True, + self, + add: AdditionFormula, + dbl: DoublingFormula, + scl: Optional[ScalingFormula] = None, + always: bool = False, + direction: ProcessingDirection = ProcessingDirection.LTR, + accumulation_order: AccumulationOrder = AccumulationOrder.PeqPR, + complete: bool = True, + short_circuit: bool = True, ): - super().__init__(short_circuit=short_circuit, accumulation_order=accumulation_order, add=add, dbl=dbl, scl=scl) + super().__init__( + short_circuit=short_circuit, + accumulation_order=accumulation_order, + add=add, + dbl=dbl, + scl=scl, + ) self.always = always self.direction = direction self.complete = complete def __hash__(self): - return hash((DoubleAndAddMultiplier, super().__hash__(), self.direction, self.accumulation_order, self.always, self.complete)) + return hash( + ( + DoubleAndAddMultiplier, + super().__hash__(), + self.direction, + self.accumulation_order, + self.always, + self.complete, + ) + ) def __eq__(self, other): if not isinstance(other, DoubleAndAddMultiplier): return False - return self.formulas == other.formulas and self.short_circuit == other.short_circuit and self.direction == other.direction and self.accumulation_order == other.accumulation_order and self.always == other.always and self.complete == other.complete + return ( + self.formulas == other.formulas + and self.short_circuit == other.short_circuit + and self.direction == other.direction + and self.accumulation_order == other.accumulation_order + and self.always == other.always + and self.complete == other.complete + ) def __repr__(self): return f"{self.__class__.__name__}({', '.join(map(str, self.formulas.values()))}, short_circuit={self.short_circuit}, direction={self.direction.name}, accumulation_order={self.accumulation_order.name}, always={self.always}, complete={self.complete})" @@ -130,18 +154,25 @@ class LTRMultiplier(DoubleAndAddMultiplier): """ def __init__( - self, - add: AdditionFormula, - dbl: DoublingFormula, - scl: Optional[ScalingFormula] = None, - always: bool = False, - accumulation_order: AccumulationOrder = AccumulationOrder.PeqPR, - complete: bool = True, - short_circuit: bool = True, + self, + add: AdditionFormula, + dbl: DoublingFormula, + scl: Optional[ScalingFormula] = None, + always: bool = False, + accumulation_order: AccumulationOrder = AccumulationOrder.PeqPR, + complete: bool = True, + short_circuit: bool = True, ): - super().__init__(short_circuit=short_circuit, direction=ProcessingDirection.LTR, - accumulation_order=accumulation_order, always=always, complete=complete, - add=add, dbl=dbl, scl=scl) + super().__init__( + short_circuit=short_circuit, + direction=ProcessingDirection.LTR, + accumulation_order=accumulation_order, + always=always, + complete=complete, + add=add, + dbl=dbl, + scl=scl, + ) @public @@ -157,18 +188,25 @@ class RTLMultiplier(DoubleAndAddMultiplier): """ def __init__( - self, - add: AdditionFormula, - dbl: DoublingFormula, - scl: Optional[ScalingFormula] = None, - always: bool = False, - accumulation_order: AccumulationOrder = AccumulationOrder.PeqPR, - complete: bool = True, - short_circuit: bool = True, + self, + add: AdditionFormula, + dbl: DoublingFormula, + scl: Optional[ScalingFormula] = None, + always: bool = False, + accumulation_order: AccumulationOrder = AccumulationOrder.PeqPR, + complete: bool = True, + short_circuit: bool = True, ): - super().__init__(short_circuit=short_circuit, direction=ProcessingDirection.RTL, - accumulation_order=accumulation_order, always=always, - add=add, dbl=dbl, scl=scl, complete=complete) + super().__init__( + short_circuit=short_circuit, + direction=ProcessingDirection.RTL, + accumulation_order=accumulation_order, + always=always, + add=add, + dbl=dbl, + scl=scl, + complete=complete, + ) @public @@ -186,11 +224,11 @@ class CoronMultiplier(ScalarMultiplier): optionals = {ScalingFormula} def __init__( - self, - add: AdditionFormula, - dbl: DoublingFormula, - scl: Optional[ScalingFormula] = None, - short_circuit: bool = True, + self, + add: AdditionFormula, + dbl: DoublingFormula, + scl: Optional[ScalingFormula] = None, + short_circuit: bool = True, ): super().__init__(short_circuit=short_circuit, add=add, dbl=dbl, scl=scl) @@ -200,7 +238,10 @@ class CoronMultiplier(ScalarMultiplier): def __eq__(self, other): if not isinstance(other, CoronMultiplier): return False - return self.formulas == other.formulas and self.short_circuit == other.short_circuit + return ( + self.formulas == other.formulas + and self.short_circuit == other.short_circuit + ) def multiply(self, scalar: int) -> Point: if not self._initialized: diff --git a/pyecsca/ec/mult/comb.py b/pyecsca/ec/mult/comb.py index c65adb6..8cea19c 100644 --- a/pyecsca/ec/mult/comb.py +++ b/pyecsca/ec/mult/comb.py @@ -5,8 +5,8 @@ from typing import MutableMapping, Optional from public import public -from ..formula import AdditionFormula, DoublingFormula, ScalingFormula -from ..mult import ( +from pyecsca.ec.formula import AdditionFormula, DoublingFormula, ScalingFormula +from pyecsca.ec.mult import ( AccumulatorMultiplier, ScalarMultiplier, ProcessingDirection, @@ -14,9 +14,9 @@ from ..mult import ( PrecomputationAction, ScalarMultiplicationAction, ) -from ..params import DomainParameters -from ..point import Point -from ..scalar import convert_base +from pyecsca.ec.params import DomainParameters +from pyecsca.ec.point import Point +from pyecsca.ec.scalar import convert_base @public @@ -61,12 +61,26 @@ class BGMWMultiplier(AccumulatorMultiplier, ScalarMultiplier): self.width = width def __hash__(self): - return hash((BGMWMultiplier, super().__hash__(), self.width, self.direction, self.accumulation_order)) + return hash( + ( + BGMWMultiplier, + super().__hash__(), + self.width, + self.direction, + self.accumulation_order, + ) + ) def __eq__(self, other): if not isinstance(other, BGMWMultiplier): return False - return self.formulas == other.formulas and self.short_circuit == other.short_circuit and self.width == other.width and self.direction == other.direction and self.accumulation_order == other.accumulation_order + return ( + self.formulas == other.formulas + and self.short_circuit == other.short_circuit + and self.width == other.width + and self.direction == other.direction + and self.accumulation_order == other.accumulation_order + ) def __repr__(self): return f"{self.__class__.__name__}({', '.join(map(str, self.formulas.values()))}, short_circuit={self.short_circuit}, width={self.width}, direction={self.direction.name}, accumulation_order={self.accumulation_order.name})" @@ -147,12 +161,19 @@ class CombMultiplier(AccumulatorMultiplier, ScalarMultiplier): self.width = width def __hash__(self): - return hash((CombMultiplier, super().__hash__(), self.width, self.accumulation_order)) + return hash( + (CombMultiplier, super().__hash__(), self.width, self.accumulation_order) + ) def __eq__(self, other): if not isinstance(other, CombMultiplier): return False - return self.formulas == other.formulas and self.short_circuit == other.short_circuit and self.width == other.width and self.accumulation_order == other.accumulation_order + return ( + self.formulas == other.formulas + and self.short_circuit == other.short_circuit + and self.width == other.width + and self.accumulation_order == other.accumulation_order + ) def __repr__(self): return f"{self.__class__.__name__}({', '.join(map(str, self.formulas.values()))}, short_circuit={self.short_circuit}, width={self.width}, accumulation_order={self.accumulation_order.name})" diff --git a/pyecsca/ec/mult/fixed.py b/pyecsca/ec/mult/fixed.py index fedc22d..afd02e5 100644 --- a/pyecsca/ec/mult/fixed.py +++ b/pyecsca/ec/mult/fixed.py @@ -4,11 +4,17 @@ from typing import MutableMapping, Optional from public import public -from ..formula import AdditionFormula, DoublingFormula, ScalingFormula -from ..mult import AccumulatorMultiplier, ScalarMultiplier, ProcessingDirection, AccumulationOrder, \ - PrecomputationAction, ScalarMultiplicationAction -from ..params import DomainParameters -from ..point import Point +from pyecsca.ec.formula import AdditionFormula, DoublingFormula, ScalingFormula +from pyecsca.ec.mult import ( + AccumulatorMultiplier, + ScalarMultiplier, + ProcessingDirection, + AccumulationOrder, + PrecomputationAction, + ScalarMultiplicationAction, +) +from pyecsca.ec.params import DomainParameters +from pyecsca.ec.point import Point @public @@ -37,30 +43,49 @@ class FullPrecompMultiplier(AccumulatorMultiplier, ScalarMultiplier): _points: MutableMapping[int, Point] def __init__( - self, - add: AdditionFormula, - dbl: DoublingFormula, - scl: Optional[ScalingFormula] = None, - always: bool = False, - direction: ProcessingDirection = ProcessingDirection.LTR, - accumulation_order: AccumulationOrder = AccumulationOrder.PeqPR, - complete: bool = True, - short_circuit: bool = True, + self, + add: AdditionFormula, + dbl: DoublingFormula, + scl: Optional[ScalingFormula] = None, + always: bool = False, + direction: ProcessingDirection = ProcessingDirection.LTR, + accumulation_order: AccumulationOrder = AccumulationOrder.PeqPR, + complete: bool = True, + short_circuit: bool = True, ): super().__init__( - short_circuit=short_circuit, accumulation_order=accumulation_order, add=add, dbl=dbl, scl=scl + short_circuit=short_circuit, + accumulation_order=accumulation_order, + add=add, + dbl=dbl, + scl=scl, ) self.always = always self.direction = direction self.complete = complete def __hash__(self): - return hash((FullPrecompMultiplier, super().__hash__(), self.direction, self.accumulation_order, self.always)) + return hash( + ( + FullPrecompMultiplier, + super().__hash__(), + self.direction, + self.accumulation_order, + self.always, + ) + ) def __eq__(self, other): if not isinstance(other, FullPrecompMultiplier): return False - return self.formulas == other.formulas and self.short_circuit == other.short_circuit and self.direction == other.direction and self.accumulation_order == other.accumulation_order and self.always == other.always and self.complete == other.complete + return ( + self.formulas == other.formulas + and self.short_circuit == other.short_circuit + and self.direction == other.direction + and self.accumulation_order == other.accumulation_order + and self.always == other.always + and self.complete == other.complete + ) def __repr__(self): return f"{self.__class__.__name__}({', '.join(map(str, self.formulas.values()))}, short_circuit={self.short_circuit}, accumulation_order={self.accumulation_order.name}, always={self.always}, complete={self.complete})" diff --git a/pyecsca/ec/mult/ladder.py b/pyecsca/ec/mult/ladder.py index 2f7fd26..105587f 100644 --- a/pyecsca/ec/mult/ladder.py +++ b/pyecsca/ec/mult/ladder.py @@ -3,15 +3,15 @@ from copy import copy from typing import Optional from public import public -from .base import ScalarMultiplier, ScalarMultiplicationAction -from ..formula import ( +from pyecsca.ec.mult.base import ScalarMultiplier, ScalarMultiplicationAction +from pyecsca.ec.formula import ( AdditionFormula, DoublingFormula, ScalingFormula, LadderFormula, - DifferentialAdditionFormula + DifferentialAdditionFormula, ) -from ..point import Point +from pyecsca.ec.point import Point @public @@ -32,12 +32,12 @@ class LadderMultiplier(ScalarMultiplier): """Whether it starts processing at full order-bit-length.""" def __init__( - self, - ladd: LadderFormula, - dbl: Optional[DoublingFormula] = None, - scl: Optional[ScalingFormula] = None, - complete: bool = True, - short_circuit: bool = True, + self, + ladd: LadderFormula, + dbl: Optional[DoublingFormula] = None, + scl: Optional[ScalingFormula] = None, + complete: bool = True, + short_circuit: bool = True, ): super().__init__(short_circuit=short_circuit, ladd=ladd, dbl=dbl, scl=scl) self.complete = complete @@ -50,7 +50,11 @@ class LadderMultiplier(ScalarMultiplier): def __eq__(self, other): if not isinstance(other, LadderMultiplier): return False - return self.formulas == other.formulas and self.short_circuit == other.short_circuit and self.complete == other.complete + return ( + self.formulas == other.formulas + and self.short_circuit == other.short_circuit + and self.complete == other.complete + ) def __repr__(self): return f"{self.__class__.__name__}({', '.join(map(str, self.formulas.values()))}, short_circuit={self.short_circuit}, complete={self.complete})" @@ -96,12 +100,12 @@ class SimpleLadderMultiplier(ScalarMultiplier): """Whether it starts processing at full order-bit-length.""" def __init__( - self, - add: AdditionFormula, - dbl: DoublingFormula, - scl: Optional[ScalingFormula] = None, - complete: bool = True, - short_circuit: bool = True, + self, + add: AdditionFormula, + dbl: DoublingFormula, + scl: Optional[ScalingFormula] = None, + complete: bool = True, + short_circuit: bool = True, ): super().__init__(short_circuit=short_circuit, add=add, dbl=dbl, scl=scl) self.complete = complete @@ -112,7 +116,11 @@ class SimpleLadderMultiplier(ScalarMultiplier): def __eq__(self, other): if not isinstance(other, SimpleLadderMultiplier): return False - return self.formulas == other.formulas and self.short_circuit == other.short_circuit and self.complete == other.complete + return ( + self.formulas == other.formulas + and self.short_circuit == other.short_circuit + and self.complete == other.complete + ) def __repr__(self): return f"{self.__class__.__name__}({', '.join(map(str, self.formulas.values()))}, short_circuit={self.short_circuit}, complete={self.complete})" @@ -157,12 +165,12 @@ class DifferentialLadderMultiplier(ScalarMultiplier): """Whether it starts processing at full order-bit-length.""" def __init__( - self, - dadd: DifferentialAdditionFormula, - dbl: DoublingFormula, - scl: Optional[ScalingFormula] = None, - complete: bool = True, - short_circuit: bool = True, + self, + dadd: DifferentialAdditionFormula, + dbl: DoublingFormula, + scl: Optional[ScalingFormula] = None, + complete: bool = True, + short_circuit: bool = True, ): super().__init__(short_circuit=short_circuit, dadd=dadd, dbl=dbl, scl=scl) self.complete = complete @@ -173,7 +181,11 @@ class DifferentialLadderMultiplier(ScalarMultiplier): def __eq__(self, other): if not isinstance(other, DifferentialLadderMultiplier): return False - return self.formulas == other.formulas and self.short_circuit == other.short_circuit and self.complete == other.complete + return ( + self.formulas == other.formulas + and self.short_circuit == other.short_circuit + and self.complete == other.complete + ) def __repr__(self): return f"{self.__class__.__name__}({', '.join(map(str, self.formulas.values()))}, short_circuit={self.short_circuit}, complete={self.complete})" diff --git a/pyecsca/ec/mult/naf.py b/pyecsca/ec/mult/naf.py index b21d1cf..408f489 100644 --- a/pyecsca/ec/mult/naf.py +++ b/pyecsca/ec/mult/naf.py @@ -3,17 +3,23 @@ from copy import copy from typing import Optional, List, MutableMapping from public import public -from .base import ScalarMultiplier, ScalarMultiplicationAction, ProcessingDirection, AccumulationOrder, \ - PrecomputationAction, AccumulatorMultiplier -from ..formula import ( +from pyecsca.ec.mult.base import ( + ScalarMultiplier, + ScalarMultiplicationAction, + ProcessingDirection, + AccumulationOrder, + PrecomputationAction, + AccumulatorMultiplier, +) +from pyecsca.ec.formula import ( AdditionFormula, DoublingFormula, ScalingFormula, - NegationFormula + NegationFormula, ) -from ..params import DomainParameters -from ..point import Point -from ..scalar import naf, wnaf +from pyecsca.ec.params import DomainParameters +from pyecsca.ec.point import Point +from pyecsca.ec.scalar import naf, wnaf @public @@ -33,27 +39,44 @@ class BinaryNAFMultiplier(AccumulatorMultiplier, ScalarMultiplier): _point_neg: Point def __init__( - self, - add: AdditionFormula, - dbl: DoublingFormula, - neg: NegationFormula, - scl: Optional[ScalingFormula] = None, - direction: ProcessingDirection = ProcessingDirection.LTR, - accumulation_order: AccumulationOrder = AccumulationOrder.PeqPR, - short_circuit: bool = True, + self, + add: AdditionFormula, + dbl: DoublingFormula, + neg: NegationFormula, + scl: Optional[ScalingFormula] = None, + direction: ProcessingDirection = ProcessingDirection.LTR, + accumulation_order: AccumulationOrder = AccumulationOrder.PeqPR, + short_circuit: bool = True, ): super().__init__( - short_circuit=short_circuit, accumulation_order=accumulation_order, add=add, dbl=dbl, neg=neg, scl=scl + short_circuit=short_circuit, + accumulation_order=accumulation_order, + add=add, + dbl=dbl, + neg=neg, + scl=scl, ) self.direction = direction def __hash__(self): - return hash((BinaryNAFMultiplier, super().__hash__(), self.direction, self.accumulation_order)) + return hash( + ( + BinaryNAFMultiplier, + super().__hash__(), + self.direction, + self.accumulation_order, + ) + ) def __eq__(self, other): if not isinstance(other, BinaryNAFMultiplier): return False - return self.formulas == other.formulas and self.short_circuit == other.short_circuit and self.direction == other.direction and self.accumulation_order == other.accumulation_order + return ( + self.formulas == other.formulas + and self.short_circuit == other.short_circuit + and self.direction == other.direction + and self.accumulation_order == other.accumulation_order + ) def __repr__(self): return f"{self.__class__.__name__}({', '.join(map(str, self.formulas.values()))}, short_circuit={self.short_circuit}, direction={self.direction.name}, accumulation_order={self.accumulation_order.name})" @@ -125,29 +148,48 @@ class WindowNAFMultiplier(AccumulatorMultiplier, ScalarMultiplier): """The width of the window.""" def __init__( - self, - add: AdditionFormula, - dbl: DoublingFormula, - neg: NegationFormula, - width: int, - scl: Optional[ScalingFormula] = None, - accumulation_order: AccumulationOrder = AccumulationOrder.PeqPR, - precompute_negation: bool = False, - short_circuit: bool = True, + self, + add: AdditionFormula, + dbl: DoublingFormula, + neg: NegationFormula, + width: int, + scl: Optional[ScalingFormula] = None, + accumulation_order: AccumulationOrder = AccumulationOrder.PeqPR, + precompute_negation: bool = False, + short_circuit: bool = True, ): super().__init__( - short_circuit=short_circuit, accumulation_order=accumulation_order, add=add, dbl=dbl, neg=neg, scl=scl + short_circuit=short_circuit, + accumulation_order=accumulation_order, + add=add, + dbl=dbl, + neg=neg, + scl=scl, ) self.width = width self.precompute_negation = precompute_negation def __hash__(self): - return hash((WindowNAFMultiplier, super().__hash__(), self.width, self.precompute_negation, self.accumulation_order)) + return hash( + ( + WindowNAFMultiplier, + super().__hash__(), + self.width, + self.precompute_negation, + self.accumulation_order, + ) + ) def __eq__(self, other): if not isinstance(other, WindowNAFMultiplier): return False - return self.formulas == other.formulas and self.short_circuit == other.short_circuit and self.width == other.width and self.precompute_negation == other.precompute_negation and self.accumulation_order == other.accumulation_order + return ( + self.formulas == other.formulas + and self.short_circuit == other.short_circuit + and self.width == other.width + and self.precompute_negation == other.precompute_negation + and self.accumulation_order == other.accumulation_order + ) def __repr__(self): return f"{self.__class__.__name__}({', '.join(map(str, self.formulas.values()))}, short_circuit={self.short_circuit}, width={self.width}, precompute_negation={self.precompute_negation}, accumulation_order={self.accumulation_order.name})" diff --git a/pyecsca/ec/mult/window.py b/pyecsca/ec/mult/window.py index d4967e8..b003e40 100644 --- a/pyecsca/ec/mult/window.py +++ b/pyecsca/ec/mult/window.py @@ -3,8 +3,8 @@ from copy import copy from typing import Optional, MutableMapping from public import public -from ..params import DomainParameters -from .base import ( +from pyecsca.ec.params import DomainParameters +from pyecsca.ec.mult.base import ( ScalarMultiplier, AccumulationOrder, ScalarMultiplicationAction, @@ -12,14 +12,19 @@ from .base import ( ProcessingDirection, AccumulatorMultiplier, ) -from ..formula import ( +from pyecsca.ec.formula import ( AdditionFormula, DoublingFormula, ScalingFormula, NegationFormula, ) -from ..point import Point -from ..scalar import convert_base, sliding_window_rtl, sliding_window_ltr, booth_window +from pyecsca.ec.point import Point +from pyecsca.ec.scalar import ( + convert_base, + sliding_window_rtl, + sliding_window_ltr, + booth_window, +) @public @@ -61,7 +66,15 @@ class SlidingWindowMultiplier(AccumulatorMultiplier, ScalarMultiplier): self.recoding_direction = recoding_direction def __hash__(self): - return hash((SlidingWindowMultiplier, super().__hash__(), self.width, self.recoding_direction, self.accumulation_order)) + return hash( + ( + SlidingWindowMultiplier, + super().__hash__(), + self.width, + self.recoding_direction, + self.accumulation_order, + ) + ) def __eq__(self, other): if not isinstance(other, SlidingWindowMultiplier): @@ -150,7 +163,14 @@ class FixedWindowLTRMultiplier(AccumulatorMultiplier, ScalarMultiplier): self.m = m def __hash__(self): - return hash((FixedWindowLTRMultiplier, super().__hash__(), self.m, self.accumulation_order)) + return hash( + ( + FixedWindowLTRMultiplier, + super().__hash__(), + self.m, + self.accumulation_order, + ) + ) def __eq__(self, other): if not isinstance(other, FixedWindowLTRMultiplier): @@ -252,7 +272,15 @@ class WindowBoothMultiplier(AccumulatorMultiplier, ScalarMultiplier): self.precompute_negation = precompute_negation def __hash__(self): - return hash((WindowBoothMultiplier, super().__hash__(), self.width, self.precompute_negation, self.accumulation_order)) + return hash( + ( + WindowBoothMultiplier, + super().__hash__(), + self.width, + self.precompute_negation, + self.accumulation_order, + ) + ) def __eq__(self, other): if not isinstance(other, WindowBoothMultiplier): diff --git a/pyecsca/ec/op.py b/pyecsca/ec/op.py index 5f57bfa..250d6a3 100644 --- a/pyecsca/ec/op.py +++ b/pyecsca/ec/op.py @@ -14,7 +14,7 @@ from ast import ( Assign, operator as ast_operator, unaryop as ast_unaryop, - USub + USub, ) from enum import Enum from types import CodeType @@ -23,8 +23,8 @@ from typing import FrozenSet, cast, Any, Optional, Union, Tuple from astunparse import unparse from public import public -from .mod import Mod -from ..misc.utils import pexec +from pyecsca.ec.mod import Mod +from pyecsca.misc.utils import pexec @public @@ -148,7 +148,12 @@ class CodeOp: def __eq__(self, other): if not isinstance(other, CodeOp): return False - return self.left == other.left and self.right == other.right and self.operator == other.operator and self.result == other.result + return ( + self.left == other.left + and self.right == other.right + and self.operator == other.operator + and self.result == other.result + ) def __getstate__(self): state = {"code": unparse(self.code).strip()} diff --git a/pyecsca/ec/params.py b/pyecsca/ec/params.py index abcac46..5de7877 100644 --- a/pyecsca/ec/params.py +++ b/pyecsca/ec/params.py @@ -14,20 +14,20 @@ from importlib_resources import files from public import public -from ..misc.cache import sympify -from .coordinates import AffineCoordinateModel, CoordinateModel -from .curve import EllipticCurve -from .error import raise_unsatisified_assumption -from .mod import Mod -from .model import ( +from pyecsca.misc.cache import sympify +from pyecsca.ec.coordinates import AffineCoordinateModel, CoordinateModel +from pyecsca.ec.curve import EllipticCurve +from pyecsca.ec.error import raise_unsatisified_assumption +from pyecsca.ec.mod import Mod +from pyecsca.ec.model import ( CurveModel, ShortWeierstrassModel, MontgomeryModel, EdwardsModel, TwistedEdwardsModel, ) -from .point import Point, InfinityPoint -from ..misc.cfg import getconfig +from pyecsca.ec.point import Point, InfinityPoint +from pyecsca.misc.cfg import getconfig @public diff --git a/pyecsca/ec/point.py b/pyecsca/ec/point.py index 9549a15..e8d5d5f 100644 --- a/pyecsca/ec/point.py +++ b/pyecsca/ec/point.py @@ -4,10 +4,10 @@ from typing import Mapping, TYPE_CHECKING from public import public -from .context import ResultAction -from .coordinates import AffineCoordinateModel, CoordinateModel -from .mod import Mod, Undefined -from .op import CodeOp +from pyecsca.ec.context import ResultAction +from pyecsca.ec.coordinates import AffineCoordinateModel, CoordinateModel +from pyecsca.ec.mod import Mod, Undefined +from pyecsca.ec.op import CodeOp if TYPE_CHECKING: @@ -140,7 +140,7 @@ class Point: if randomized: lmbd = Mod.random(curve.prime) for var, value in result.items(): - result[var] = value * (lmbd**coordinate_model.homogweights[var]) + result[var] = value * (lmbd ** coordinate_model.homogweights[var]) return action.exit(Point(coordinate_model, **result)) def equals_affine(self, other: "Point") -> bool: @@ -226,8 +226,10 @@ class InfinityPoint(Point): return InfinityPoint(AffineCoordinateModel(self.coordinate_model.curve_model)) def to_model( - self, coordinate_model: CoordinateModel, curve: "EllipticCurve", - randomized: bool = False + self, + coordinate_model: CoordinateModel, + curve: "EllipticCurve", + randomized: bool = False, ) -> "InfinityPoint": return InfinityPoint(coordinate_model) diff --git a/pyecsca/ec/scalar.py b/pyecsca/ec/scalar.py index af5a6ab..5d20634 100644 --- a/pyecsca/ec/scalar.py +++ b/pyecsca/ec/scalar.py @@ -1,5 +1,5 @@ """Provides functions for computing various scalar representations (like NAF, or different bases).""" -from typing import List, Tuple, Literal +from typing import List from itertools import dropwhile from public import public diff --git a/pyecsca/ec/signature.py b/pyecsca/ec/signature.py index abad783..331af6e 100644 --- a/pyecsca/ec/signature.py +++ b/pyecsca/ec/signature.py @@ -5,12 +5,12 @@ from typing import Optional, Any from asn1crypto.core import Sequence, SequenceOf, Integer from public import public -from .context import Action -from .formula import AdditionFormula -from .mod import Mod -from .mult import ScalarMultiplier -from .params import DomainParameters -from .point import Point +from pyecsca.ec.context import Action +from pyecsca.ec.formula import AdditionFormula +from pyecsca.ec.mod import Mod +from pyecsca.ec.mult import ScalarMultiplier +from pyecsca.ec.params import DomainParameters +from pyecsca.ec.point import Point @public @@ -67,7 +67,9 @@ class ECDSAAction(Action): self.msg = msg def __repr__(self): - return f"{self.__class__.__name__}({self.params}, {self.hash_algo}, {self.msg!r})" + return ( + f"{self.__class__.__name__}({self.params}, {self.hash_algo}, {self.msg!r})" + ) @public diff --git a/pyecsca/ec/transformations.py b/pyecsca/ec/transformations.py index de1915c..20ecde7 100644 --- a/pyecsca/ec/transformations.py +++ b/pyecsca/ec/transformations.py @@ -4,12 +4,17 @@ from typing import Tuple, Generator from public import public from sympy import FF, symbols, Poly -from .coordinates import AffineCoordinateModel -from .curve import EllipticCurve -from .mod import Mod -from .model import ShortWeierstrassModel, MontgomeryModel, TwistedEdwardsModel, EdwardsModel -from .params import DomainParameters -from .point import InfinityPoint, Point +from pyecsca.ec.coordinates import AffineCoordinateModel +from pyecsca.ec.curve import EllipticCurve +from pyecsca.ec.mod import Mod +from pyecsca.ec.model import ( + ShortWeierstrassModel, + MontgomeryModel, + TwistedEdwardsModel, + EdwardsModel, +) +from pyecsca.ec.params import DomainParameters +from pyecsca.ec.point import InfinityPoint, Point def __map(params, param_names, map_parameters, map_point, model): @@ -40,13 +45,13 @@ def M2SW(params: DomainParameters) -> DomainParameters: :return: The converted domain parameters. """ if not isinstance(params.curve.model, MontgomeryModel) or not isinstance( - params.curve.coordinate_model, AffineCoordinateModel + params.curve.coordinate_model, AffineCoordinateModel ): raise ValueError def map_parameters(A, B): - a = (3 - A ** 2) / (3 * B ** 2) - b = (2 * A ** 3 - 9 * A) / (27 * B ** 3) + a = (3 - A**2) / (3 * B**2) + b = (2 * A**3 - 9 * A) / (27 * B**3) return {"a": a, "b": b} def map_point(A, B, pt, aff): @@ -54,9 +59,7 @@ def M2SW(params: DomainParameters) -> DomainParameters: v = pt.y / B return Point(aff, x=u, y=v) - return __map( - params, ("a", "b"), map_parameters, map_point, ShortWeierstrassModel() - ) + return __map(params, ("a", "b"), map_parameters, map_point, ShortWeierstrassModel()) @public @@ -68,7 +71,7 @@ def M2TE(params: DomainParameters) -> DomainParameters: :return: The converted domain parameters. """ if not isinstance(params.curve.model, MontgomeryModel) or not isinstance( - params.curve.coordinate_model, AffineCoordinateModel + params.curve.coordinate_model, AffineCoordinateModel ): raise ValueError @@ -94,13 +97,13 @@ def M2E(params: DomainParameters) -> DomainParameters: :return: The converted domain parameters. """ if not isinstance(params.curve.model, MontgomeryModel) or not isinstance( - params.curve.coordinate_model, AffineCoordinateModel + params.curve.coordinate_model, AffineCoordinateModel ): raise ValueError def map_parameters(A, B): c = (B / (A + 2)).sqrt() - d = (A ** 2 - 4) / (B ** 2) + d = (A**2 - 4) / (B**2) return {"c": c, "d": d} def map_point(A, B, pt, aff): @@ -120,7 +123,7 @@ def TE2M(params: DomainParameters) -> DomainParameters: :return: The converted domain parameters. """ if not isinstance(params.curve.model, TwistedEdwardsModel) or not isinstance( - params.curve.coordinate_model, AffineCoordinateModel + params.curve.coordinate_model, AffineCoordinateModel ): raise ValueError @@ -146,7 +149,7 @@ def TE2E(params: DomainParameters) -> DomainParameters: :return: The converted domain parameters. """ if not isinstance(params.curve.model, TwistedEdwardsModel) or not isinstance( - params.curve.coordinate_model, AffineCoordinateModel + params.curve.coordinate_model, AffineCoordinateModel ): raise ValueError @@ -172,13 +175,13 @@ def TE2SW(params: DomainParameters) -> DomainParameters: :return: The converted domain parameters. """ if not isinstance(params.curve.model, TwistedEdwardsModel) or not isinstance( - params.curve.coordinate_model, AffineCoordinateModel + params.curve.coordinate_model, AffineCoordinateModel ): raise ValueError def map_parameters(A, D): - a = -(A ** 2 + 14 * D * A + D ** 2) / 48 - b = (A + D) * (-A ** 2 + 34 * A * D - D ** 2) / 864 + a = -(A**2 + 14 * D * A + D**2) / 48 + b = (A + D) * (-(A**2) + 34 * A * D - D**2) / 864 return {"a": a, "b": b} def map_point(A, D, pt, aff): @@ -191,13 +194,13 @@ def TE2SW(params: DomainParameters) -> DomainParameters: def __sw_ab(params: DomainParameters) -> Generator[Tuple[Mod, Mod], None, None]: if not isinstance(params.curve.model, ShortWeierstrassModel) or not isinstance( - params.curve.coordinate_model, AffineCoordinateModel + params.curve.coordinate_model, AffineCoordinateModel ): raise ValueError ax = symbols("α") field = FF(params.curve.prime) rhs = Poly( - ax ** 3 + ax**3 + field(int(params.curve.parameters["a"])) * ax + field(int(params.curve.parameters["b"])), ax, @@ -205,12 +208,10 @@ def __sw_ab(params: DomainParameters) -> Generator[Tuple[Mod, Mod], None, None]: ) roots = rhs.ground_roots() if not roots: - raise ValueError( - "Curve cannot be transformed (x^3 + ax + b has no root)." - ) + raise ValueError("Curve cannot be transformed (x^3 + ax + b has no root).") for root in roots: alpha = Mod(int(root), params.curve.prime) - beta = (3 * alpha ** 2 + params.curve.parameters["a"]).sqrt() + beta = (3 * alpha**2 + params.curve.parameters["a"]).sqrt() yield alpha, beta @@ -277,14 +278,14 @@ def SW2E(params: DomainParameters) -> DomainParameters: """ for alpha, beta in __sw_ab(params): s = beta.inverse() - t = (s / (3 * s * alpha + 2)) + t = s / (3 * s * alpha + 2) if not t.is_residue(): continue t = t.sqrt() def map_parameters(a, b): c = t - d = -4 * a - 3 * alpha ** 2 + d = -4 * a - 3 * alpha**2 return {"c": c, "d": d} def map_point(a, b, pt, aff): diff --git a/pyecsca/misc/utils.py b/pyecsca/misc/utils.py index f19009e..060208f 100644 --- a/pyecsca/misc/utils.py +++ b/pyecsca/misc/utils.py @@ -4,7 +4,7 @@ from ast import parse from contextlib import contextmanager from typing import List, Any, Generator -from ..misc.cfg import getconfig, TemporaryConfig +from pyecsca.misc.cfg import getconfig, TemporaryConfig from concurrent.futures import ProcessPoolExecutor, as_completed, Future diff --git a/pyecsca/sca/attack/CPA.py b/pyecsca/sca/attack/CPA.py index 8d4687a..77c9abb 100644 --- a/pyecsca/sca/attack/CPA.py +++ b/pyecsca/sca/attack/CPA.py @@ -3,14 +3,14 @@ from scipy.stats import pearsonr import numpy as np from numpy.typing import NDArray -from ...ec.mult import ScalarMultiplier -from ...ec.point import Point -from ...ec.context import DefaultContext, local -from ...ec.params import DomainParameters -from ...ec.mod import Mod -from ..trace import Trace -from ..trace.plot import plot_trace -from ..attack.leakage_model import LeakageModel +from pyecsca.ec.mult import ScalarMultiplier +from pyecsca.ec.point import Point +from pyecsca.ec.context import DefaultContext, local +from pyecsca.ec.params import DomainParameters +from pyecsca.ec.mod import Mod +from pyecsca.sca.trace import Trace +from pyecsca.sca.trace.plot import plot_trace +from pyecsca.sca.attack.leakage_model import LeakageModel @public diff --git a/pyecsca/sca/attack/DPA.py b/pyecsca/sca/attack/DPA.py index d77b28b..661adc6 100644 --- a/pyecsca/sca/attack/DPA.py +++ b/pyecsca/sca/attack/DPA.py @@ -1,14 +1,14 @@ from typing import Tuple, Dict from public import public -from ...ec.mult import ScalarMultiplier -from ...ec.point import Point -from ...ec.context import DefaultContext, local -from ...ec.params import DomainParameters -from ..trace import Trace -from ..trace.combine import average, subtract -from ..trace.process import absolute -from ..trace.plot import plot_trace +from pyecsca.ec.mult import ScalarMultiplier +from pyecsca.ec.point import Point +from pyecsca.ec.context import DefaultContext, local +from pyecsca.ec.params import DomainParameters +from pyecsca.sca.trace import Trace +from pyecsca.sca.trace.combine import average, subtract +from pyecsca.sca.trace.process import absolute +from pyecsca.sca.trace.plot import plot_trace @public diff --git a/pyecsca/sca/attack/leakage_model.py b/pyecsca/sca/attack/leakage_model.py index 87f32f0..c1691d8 100644 --- a/pyecsca/sca/attack/leakage_model.py +++ b/pyecsca/sca/attack/leakage_model.py @@ -8,7 +8,7 @@ from typing import Literal, ClassVar from numpy.random import default_rng from public import public -from ...sca.trace import Trace +from pyecsca.sca.trace import Trace if sys.version_info[0] < 3 or sys.version_info[0] == 3 and sys.version_info[1] < 10: def hw(i): diff --git a/pyecsca/sca/re/base.py b/pyecsca/sca/re/base.py index 742e930..ca9b454 100644 --- a/pyecsca/sca/re/base.py +++ b/pyecsca/sca/re/base.py @@ -3,12 +3,13 @@ from typing import Optional, Any, Set from public import public -from .tree import Tree +from pyecsca.sca.re.tree import Tree @public class RE(ABC): """A base class for Reverse-Engineering methods.""" + tree: Optional[Tree] = None """The RE tree (if any).""" configs: Set[Any] diff --git a/pyecsca/sca/re/rpa.py b/pyecsca/sca/re/rpa.py index 03a4873..c055274 100644 --- a/pyecsca/sca/re/rpa.py +++ b/pyecsca/sca/re/rpa.py @@ -8,10 +8,10 @@ from typing import MutableMapping, Optional, Callable, List, Set, cast from sympy import FF, sympify, Poly, symbols -from .base import RE -from .tree import Tree, Map -from ...ec.coordinates import AffineCoordinateModel -from ...ec.formula import ( +from pyecsca.sca.re.base import RE +from pyecsca.sca.re.tree import Tree, Map +from pyecsca.ec.coordinates import AffineCoordinateModel +from pyecsca.ec.formula import ( FormulaAction, DoublingFormula, AdditionFormula, @@ -20,17 +20,17 @@ from ...ec.formula import ( DifferentialAdditionFormula, LadderFormula, ) -from ...ec.mod import Mod -from ...ec.mult import ( +from pyecsca.ec.mod import Mod +from pyecsca.ec.mult import ( ScalarMultiplicationAction, PrecomputationAction, ScalarMultiplier, ) -from ...ec.params import DomainParameters -from ...ec.model import ShortWeierstrassModel, MontgomeryModel -from ...ec.point import Point -from ...ec.context import Context, Action, local -from ...misc.utils import log, warn +from pyecsca.ec.params import DomainParameters +from pyecsca.ec.model import ShortWeierstrassModel, MontgomeryModel +from pyecsca.ec.point import Point +from pyecsca.ec.context import Context, Action, local +from pyecsca.misc.utils import log, warn @public @@ -209,6 +209,7 @@ def rpa_distinguish( @public class RPA(RE): """RPA-based RE.""" + params: Optional[DomainParameters] = None """The domain parameters to use.""" P0: Optional[Point] = None @@ -306,7 +307,9 @@ class RPA(RE): if not tree.precise: done += 1 if done > tries: - warn(f"Tried more than {tries} times. Aborting. Distinguishing may not be precise.") + warn( + f"Tried more than {tries} times. Aborting. Distinguishing may not be precise." + ) break else: continue @@ -327,7 +330,12 @@ class RPA(RE): :param majority: Query the oracle up to `majority` times and take the majority vote of the results. :return: The set of possible multipliers. """ - if self.tree is None or self.scalars is None or self.P0 is None or self.params is None: + if ( + self.tree is None + or self.scalars is None + or self.P0 is None + or self.params is None + ): raise ValueError("Need to build tree first.") if (majority % 2) == 0: diff --git a/pyecsca/sca/re/tree.py b/pyecsca/sca/re/tree.py index c035638..bab749e 100644 --- a/pyecsca/sca/re/tree.py +++ b/pyecsca/sca/re/tree.py @@ -51,7 +51,7 @@ import pandas as pd from public import public from anytree import RenderTree, NodeMixin, AbstractStyle, PreOrderIter -from ...misc.utils import log +from pyecsca.misc.utils import log @public diff --git a/pyecsca/sca/re/zvp.py b/pyecsca/sca/re/zvp.py index a712624..a697388 100644 --- a/pyecsca/sca/re/zvp.py +++ b/pyecsca/sca/re/zvp.py @@ -8,12 +8,12 @@ from public import public from astunparse import unparse from sympy import FF, Poly, Monomial, Symbol, Expr, sympify, symbols, div -from .rpa import MultipleContext -from ...ec.context import local -from ...ec.curve import EllipticCurve -from ...ec.model import CurveModel -from ...ec.divpoly import mult_by_n -from ...ec.formula import ( +from pyecsca.sca.re.rpa import MultipleContext +from pyecsca.ec.context import local +from pyecsca.ec.curve import EllipticCurve +from pyecsca.ec.model import CurveModel +from pyecsca.ec.divpoly import mult_by_n +from pyecsca.ec.formula import ( Formula, AdditionFormula, DoublingFormula, @@ -21,12 +21,12 @@ from ...ec.formula import ( LadderFormula, NegationFormula, ) -from ...ec.formula.fake import FakePoint, FakeFormula -from ...ec.formula.unroll import unroll_formula -from ...ec.mod import Mod -from ...ec.mult import ScalarMultiplier -from ...ec.params import DomainParameters -from ...ec.point import Point +from pyecsca.ec.formula.fake import FakePoint, FakeFormula +from pyecsca.ec.formula.unroll import unroll_formula +from pyecsca.ec.mod import Mod +from pyecsca.ec.mult import ScalarMultiplier +from pyecsca.ec.params import DomainParameters +from pyecsca.ec.point import Point has_pari = False @@ -146,7 +146,7 @@ def compute_factor_set( formula: Formula, affine: bool = True, filter_nonhomo: bool = True, - xonly: bool = False + xonly: bool = False, ) -> Set[Poly]: """ Compute a set of factors present in the :paramref:`~.compute_factor_set.formula`. @@ -163,7 +163,12 @@ def compute_factor_set( if affine: unrolled = map_to_affine(formula, unrolled) if xonly: - unrolled = list({(name, eliminate_y(poly, formula.coordinate_model.curve_model)) for name, poly in unrolled}) + unrolled = list( + { + (name, eliminate_y(poly, formula.coordinate_model.curve_model)) + for name, poly in unrolled + } + ) curve_params = set(formula.coordinate_model.curve_model.parameter_names) @@ -231,11 +236,10 @@ def symbolic_curve_equation(x: Symbol, model: CurveModel) -> Expr: :param model: The curve model to use. :return: The sympy expression of the "ysquared" curve polynomial. """ - parameters = { - name: symbols(name) - for name in model.parameter_names - } - return eval(compile(model.ysquared, "", mode="eval"), {"x": x, **parameters}) # eval is OK here, skipcq: PYL-W0123 + parameters = {name: symbols(name) for name in model.parameter_names} + return eval( + compile(model.ysquared, "", mode="eval"), {"x": x, **parameters} + ) # eval is OK here, skipcq: PYL-W0123 def curve_equation(x: Symbol, curve: EllipticCurve) -> Expr: @@ -247,7 +251,9 @@ def curve_equation(x: Symbol, curve: EllipticCurve) -> Expr: :param curve: The elliptic curve to use. :return: The sympy expression of the "ysquared" curve polynomial. """ - return eval(compile(curve.model.ysquared, "", mode="eval"), {"x": x, **curve.parameters}) # eval is OK here, skipcq: PYL-W0123 + return eval( + compile(curve.model.ysquared, "", mode="eval"), {"x": x, **curve.parameters} + ) # eval is OK here, skipcq: PYL-W0123 def subs_curve_equation(poly: Poly, curve: EllipticCurve) -> Poly: @@ -565,7 +571,7 @@ def solve_hard_dcp_cypari( for deg in range(polydeg + 1): monomial = pari.polcoef(polynomial, deg, x2) monomial *= num**deg - monomial *= den**(polydeg - deg) + monomial *= den ** (polydeg - deg) subspoly += monomial if subspoly == pari.zero(): return {_deterministic_point_x(curve)} diff --git a/pyecsca/sca/scope/base.py b/pyecsca/sca/scope/base.py index 08befda..b9d43af 100644 --- a/pyecsca/sca/scope/base.py +++ b/pyecsca/sca/scope/base.py @@ -4,7 +4,7 @@ from typing import Tuple, Sequence, Optional from public import public -from ..trace import Trace +from pyecsca.sca.trace import Trace @public diff --git a/pyecsca/sca/scope/chipwhisperer.py b/pyecsca/sca/scope/chipwhisperer.py index 3706c0e..ba11525 100644 --- a/pyecsca/sca/scope/chipwhisperer.py +++ b/pyecsca/sca/scope/chipwhisperer.py @@ -5,8 +5,8 @@ import numpy as np from chipwhisperer.capture.scopes.OpenADC import OpenADC from public import public -from .base import Scope, SampleType -from ..trace import Trace +from pyecsca.sca.scope.base import Scope, SampleType +from pyecsca.sca.trace import Trace @public diff --git a/pyecsca/sca/scope/picoscope_alt.py b/pyecsca/sca/scope/picoscope_alt.py index 900d796..86332c0 100644 --- a/pyecsca/sca/scope/picoscope_alt.py +++ b/pyecsca/sca/scope/picoscope_alt.py @@ -9,8 +9,8 @@ from picoscope.ps5000 import PS5000 from picoscope.ps6000 import PS6000 from public import public -from .base import Scope, SampleType -from ..trace import Trace +from pyecsca.sca.scope.base import Scope, SampleType +from pyecsca.sca.trace import Trace @public diff --git a/pyecsca/sca/scope/picoscope_sdk.py b/pyecsca/sca/scope/picoscope_sdk.py index 2981ca3..b04d6bd 100644 --- a/pyecsca/sca/scope/picoscope_sdk.py +++ b/pyecsca/sca/scope/picoscope_sdk.py @@ -31,8 +31,8 @@ except CannotFindPicoSDKError as exc: ps6000 = exc from public import public -from .base import Scope, SampleType -from ..trace import Trace +from pyecsca.sca.scope.base import Scope, SampleType +from pyecsca.sca.trace import Trace def adc2volt( diff --git a/pyecsca/sca/stacked_traces/combine.py b/pyecsca/sca/stacked_traces/combine.py index 4b03985..a55c18b 100644 --- a/pyecsca/sca/stacked_traces/combine.py +++ b/pyecsca/sca/stacked_traces/combine.py @@ -10,8 +10,8 @@ from math import sqrt from public import public from typing import Callable, Union, Tuple, Optional, cast, List -from ...sca.trace.trace import CombinedTrace -from ...sca.stacked_traces import StackedTraces +from pyecsca.sca.trace.trace import CombinedTrace +from pyecsca.sca.stacked_traces import StackedTraces TPB = Union[int, Tuple[int, ...]] CudaCTX = Tuple[devicearray.DeviceNDArray, ...] diff --git a/pyecsca/sca/stacked_traces/stacked_traces.py b/pyecsca/sca/stacked_traces/stacked_traces.py index f2c67fc..09169bd 100644 --- a/pyecsca/sca/stacked_traces/stacked_traces.py +++ b/pyecsca/sca/stacked_traces/stacked_traces.py @@ -4,7 +4,7 @@ import numpy as np from public import public from typing import Any, Mapping, Sequence -from ...sca.trace_set.base import TraceSet +from pyecsca.sca.trace_set.base import TraceSet @public diff --git a/pyecsca/sca/target/ISO7816.py b/pyecsca/sca/target/ISO7816.py index 63326ca..0af78db 100644 --- a/pyecsca/sca/target/ISO7816.py +++ b/pyecsca/sca/target/ISO7816.py @@ -6,7 +6,7 @@ from typing import Optional from public import public -from .base import Target +from pyecsca.sca.target.base import Target @public diff --git a/pyecsca/sca/target/PCSC.py b/pyecsca/sca/target/PCSC.py index 212651b..cd74149 100644 --- a/pyecsca/sca/target/PCSC.py +++ b/pyecsca/sca/target/PCSC.py @@ -7,7 +7,8 @@ from smartcard.System import readers from smartcard.pcsc.PCSCCardConnection import PCSCCardConnection from smartcard.pcsc.PCSCReader import PCSCReader -from .ISO7816 import ISO7816Target, CommandAPDU, ResponseAPDU, ISO7816, CardProtocol, CardConnectionException +from pyecsca.sca.target.ISO7816 import ISO7816Target, CommandAPDU, ResponseAPDU, ISO7816, CardProtocol, \ + CardConnectionException @public diff --git a/pyecsca/sca/target/binary.py b/pyecsca/sca/target/binary.py index 310b9e2..0dd22d5 100644 --- a/pyecsca/sca/target/binary.py +++ b/pyecsca/sca/target/binary.py @@ -5,7 +5,7 @@ from typing import Optional, Union, List from public import public -from .serial import SerialTarget +from pyecsca.sca.target.serial import SerialTarget @public diff --git a/pyecsca/sca/target/chipwhisperer.py b/pyecsca/sca/target/chipwhisperer.py index 784596a..28a2cb8 100644 --- a/pyecsca/sca/target/chipwhisperer.py +++ b/pyecsca/sca/target/chipwhisperer.py @@ -12,8 +12,8 @@ from chipwhisperer.capture.scopes import ScopeTypes from chipwhisperer.capture.targets.SimpleSerial import SimpleSerial from public import public -from .flash import Flashable -from .simpleserial import SimpleSerialTarget +from pyecsca.sca.target.flash import Flashable +from pyecsca.sca.target.simpleserial import SimpleSerialTarget @public diff --git a/pyecsca/sca/target/ectester.py b/pyecsca/sca/target/ectester.py index 3f6bd57..ec00502 100644 --- a/pyecsca/sca/target/ectester.py +++ b/pyecsca/sca/target/ectester.py @@ -9,11 +9,18 @@ from typing import Optional, Mapping, List, Union from public import public -from .ISO7816 import CommandAPDU, ResponseAPDU, ISO7816, ISO7816Target, CardProtocol, CardConnectionException -from . import has_leia, has_pyscard -from ...ec.model import ShortWeierstrassModel -from ...ec.params import DomainParameters -from ...ec.point import Point +from pyecsca.sca.target.ISO7816 import ( + CommandAPDU, + ResponseAPDU, + ISO7816, + ISO7816Target, + CardProtocol, + CardConnectionException, +) +from pyecsca.sca.target import has_leia, has_pyscard +from pyecsca.ec.model import ShortWeierstrassModel +from pyecsca.ec.params import DomainParameters +from pyecsca.ec.point import Point class ShiftableFlag(IntFlag): # pragma: no cover @@ -248,7 +255,7 @@ class Response(ABC): # pragma: no cover offset = 0 for i in range(num_sw): if len(resp.data) >= offset + 2: - self.sws[i] = int.from_bytes(resp.data[offset: offset + 2], "big") + self.sws[i] = int.from_bytes(resp.data[offset : offset + 2], "big") offset += 2 if self.sws[i] != ISO7816.SW_NO_ERROR: self.success = False @@ -265,13 +272,13 @@ class Response(ABC): # pragma: no cover self.success = False self.error = True break - param_len = int.from_bytes(resp.data[offset: offset + 2], "big") + param_len = int.from_bytes(resp.data[offset : offset + 2], "big") offset += 2 if len(resp.data) < offset + param_len: self.success = False self.error = True break - self.params[i] = resp.data[offset: offset + param_len] + self.params[i] = resp.data[offset : offset + param_len] offset += param_len def __repr__(self): @@ -343,11 +350,11 @@ class ExportResponse(Response): # pragma: no cover parameters: ParameterEnum def __init__( - self, - resp: ResponseAPDU, - keypair: KeypairEnum, - key: KeyEnum, - params: ParameterEnum, + self, + resp: ResponseAPDU, + keypair: KeypairEnum, + key: KeyEnum, + params: ParameterEnum, ): self.keypair = keypair self.key = key @@ -473,31 +480,31 @@ class InfoResponse(Response): # pragma: no cover super().__init__(resp, 1, 0) offset = 2 - version_len = int.from_bytes(resp.data[offset: offset + 2], "big") + version_len = int.from_bytes(resp.data[offset : offset + 2], "big") offset += 2 - self.version = resp.data[offset: offset + version_len].decode() + self.version = resp.data[offset : offset + version_len].decode() offset += version_len self.base = AppletBaseEnum( - int.from_bytes(resp.data[offset: offset + 2], "big") + int.from_bytes(resp.data[offset : offset + 2], "big") ) offset += 2 - system_version = int.from_bytes(resp.data[offset: offset + 2], "big") + system_version = int.from_bytes(resp.data[offset : offset + 2], "big") system_major = system_version >> 8 system_minor = system_version & 0xFF minor_size = 1 if system_minor == 0 else ceil(log(system_minor, 10)) self.system_version = system_major + system_minor / (minor_size * 10) offset += 2 self.object_deletion_supported = ( - int.from_bytes(resp.data[offset: offset + 2], "big") == 1 + int.from_bytes(resp.data[offset : offset + 2], "big") == 1 ) offset += 2 - self.buf_len = int.from_bytes(resp.data[offset: offset + 2], "big") + self.buf_len = int.from_bytes(resp.data[offset : offset + 2], "big") offset += 2 - self.ram1_len = int.from_bytes(resp.data[offset: offset + 2], "big") + self.ram1_len = int.from_bytes(resp.data[offset : offset + 2], "big") offset += 2 - self.ram2_len = int.from_bytes(resp.data[offset: offset + 2], "big") + self.ram2_len = int.from_bytes(resp.data[offset : offset + 2], "big") offset += 2 - self.apdu_len = int.from_bytes(resp.data[offset: offset + 2], "big") + self.apdu_len = int.from_bytes(resp.data[offset : offset + 2], "big") offset += 2 def __repr__(self): @@ -538,7 +545,7 @@ class ECTesterTarget(ISO7816Target, ABC): # pragma: no cover chunk_length = 255 if chunk_start + chunk_length > len(data): chunk_length = len(data) - chunk_start - chunk = data[chunk_start: chunk_start + chunk_length] + chunk = data[chunk_start : chunk_start + chunk_length] chunk_apdu = CommandAPDU( self.CLA_ECTESTER, InstructionEnum.INS_BUFFER, 0, 0, chunk ) @@ -554,7 +561,7 @@ class ECTesterTarget(ISO7816Target, ABC): # pragma: no cover return resp def select_applet( - self, latest_version: bytes = AID_CURRENT_VERSION, count_back: int = 10 + self, latest_version: bytes = AID_CURRENT_VERSION, count_back: int = 10 ) -> bool: """ Select the *ECTester* applet, with a specified version or older. @@ -565,7 +572,11 @@ class ECTesterTarget(ISO7816Target, ABC): # pragma: no cover """ version_bytes = bytearray(latest_version) for _ in range(count_back): - for aid_suffix in (self.AID_SUFFIX_304, self.AID_SUFFIX_222, self.AID_SUFFIX_221): + for aid_suffix in ( + self.AID_SUFFIX_304, + self.AID_SUFFIX_222, + self.AID_SUFFIX_221, + ): aid = self.AID_PREFIX + version_bytes + aid_suffix if self.select(aid): return True @@ -587,7 +598,7 @@ class ECTesterTarget(ISO7816Target, ABC): # pragma: no cover @staticmethod def encode_parameters( - params: ParameterEnum, obj: Union[DomainParameters, Point, int] + params: ParameterEnum, obj: Union[DomainParameters, Point, int] ) -> Mapping[ParameterEnum, bytes]: """Encode values from `obj` into the byte parameters that the **ECTester** applet expects.""" @@ -600,7 +611,7 @@ class ECTesterTarget(ISO7816Target, ABC): # pragma: no cover result = {} if isinstance(obj, DomainParameters) and isinstance( - obj.curve.model, ShortWeierstrassModel + obj.curve.model, ShortWeierstrassModel ): for param in params & ParameterEnum.DOMAIN_FP: if param == ParameterEnum.G: @@ -620,7 +631,7 @@ class ECTesterTarget(ISO7816Target, ABC): # pragma: no cover result[param] = convert_point(obj) elif isinstance(obj, int): for param in params & ( - (ParameterEnum.DOMAIN_FP ^ ParameterEnum.G) | ParameterEnum.S + (ParameterEnum.DOMAIN_FP ^ ParameterEnum.G) | ParameterEnum.S ): result[param] = convert_int(obj) else: @@ -664,11 +675,11 @@ class ECTesterTarget(ISO7816Target, ABC): # pragma: no cover return AllocateSigResponse(resp) def allocate( - self, - keypair: KeypairEnum, - builder: KeyBuildEnum, - key_length: int, - key_class: KeyClassEnum, + self, + keypair: KeypairEnum, + builder: KeyBuildEnum, + key_length: int, + key_class: KeyClassEnum, ) -> AllocateResponse: """ Send the Allocate KeyPair command. @@ -703,11 +714,11 @@ class ECTesterTarget(ISO7816Target, ABC): # pragma: no cover return ClearResponse(resp, keypair) def set( - self, - keypair: KeypairEnum, - curve: CurveEnum, - params: ParameterEnum, - values: Optional[Mapping[ParameterEnum, bytes]] = None, + self, + keypair: KeypairEnum, + curve: CurveEnum, + params: ParameterEnum, + values: Optional[Mapping[ParameterEnum, bytes]] = None, ) -> SetResponse: """ Send the Set command. @@ -749,11 +760,11 @@ class ECTesterTarget(ISO7816Target, ABC): # pragma: no cover return SetResponse(resp, keypair) def transform( - self, - keypair: KeypairEnum, - key: KeyEnum, - params: ParameterEnum, - transformation: TransformationEnum, + self, + keypair: KeypairEnum, + key: KeyEnum, + params: ParameterEnum, + transformation: TransformationEnum, ) -> TransformResponse: """ Send the Transform command. @@ -790,7 +801,7 @@ class ECTesterTarget(ISO7816Target, ABC): # pragma: no cover return GenerateResponse(resp, keypair) def export( - self, keypair: KeypairEnum, key: KeyEnum, params: ParameterEnum + self, keypair: KeypairEnum, key: KeyEnum, params: ParameterEnum ) -> ExportResponse: """ Send the Export command. @@ -812,12 +823,12 @@ class ECTesterTarget(ISO7816Target, ABC): # pragma: no cover return ExportResponse(resp, keypair, key, params) def ecdh( - self, - pubkey: KeypairEnum, - privkey: KeypairEnum, - export: bool, - transformation: TransformationEnum, - ka_type: KeyAgreementEnum, + self, + pubkey: KeypairEnum, + privkey: KeypairEnum, + export: bool, + transformation: TransformationEnum, + ka_type: KeyAgreementEnum, ) -> ECDHResponse: """ Send the ECDH command. @@ -843,12 +854,12 @@ class ECTesterTarget(ISO7816Target, ABC): # pragma: no cover return ECDHResponse(resp, export) def ecdh_direct( - self, - privkey: KeypairEnum, - export: bool, - transformation: TransformationEnum, - ka_type: KeyAgreementEnum, - pubkey: bytes, + self, + privkey: KeypairEnum, + export: bool, + transformation: TransformationEnum, + ka_type: KeyAgreementEnum, + pubkey: bytes, ) -> ECDHResponse: """ Send the ECDH direct command. @@ -875,7 +886,7 @@ class ECTesterTarget(ISO7816Target, ABC): # pragma: no cover return ECDHResponse(resp, export) def ecdsa( - self, keypair: KeypairEnum, export: bool, sig_type: SignatureEnum, data: bytes + self, keypair: KeypairEnum, export: bool, sig_type: SignatureEnum, data: bytes ) -> ECDSAResponse: """ Send the ECDSA command. @@ -898,7 +909,7 @@ class ECTesterTarget(ISO7816Target, ABC): # pragma: no cover return ECDSAResponse(resp, export) def ecdsa_sign( - self, keypair: KeypairEnum, export: bool, sig_type: SignatureEnum, data: bytes + self, keypair: KeypairEnum, export: bool, sig_type: SignatureEnum, data: bytes ) -> ECDSAResponse: """ Send the ECDSA sign command. @@ -921,7 +932,7 @@ class ECTesterTarget(ISO7816Target, ABC): # pragma: no cover return ECDSAResponse(resp, export) def ecdsa_verify( - self, keypair: KeypairEnum, sig_type: SignatureEnum, sig: bytes, data: bytes + self, keypair: KeypairEnum, sig_type: SignatureEnum, sig: bytes, data: bytes ) -> ECDSAResponse: """ Send the ECDSA verify command. @@ -984,17 +995,20 @@ class ECTesterTarget(ISO7816Target, ABC): # pragma: no cover if has_pyscard: - from .PCSC import PCSCTarget + from pyecsca.sca.target.PCSC import PCSCTarget @public class ECTesterTargetPCSC(ECTesterTarget, PCSCTarget): """An ECTester-applet-based target that is connected via a PCSC-compatible reader.""" + pass + if has_leia: - from .leia import LEIATarget + from pyecsca.sca.target.leia import LEIATarget @public class ECTesterTargetLEIA(ECTesterTarget, LEIATarget): """An ECTester-applet-based target that is connected via the LEIA board.""" + pass diff --git a/pyecsca/sca/target/leakage.py b/pyecsca/sca/target/leakage.py index 1f6e2b0..c832028 100644 --- a/pyecsca/sca/target/leakage.py +++ b/pyecsca/sca/target/leakage.py @@ -2,20 +2,20 @@ import numpy as np from typing import Optional, Tuple from public import public -from ...ec.coordinates import CoordinateModel -from ...ec.mod import Mod -from ...ec.model import CurveModel -from ...ec.params import DomainParameters -from ...ec.point import Point -from ...ec.mult import ScalarMultiplier -from ...ec.key_generation import KeyGeneration -from ...ec.key_agreement import KeyAgreement -from ...ec.signature import Signature, SignatureResult -from ...ec.formula import FormulaAction -from ...ec.context import DefaultContext, local -from ..attack import LeakageModel -from ..trace import Trace -from .base import Target +from pyecsca.ec.coordinates import CoordinateModel +from pyecsca.ec.mod import Mod +from pyecsca.ec.model import CurveModel +from pyecsca.ec.params import DomainParameters +from pyecsca.ec.point import Point +from pyecsca.ec.mult import ScalarMultiplier +from pyecsca.ec.key_generation import KeyGeneration +from pyecsca.ec.key_agreement import KeyAgreement +from pyecsca.ec.signature import Signature, SignatureResult +from pyecsca.ec.formula import FormulaAction +from pyecsca.ec.context import DefaultContext, local +from pyecsca.sca.attack import LeakageModel +from pyecsca.sca.trace import Trace +from pyecsca.sca.target.base import Target @public diff --git a/pyecsca/sca/target/leia.py b/pyecsca/sca/target/leia.py index f4d5643..8dab7df 100644 --- a/pyecsca/sca/target/leia.py +++ b/pyecsca/sca/target/leia.py @@ -3,7 +3,8 @@ from typing import Optional from smartleia import LEIA, create_APDU_from_bytes, T -from .ISO7816 import ISO7816Target, CommandAPDU, ResponseAPDU, ISO7816, CardProtocol, CardConnectionException +from pyecsca.sca.target.ISO7816 import ISO7816Target, CommandAPDU, ResponseAPDU, ISO7816, CardProtocol, \ + CardConnectionException class LEIATarget(ISO7816Target): # pragma: no cover diff --git a/pyecsca/sca/target/serial.py b/pyecsca/sca/target/serial.py index 3b81851..62dea45 100644 --- a/pyecsca/sca/target/serial.py +++ b/pyecsca/sca/target/serial.py @@ -3,7 +3,7 @@ from abc import abstractmethod from public import public -from .base import Target +from pyecsca.sca.target.base import Target @public diff --git a/pyecsca/sca/target/simpleserial.py b/pyecsca/sca/target/simpleserial.py index edc543e..f13a0a6 100644 --- a/pyecsca/sca/target/simpleserial.py +++ b/pyecsca/sca/target/simpleserial.py @@ -5,7 +5,7 @@ from typing import Mapping, Union from public import public -from .serial import SerialTarget +from pyecsca.sca.target.serial import SerialTarget @public diff --git a/pyecsca/sca/trace/align.py b/pyecsca/sca/trace/align.py index 71815b8..e1d3669 100644 --- a/pyecsca/sca/trace/align.py +++ b/pyecsca/sca/trace/align.py @@ -5,8 +5,8 @@ from fastdtw import fastdtw, dtw from public import public from typing import List, Callable, Tuple -from .process import normalize -from .trace import Trace +from pyecsca.sca.trace.process import normalize +from pyecsca.sca.trace.trace import Trace def _align_reference( @@ -39,7 +39,7 @@ def align_correlation( reference_offset: int, reference_length: int, max_offset: int, - min_correlation: float = 0.5 + min_correlation: float = 0.5, ) -> Tuple[List[Trace], List[int]]: """ Align :paramref:`~.align_correlation.traces` to the :paramref:`~.align_correlation.reference` trace using correlation. @@ -92,7 +92,7 @@ def align_peaks( *traces: Trace, reference_offset: int, reference_length: int, - max_offset: int + max_offset: int, ) -> Tuple[List[Trace], List[int]]: """ Align :paramref:`~.align_correlation.traces` to the :paramref:`~.align_correlation.reference` trace using peaks. @@ -133,7 +133,7 @@ def align_offset( reference_length: int, max_offset: int, dist_func: Callable[[np.ndarray, np.ndarray], float], - max_dist: float = float("inf") + max_dist: float = float("inf"), ) -> Tuple[List[Trace], List[int]]: """ Align :paramref:`~.align_correlation.traces` to the :paramref:`~.align_correlation.reference` trace using a distance function. @@ -183,7 +183,7 @@ def align_sad( *traces: Trace, reference_offset: int, reference_length: int, - max_offset: int + max_offset: int, ) -> Tuple[List[Trace], List[int]]: """ Align :paramref:`~.align_correlation.traces` to the :paramref:`~.align_correlation.reference` trace using Sum of Absolute Differences. @@ -209,7 +209,7 @@ def align_sad( reference_offset=reference_offset, reference_length=reference_length, max_offset=max_offset, - dist_func=sad + dist_func=sad, ) diff --git a/pyecsca/sca/trace/combine.py b/pyecsca/sca/trace/combine.py index 42e8b1b..9997a83 100644 --- a/pyecsca/sca/trace/combine.py +++ b/pyecsca/sca/trace/combine.py @@ -4,7 +4,7 @@ from typing import Callable, Tuple import numpy as np from public import public -from .trace import Trace, CombinedTrace +from pyecsca.sca.trace.trace import Trace, CombinedTrace @public diff --git a/pyecsca/sca/trace/edit.py b/pyecsca/sca/trace/edit.py index 47b455e..7d50188 100644 --- a/pyecsca/sca/trace/edit.py +++ b/pyecsca/sca/trace/edit.py @@ -3,7 +3,7 @@ import numpy as np from public import public from typing import Union, Tuple, Any, Optional -from .trace import Trace +from pyecsca.sca.trace.trace import Trace @public diff --git a/pyecsca/sca/trace/filter.py b/pyecsca/sca/trace/filter.py index 40ec13e..17361b9 100644 --- a/pyecsca/sca/trace/filter.py +++ b/pyecsca/sca/trace/filter.py @@ -3,7 +3,7 @@ from public import public from scipy.signal import butter, lfilter from typing import Union, Tuple -from .trace import Trace +from pyecsca.sca.trace.trace import Trace def _filter_any( diff --git a/pyecsca/sca/trace/match.py b/pyecsca/sca/trace/match.py index ae41dff..8a1b9bb 100644 --- a/pyecsca/sca/trace/match.py +++ b/pyecsca/sca/trace/match.py @@ -4,9 +4,9 @@ from scipy.signal import find_peaks from public import public from typing import List -from .process import normalize -from .edit import trim -from .trace import Trace +from pyecsca.sca.trace.process import normalize +from pyecsca.sca.trace.edit import trim +from pyecsca.sca.trace.trace import Trace @public diff --git a/pyecsca/sca/trace/plot.py b/pyecsca/sca/trace/plot.py index d89310d..c12840b 100644 --- a/pyecsca/sca/trace/plot.py +++ b/pyecsca/sca/trace/plot.py @@ -5,7 +5,7 @@ import holoviews as hv from holoviews.operation.datashader import datashade from public import public -from .trace import Trace +from pyecsca.sca.trace.trace import Trace @public diff --git a/pyecsca/sca/trace/process.py b/pyecsca/sca/trace/process.py index 92a6296..1851e10 100644 --- a/pyecsca/sca/trace/process.py +++ b/pyecsca/sca/trace/process.py @@ -5,7 +5,7 @@ import numpy as np from scipy.signal import convolve from public import public -from .trace import Trace +from pyecsca.sca.trace.trace import Trace @public diff --git a/pyecsca/sca/trace/sampling.py b/pyecsca/sca/trace/sampling.py index b04ec5e..2c39e4d 100644 --- a/pyecsca/sca/trace/sampling.py +++ b/pyecsca/sca/trace/sampling.py @@ -5,7 +5,7 @@ import numpy as np from public import public from scipy.signal import decimate -from .trace import Trace +from pyecsca.sca.trace.trace import Trace @public diff --git a/pyecsca/sca/trace/test.py b/pyecsca/sca/trace/test.py index 8a0ddb9..c7bbd95 100644 --- a/pyecsca/sca/trace/test.py +++ b/pyecsca/sca/trace/test.py @@ -5,9 +5,9 @@ import numpy as np from public import public from scipy.stats import ttest_ind, ks_2samp, t -from .trace import Trace, CombinedTrace -from .combine import average_and_variance -from .edit import trim +from pyecsca.sca.trace.trace import Trace, CombinedTrace +from pyecsca.sca.trace.combine import average_and_variance +from pyecsca.sca.trace.edit import trim def _ttest_func( diff --git a/pyecsca/sca/trace/trace.py b/pyecsca/sca/trace/trace.py index dbab02d..a609ecb 100644 --- a/pyecsca/sca/trace/trace.py +++ b/pyecsca/sca/trace/trace.py @@ -17,7 +17,10 @@ class Trace: samples: ndarray def __init__( - self, samples: ndarray, meta: Optional[Mapping[str, Any]] = None, trace_set: Any = None + self, + samples: ndarray, + meta: Optional[Mapping[str, Any]] = None, + trace_set: Any = None, ): """ Construct a new trace. @@ -104,8 +107,10 @@ class Trace: def __deepcopy__(self, memodict): return Trace( - deepcopy(self.samples, memo=memodict) if isinstance(self.samples, np.ndarray) else np.array(self.samples), - deepcopy(self.meta, memo=memodict) + deepcopy(self.samples, memo=memodict) + if isinstance(self.samples, np.ndarray) + else np.array(self.samples), + deepcopy(self.meta, memo=memodict), ) def __repr__(self): diff --git a/pyecsca/sca/trace_set/base.py b/pyecsca/sca/trace_set/base.py index 99094bc..0f605e4 100644 --- a/pyecsca/sca/trace_set/base.py +++ b/pyecsca/sca/trace_set/base.py @@ -4,7 +4,7 @@ from typing import List, Union, BinaryIO from public import public -from ..trace import Trace +from pyecsca.sca.trace import Trace @public diff --git a/pyecsca/sca/trace_set/chipwhisperer.py b/pyecsca/sca/trace_set/chipwhisperer.py index 8ff20ea..564e1cd 100644 --- a/pyecsca/sca/trace_set/chipwhisperer.py +++ b/pyecsca/sca/trace_set/chipwhisperer.py @@ -7,8 +7,8 @@ from typing import Union, BinaryIO import numpy as np from public import public -from .base import TraceSet -from ..trace import Trace +from pyecsca.sca.trace_set.base import TraceSet +from pyecsca.sca.trace import Trace @public diff --git a/pyecsca/sca/trace_set/hdf5.py b/pyecsca/sca/trace_set/hdf5.py index 88c10a0..62690ae 100644 --- a/pyecsca/sca/trace_set/hdf5.py +++ b/pyecsca/sca/trace_set/hdf5.py @@ -16,8 +16,8 @@ import numpy as np from public import public from copy import deepcopy -from .base import TraceSet -from .. import Trace +from pyecsca.sca.trace_set.base import TraceSet +from pyecsca.sca import Trace @public diff --git a/pyecsca/sca/trace_set/inspector.py b/pyecsca/sca/trace_set/inspector.py index e945409..3ed4e2b 100644 --- a/pyecsca/sca/trace_set/inspector.py +++ b/pyecsca/sca/trace_set/inspector.py @@ -8,8 +8,8 @@ from typing import Union, Optional, BinaryIO import numpy as np from public import public -from .base import TraceSet -from ..trace import Trace +from pyecsca.sca.trace_set.base import TraceSet +from pyecsca.sca.trace import Trace @public diff --git a/pyecsca/sca/trace_set/pickle.py b/pyecsca/sca/trace_set/pickle.py index fdb65fe..0134c63 100644 --- a/pyecsca/sca/trace_set/pickle.py +++ b/pyecsca/sca/trace_set/pickle.py @@ -10,7 +10,7 @@ from typing import Union, BinaryIO from public import public -from .base import TraceSet +from pyecsca.sca.trace_set.base import TraceSet @public |
