From eccc58127b4c0c10f50e4d05e699d3585391e8a1 Mon Sep 17 00:00:00 2001 From: J08nY Date: Thu, 13 Mar 2025 19:38:06 +0100 Subject: Add "bits" param to scalarmults to have control over their range. --- pyecsca/ec/countermeasures.py | 8 ++++++-- pyecsca/ec/mult/base.py | 6 +++++- pyecsca/ec/mult/binary.py | 4 ++-- pyecsca/ec/mult/comb.py | 14 +++++++------- pyecsca/ec/mult/fake.py | 2 +- pyecsca/ec/mult/fixed.py | 12 ++++++------ pyecsca/ec/mult/ladder.py | 7 ++++--- pyecsca/ec/mult/naf.py | 8 ++++---- pyecsca/ec/mult/window.py | 14 +++++++------- 9 files changed, 42 insertions(+), 33 deletions(-) (limited to 'pyecsca/ec') diff --git a/pyecsca/ec/countermeasures.py b/pyecsca/ec/countermeasures.py index 8a479b6..19afb06 100644 --- a/pyecsca/ec/countermeasures.py +++ b/pyecsca/ec/countermeasures.py @@ -70,6 +70,11 @@ class GroupScalarRandomization(ScalarMultiplierCountermeasure): super().__init__(mult) self.rand_bits = rand_bits + def init(self, params: DomainParameters, point: Point): + self.params = params + self.point = point + self.mult.init(self.params, self.point, bits=params.full_order.bit_length() + self.rand_bits) + def multiply(self, scalar: int) -> Point: if self.params is None or self.point is None: raise ValueError("Not initialized.") @@ -189,8 +194,7 @@ class EuclideanSplitting(ScalarMultiplierCountermeasure): if self.params is None or self.point is None: raise ValueError("Not initialized.") with ScalarMultiplicationAction(self.point, self.params, scalar) as action: - order = self.params.order - half_bits = order.bit_length() // 2 + half_bits = self.params.order.bit_length() // 2 r = Mod.random(1 << half_bits) R = self.mult.multiply(int(r)) diff --git a/pyecsca/ec/mult/base.py b/pyecsca/ec/mult/base.py index f7a8c5b..15f2fd5 100644 --- a/pyecsca/ec/mult/base.py +++ b/pyecsca/ec/mult/base.py @@ -87,6 +87,7 @@ class ScalarMultiplier(ABC): """All formulas the multiplier was initialized with.""" _params: DomainParameters _point: Point + _bits: int _initialized: bool = False def __init__(self, short_circuit: bool = True, **formulas: Optional[Formula]): @@ -202,7 +203,7 @@ class ScalarMultiplier(ABC): def __repr__(self): return f"{self.__class__.__name__}({', '.join(map(str, self.formulas.values()))}, short_circuit={self.short_circuit})" - def init(self, params: DomainParameters, point: Point): + def init(self, params: DomainParameters, point: Point, bits: Optional[int] = None): """ Initialize the scalar multiplier with :paramref:`~.init.params` and a :paramref:`~.init.point`. @@ -211,6 +212,8 @@ class ScalarMultiplier(ABC): :param params: The domain parameters to initialize the multiplier with. :param point: The point to initialize the multiplier with. + :param bits: The number of bits to use in the scalar multiplication (i.e. no scalar will be larger than 2^bits). + The default is the bit length of the full order of the curve (including cofactor). """ coord_model = set(self.formulas.values()).pop().coordinate_model if ( @@ -222,6 +225,7 @@ class ScalarMultiplier(ABC): ) self._params = params self._point = point + self._bits = bits if bits is not None else params.full_order.bit_length() self._initialized = True @abstractmethod diff --git a/pyecsca/ec/mult/binary.py b/pyecsca/ec/mult/binary.py index 5b6bed7..f0cb5ac 100644 --- a/pyecsca/ec/mult/binary.py +++ b/pyecsca/ec/mult/binary.py @@ -94,7 +94,7 @@ class DoubleAndAddMultiplier(AccumulatorMultiplier, ScalarMultiplier, ABC): if self.complete: q = self._point r = copy(self._params.curve.neutral) - top = self._params.order.bit_length() - 1 + top = self._bits - 1 else: q = copy(self._point) r = copy(self._point) @@ -112,7 +112,7 @@ class DoubleAndAddMultiplier(AccumulatorMultiplier, ScalarMultiplier, ABC): q = self._point r = copy(self._params.curve.neutral) if self.complete: - top = self._params.order.bit_length() + top = self._bits else: top = scalar.bit_length() for _ in range(top): diff --git a/pyecsca/ec/mult/comb.py b/pyecsca/ec/mult/comb.py index 35d1678..1a6c0c2 100644 --- a/pyecsca/ec/mult/comb.py +++ b/pyecsca/ec/mult/comb.py @@ -85,10 +85,10 @@ class BGMWMultiplier(AccumulatorMultiplier, PrecompMultiplier, ScalarMultiplier) 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})" - def init(self, params: DomainParameters, point: Point): + def init(self, params: DomainParameters, point: Point, bits: Optional[int] = None): with PrecomputationAction(params, point) as action: - super().init(params, point) - d = ceil(params.order.bit_length() / self.width) + super().init(params, point, bits) + d = ceil(self._bits / self.width) self._points = {} current_point = point for i in range(d): @@ -179,10 +179,10 @@ class CombMultiplier(AccumulatorMultiplier, PrecompMultiplier, ScalarMultiplier) 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})" - def init(self, params: DomainParameters, point: Point): + def init(self, params: DomainParameters, point: Point, bits: Optional[int] = None): with PrecomputationAction(params, point) as action: - super().init(params, point) - d = ceil(params.order.bit_length() / self.width) + super().init(params, point, bits) + d = ceil(self._bits / self.width) base_points = {} current_point = point for i in range(self.width): @@ -208,7 +208,7 @@ class CombMultiplier(AccumulatorMultiplier, PrecompMultiplier, ScalarMultiplier) if scalar == 0: return action.exit(copy(self._params.curve.neutral)) q = copy(self._params.curve.neutral) - d = ceil(self._params.order.bit_length() / self.width) + d = ceil(self._bits / self.width) recoded = convert_base(scalar, 2**d) if len(recoded) != self.width: recoded.extend([0] * (self.width - len(recoded))) diff --git a/pyecsca/ec/mult/fake.py b/pyecsca/ec/mult/fake.py index f89d622..391696b 100644 --- a/pyecsca/ec/mult/fake.py +++ b/pyecsca/ec/mult/fake.py @@ -9,7 +9,7 @@ from pyecsca.ec.params import DomainParameters def fake_mult(mult_class: Type[ScalarMultiplier], mult_factory: Callable, params: DomainParameters) -> ScalarMultiplier: """ - Get a multiplier with FakeFormulas. + Get a multiplier with `FakeFormula`s. :param mult_class: The class of the scalar multiplier to use. :param mult_factory: A callable that takes the formulas and instantiates the multiplier. diff --git a/pyecsca/ec/mult/fixed.py b/pyecsca/ec/mult/fixed.py index 2c01648..070aaec 100644 --- a/pyecsca/ec/mult/fixed.py +++ b/pyecsca/ec/mult/fixed.py @@ -90,20 +90,20 @@ class FullPrecompMultiplier(AccumulatorMultiplier, PrecompMultiplier, ScalarMult 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})" - def init(self, params: DomainParameters, point: Point): + def init(self, params: DomainParameters, point: Point, bits: Optional[int] = None): with PrecomputationAction(params, point) as action: - super().init(params, point) + super().init(params, point, bits) self._points = {} current_point = point - for i in range(params.order.bit_length() + 1): + for i in range(self._bits + 1): self._points[i] = current_point - if i != params.order.bit_length(): + if i != self._bits: current_point = self._dbl(current_point) action.exit(self._points) def _ltr(self, scalar: int) -> Point: if self.complete: - top = self._params.order.bit_length() - 1 + top = self._bits - 1 else: top = scalar.bit_length() - 1 r = copy(self._params.curve.neutral) @@ -118,7 +118,7 @@ class FullPrecompMultiplier(AccumulatorMultiplier, PrecompMultiplier, ScalarMult def _rtl(self, scalar: int) -> Point: r = copy(self._params.curve.neutral) if self.complete: - top = self._params.order.bit_length() + top = self._bits else: top = scalar.bit_length() for i in range(top): diff --git a/pyecsca/ec/mult/ladder.py b/pyecsca/ec/mult/ladder.py index 5f5d8a2..3635ada 100644 --- a/pyecsca/ec/mult/ladder.py +++ b/pyecsca/ec/mult/ladder.py @@ -12,6 +12,7 @@ from pyecsca.ec.formula import ( LadderFormula, DifferentialAdditionFormula, ) +from pyecsca.ec.params import DomainParameters from pyecsca.ec.point import Point @@ -87,7 +88,7 @@ class LadderMultiplier(ScalarMultiplier): if self.complete: p0 = copy(self._params.curve.neutral) p1 = self._point - top = self._params.full_order.bit_length() - 1 + top = self._bits - 1 elif self.full: p0 = copy(self._params.curve.neutral) p1 = self._point @@ -154,7 +155,7 @@ class SimpleLadderMultiplier(ScalarMultiplier): if scalar == 0: return action.exit(copy(self._params.curve.neutral)) if self.complete: - top = self._params.full_order.bit_length() - 1 + top = self._bits - 1 else: top = scalar.bit_length() - 1 p0 = copy(self._params.curve.neutral) @@ -232,7 +233,7 @@ class DifferentialLadderMultiplier(ScalarMultiplier): if self.complete: p0 = copy(self._params.curve.neutral) p1 = copy(q) - top = self._params.full_order.bit_length() - 1 + top = self._bits - 1 elif self.full: p0 = copy(self._params.curve.neutral) p1 = copy(q) diff --git a/pyecsca/ec/mult/naf.py b/pyecsca/ec/mult/naf.py index 83dc0dc..b886552 100644 --- a/pyecsca/ec/mult/naf.py +++ b/pyecsca/ec/mult/naf.py @@ -81,9 +81,9 @@ class BinaryNAFMultiplier(AccumulatorMultiplier, PrecompMultiplier, ScalarMultip 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})" - def init(self, params: DomainParameters, point: Point): + def init(self, params: DomainParameters, point: Point, bits: Optional[int] = None): with PrecomputationAction(params, point) as action: - super().init(params, point) + super().init(params, point, bits) self._point_neg = self._neg(point) action.exit({-1: self._point_neg}) @@ -195,9 +195,9 @@ class WindowNAFMultiplier(AccumulatorMultiplier, PrecompMultiplier, ScalarMultip 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})" - def init(self, params: DomainParameters, point: Point): + def init(self, params: DomainParameters, point: Point, bits: Optional[int] = None): with PrecomputationAction(params, point) as action: - super().init(params, point) + super().init(params, point, bits) self._points = {} self._points_neg = {} current_point = point diff --git a/pyecsca/ec/mult/window.py b/pyecsca/ec/mult/window.py index 6fbee24..1a0ecec 100644 --- a/pyecsca/ec/mult/window.py +++ b/pyecsca/ec/mult/window.py @@ -90,9 +90,9 @@ class SlidingWindowMultiplier(AccumulatorMultiplier, PrecompMultiplier, ScalarMu def __repr__(self): return f"{self.__class__.__name__}({', '.join(map(str, self.formulas.values()))}, short_circuit={self.short_circuit}, width={self.width}, recoding_direction={self.recoding_direction.name}, accumulation_order={self.accumulation_order.name})" - def init(self, params: DomainParameters, point: Point): + def init(self, params: DomainParameters, point: Point, bits: Optional[int] = None): with PrecomputationAction(params, point) as action: - super().init(params, point) + super().init(params, point, bits) self._points = {} current_point = point double_point = self._dbl(point) @@ -186,9 +186,9 @@ class FixedWindowLTRMultiplier(AccumulatorMultiplier, PrecompMultiplier, ScalarM def __repr__(self): return f"{self.__class__.__name__}({', '.join(map(str, self.formulas.values()))}, short_circuit={self.short_circuit}, m={self.m}, accumulation_order={self.accumulation_order.name})" - def init(self, params: DomainParameters, point: Point): + def init(self, params: DomainParameters, point: Point, bits: Optional[int] = None): with PrecomputationAction(params, point) as action: - super().init(params, point) + super().init(params, point, bits) double_point = self._dbl(point) self._points = {1: point, 2: double_point} current_point = double_point @@ -298,9 +298,9 @@ class WindowBoothMultiplier(AccumulatorMultiplier, PrecompMultiplier, ScalarMult 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})" - def init(self, params: DomainParameters, point: Point): + def init(self, params: DomainParameters, point: Point, bits: Optional[int] = None): with PrecomputationAction(params, point) as actions: - super().init(params, point) + super().init(params, point, bits) double_point = self._dbl(point) self._points = {1: point, 2: double_point} if self.precompute_negation: @@ -323,7 +323,7 @@ class WindowBoothMultiplier(AccumulatorMultiplier, PrecompMultiplier, ScalarMult if scalar == 0: return action.exit(copy(self._params.curve.neutral)) scalar_booth = booth_window( - scalar, self.width, self._params.order.bit_length() + scalar, self.width, self._bits ) q = copy(self._params.curve.neutral) for val in scalar_booth: -- cgit v1.2.3-70-g09d2