diff options
| author | J08nY | 2024-08-28 12:37:38 +0200 |
|---|---|---|
| committer | J08nY | 2024-08-28 12:37:38 +0200 |
| commit | 979d86979313de02c4dab71f99ce1c5dddd5877a (patch) | |
| tree | 3f6e8930b0d15e293ae16ee2074e41ad8cf40f8c /pyecsca/ec/mult | |
| parent | f5af7b538692cdfdeab6f71751149b496062fde4 (diff) | |
| download | pyecsca-979d86979313de02c4dab71f99ce1c5dddd5877a.tar.gz pyecsca-979d86979313de02c4dab71f99ce1c5dddd5877a.tar.zst pyecsca-979d86979313de02c4dab71f99ce1c5dddd5877a.zip | |
More ladder multipliers.
Diffstat (limited to 'pyecsca/ec/mult')
| -rw-r--r-- | pyecsca/ec/mult/base.py | 6 | ||||
| -rw-r--r-- | pyecsca/ec/mult/binary.py | 4 | ||||
| -rw-r--r-- | pyecsca/ec/mult/comb.py | 4 | ||||
| -rw-r--r-- | pyecsca/ec/mult/fixed.py | 2 | ||||
| -rw-r--r-- | pyecsca/ec/mult/ladder.py | 101 | ||||
| -rw-r--r-- | pyecsca/ec/mult/naf.py | 4 | ||||
| -rw-r--r-- | pyecsca/ec/mult/window.py | 6 |
7 files changed, 91 insertions, 36 deletions
diff --git a/pyecsca/ec/mult/base.py b/pyecsca/ec/mult/base.py index 537f43e..469be39 100644 --- a/pyecsca/ec/mult/base.py +++ b/pyecsca/ec/mult/base.py @@ -34,15 +34,17 @@ class ScalarMultiplicationAction(ResultAction): """A scalar multiplication of a point on a curve by a scalar.""" point: Point + params: DomainParameters scalar: int - def __init__(self, point: Point, scalar: int): + def __init__(self, point: Point, params: DomainParameters, scalar: int): super().__init__() self.point = point + self.params = params self.scalar = scalar def __repr__(self): - return f"{self.__class__.__name__}({self.point}, {self.scalar})" + return f"{self.__class__.__name__}({self.point}, {self.params}, {self.scalar})" @public diff --git a/pyecsca/ec/mult/binary.py b/pyecsca/ec/mult/binary.py index 9b6a07a..5b6bed7 100644 --- a/pyecsca/ec/mult/binary.py +++ b/pyecsca/ec/mult/binary.py @@ -129,7 +129,7 @@ class DoubleAndAddMultiplier(AccumulatorMultiplier, ScalarMultiplier, ABC): def multiply(self, scalar: int) -> Point: if not self._initialized: raise ValueError("ScalarMultiplier not initialized.") - with ScalarMultiplicationAction(self._point, scalar) as action: + with ScalarMultiplicationAction(self._point, self._params, scalar) as action: if scalar == 0: return action.exit(copy(self._params.curve.neutral)) if self.direction is ProcessingDirection.LTR: @@ -246,7 +246,7 @@ class CoronMultiplier(ScalarMultiplier): def multiply(self, scalar: int) -> Point: if not self._initialized: raise ValueError("ScalarMultiplier not initialized.") - with ScalarMultiplicationAction(self._point, scalar) as action: + with ScalarMultiplicationAction(self._point, self._params, scalar) as action: if scalar == 0: return action.exit(copy(self._params.curve.neutral)) q = self._point diff --git a/pyecsca/ec/mult/comb.py b/pyecsca/ec/mult/comb.py index 8cea19c..9557fe6 100644 --- a/pyecsca/ec/mult/comb.py +++ b/pyecsca/ec/mult/comb.py @@ -100,7 +100,7 @@ class BGMWMultiplier(AccumulatorMultiplier, ScalarMultiplier): def multiply(self, scalar: int) -> Point: if not self._initialized: raise ValueError("ScalarMultiplier not initialized.") - with ScalarMultiplicationAction(self._point, scalar) as action: + with ScalarMultiplicationAction(self._point, self._params, scalar) as action: if scalar == 0: return action.exit(copy(self._params.curve.neutral)) a = copy(self._params.curve.neutral) @@ -202,7 +202,7 @@ class CombMultiplier(AccumulatorMultiplier, ScalarMultiplier): def multiply(self, scalar: int) -> Point: if not self._initialized: raise ValueError("ScalarMultiplier not initialized.") - with ScalarMultiplicationAction(self._point, scalar) as action: + with ScalarMultiplicationAction(self._point, self._params, scalar) as action: if scalar == 0: return action.exit(copy(self._params.curve.neutral)) q = copy(self._params.curve.neutral) diff --git a/pyecsca/ec/mult/fixed.py b/pyecsca/ec/mult/fixed.py index afd02e5..2c60be2 100644 --- a/pyecsca/ec/mult/fixed.py +++ b/pyecsca/ec/mult/fixed.py @@ -132,7 +132,7 @@ class FullPrecompMultiplier(AccumulatorMultiplier, ScalarMultiplier): def multiply(self, scalar: int) -> Point: if not self._initialized: raise ValueError("ScalarMultiplier not initialized.") - with ScalarMultiplicationAction(self._point, scalar) as action: + with ScalarMultiplicationAction(self._point, self._params, scalar) as action: if scalar == 0: return action.exit(copy(self._params.curve.neutral)) if self.direction is ProcessingDirection.LTR: diff --git a/pyecsca/ec/mult/ladder.py b/pyecsca/ec/mult/ladder.py index f2939af..9f31b7f 100644 --- a/pyecsca/ec/mult/ladder.py +++ b/pyecsca/ec/mult/ladder.py @@ -1,4 +1,5 @@ """Provides ladder-based scalar multipliers, either using the ladder formula, or (diffadd, dbl) or (add, dbl).""" + from copy import copy from typing import Optional from public import public @@ -24,12 +25,15 @@ class LadderMultiplier(ScalarMultiplier): :param short_circuit: Whether the use of formulas will be guarded by short-circuit on inputs of the point at infinity. :param complete: Whether it starts processing at full order-bit-length. + :param full: Whether it start processing at top bit of the scalar. """ requires = {LadderFormula} optionals = {DoublingFormula, ScalingFormula} complete: bool """Whether it starts processing at full order-bit-length.""" + full: bool + """Whether it start processing at top bit of the scalar.""" def __init__( self, @@ -38,17 +42,27 @@ class LadderMultiplier(ScalarMultiplier): scl: Optional[ScalingFormula] = None, complete: bool = True, short_circuit: bool = True, + full: bool = False, ): super().__init__(short_circuit=short_circuit, ladd=ladd, dbl=dbl, scl=scl) self.complete = complete + self.full = full + + if complete and full: + raise ValueError("Only one of `complete` and `full` can be set.") + if dbl is None: - if not complete: - raise ValueError("When complete is not set LadderMultiplier requires a doubling formula.") - if short_circuit: # complete = True - raise ValueError("When short_circuit is set LadderMultiplier requires a doubling formula.") + if short_circuit: + raise ValueError( + "When `short_circuit` is set LadderMultiplier requires a doubling formula." + ) + if not (complete or full): + raise ValueError( + "When neither `complete` nor `full` is not set LadderMultiplier requires a doubling formula." + ) def __hash__(self): - return hash((LadderMultiplier, super().__hash__(), self.complete)) + return hash((LadderMultiplier, super().__hash__(), self.complete, self.full)) def __eq__(self, other): if not isinstance(other, LadderMultiplier): @@ -57,15 +71,16 @@ class LadderMultiplier(ScalarMultiplier): self.formulas == other.formulas and self.short_circuit == other.short_circuit and self.complete == other.complete + and self.full == other.full ) def __repr__(self): - return f"{self.__class__.__name__}({', '.join(map(str, self.formulas.values()))}, short_circuit={self.short_circuit}, complete={self.complete})" + return f"{self.__class__.__name__}({', '.join(map(str, self.formulas.values()))}, short_circuit={self.short_circuit}, complete={self.complete}, full={self.full})" def multiply(self, scalar: int) -> Point: if not self._initialized: raise ValueError("ScalarMultiplier not initialized.") - with ScalarMultiplicationAction(self._point, scalar) as action: + with ScalarMultiplicationAction(self._point, self._params, scalar) as action: if scalar == 0: return action.exit(copy(self._params.curve.neutral)) q = self._point @@ -73,6 +88,10 @@ class LadderMultiplier(ScalarMultiplier): p0 = copy(self._params.curve.neutral) p1 = self._point top = self._params.full_order.bit_length() - 1 + elif self.full: + p0 = copy(self._params.curve.neutral) + p1 = self._point + top = scalar.bit_length() - 1 else: p0 = copy(q) p1 = self._dbl(q) @@ -97,12 +116,15 @@ class SwapLadderMultiplier(ScalarMultiplier): :param short_circuit: Whether the use of formulas will be guarded by short-circuit on inputs of the point at infinity. :param complete: Whether it starts processing at full order-bit-length. + :param full: Whether it start processing at top bit of the scalar. """ requires = {LadderFormula} optionals = {DoublingFormula, ScalingFormula} complete: bool """Whether it starts processing at full order-bit-length.""" + full: bool + """Whether it start processing at top bit of the scalar.""" def __init__( self, @@ -111,34 +133,45 @@ class SwapLadderMultiplier(ScalarMultiplier): scl: Optional[ScalingFormula] = None, complete: bool = True, short_circuit: bool = True, + full: bool = False, ): super().__init__(short_circuit=short_circuit, ladd=ladd, dbl=dbl, scl=scl) self.complete = complete + self.full = full + + if complete and full: + raise ValueError("Only one of `complete` and `full` can be set.") + if dbl is None: - if not complete: - raise ValueError("When complete is not set SwapLadderMultiplier requires a doubling formula.") - if short_circuit: # complete = True - raise ValueError("When short_circuit is set SwapLadderMultiplier requires a doubling formula.") + if short_circuit: + raise ValueError( + "When `short_circuit` is set SwapLadderMultiplier requires a doubling formula." + ) + if not (complete or full): + raise ValueError( + "When neither `complete` nor `full` is not set SwapLadderMultiplier requires a doubling formula." + ) def __hash__(self): - return hash((LadderMultiplier, super().__hash__(), self.complete)) + return hash((SwapLadderMultiplier, super().__hash__(), self.complete, self.full)) def __eq__(self, other): - if not isinstance(other, LadderMultiplier): + if not isinstance(other, SwapLadderMultiplier): return False return ( self.formulas == other.formulas and self.short_circuit == other.short_circuit and self.complete == other.complete + and self.full == other.full ) def __repr__(self): - return f"{self.__class__.__name__}({', '.join(map(str, self.formulas.values()))}, short_circuit={self.short_circuit}, complete={self.complete})" + return f"{self.__class__.__name__}({', '.join(map(str, self.formulas.values()))}, short_circuit={self.short_circuit}, complete={self.complete}, full={self.full})" def multiply(self, scalar: int) -> Point: if not self._initialized: raise ValueError("ScalarMultiplier not initialized.") - with ScalarMultiplicationAction(self._point, scalar) as action: + with ScalarMultiplicationAction(self._point, self._params, scalar) as action: if scalar == 0: return action.exit(copy(self._params.curve.neutral)) q = self._point @@ -146,6 +179,10 @@ class SwapLadderMultiplier(ScalarMultiplier): p0 = copy(self._params.curve.neutral) p1 = self._point top = self._params.full_order.bit_length() - 1 + elif self.full: + p0 = copy(self._params.curve.neutral) + p1 = self._point + top = scalar.bit_length() - 1 else: p0 = copy(q) p1 = self._dbl(q) @@ -207,11 +244,11 @@ class SimpleLadderMultiplier(ScalarMultiplier): def multiply(self, scalar: int) -> Point: if not self._initialized: raise ValueError("ScalarMultiplier not initialized.") - with ScalarMultiplicationAction(self._point, scalar) as action: + with ScalarMultiplicationAction(self._point, self._params, scalar) as action: if scalar == 0: return action.exit(copy(self._params.curve.neutral)) if self.complete: - top = self._params.order.bit_length() - 1 + top = self._params.full_order.bit_length() - 1 else: top = scalar.bit_length() - 1 p0 = copy(self._params.curve.neutral) @@ -242,6 +279,8 @@ class DifferentialLadderMultiplier(ScalarMultiplier): optionals = {ScalingFormula} complete: bool """Whether it starts processing at full order-bit-length.""" + full: bool + """Whether it start processing at top bit of the scalar.""" def __init__( self, @@ -250,12 +289,19 @@ class DifferentialLadderMultiplier(ScalarMultiplier): scl: Optional[ScalingFormula] = None, complete: bool = True, short_circuit: bool = True, + full: bool = False, ): super().__init__(short_circuit=short_circuit, dadd=dadd, dbl=dbl, scl=scl) self.complete = complete + self.full = full + + if complete and full: + raise ValueError("Only one of `complete` and `full` can be set.") def __hash__(self): - return hash((DifferentialLadderMultiplier, super().__hash__(), self.complete)) + return hash( + (DifferentialLadderMultiplier, super().__hash__(), self.complete, self.full) + ) def __eq__(self, other): if not isinstance(other, DifferentialLadderMultiplier): @@ -264,24 +310,31 @@ class DifferentialLadderMultiplier(ScalarMultiplier): self.formulas == other.formulas and self.short_circuit == other.short_circuit and self.complete == other.complete + and self.full == other.full ) def __repr__(self): - return f"{self.__class__.__name__}({', '.join(map(str, self.formulas.values()))}, short_circuit={self.short_circuit}, complete={self.complete})" + return f"{self.__class__.__name__}({', '.join(map(str, self.formulas.values()))}, short_circuit={self.short_circuit}, complete={self.complete}, full={self.full})" def multiply(self, scalar: int) -> Point: if not self._initialized: raise ValueError("ScalarMultiplier not initialized.") - with ScalarMultiplicationAction(self._point, scalar) as action: + with ScalarMultiplicationAction(self._point, self._params, scalar) as action: if scalar == 0: return action.exit(copy(self._params.curve.neutral)) + q = self._point if self.complete: + p0 = copy(self._params.curve.neutral) + p1 = copy(q) top = self._params.full_order.bit_length() - 1 - else: + elif self.full: + p0 = copy(self._params.curve.neutral) + p1 = copy(q) top = scalar.bit_length() - 1 - q = self._point - p0 = copy(self._params.curve.neutral) - p1 = copy(q) + else: + p0 = copy(q) + p1 = self._dbl(q) + top = scalar.bit_length() - 2 for i in range(top, -1, -1): if scalar & (1 << i) == 0: p1 = self._dadd(q, p0, p1) diff --git a/pyecsca/ec/mult/naf.py b/pyecsca/ec/mult/naf.py index 408f489..6fc9131 100644 --- a/pyecsca/ec/mult/naf.py +++ b/pyecsca/ec/mult/naf.py @@ -112,7 +112,7 @@ class BinaryNAFMultiplier(AccumulatorMultiplier, ScalarMultiplier): def multiply(self, scalar: int) -> Point: if not self._initialized: raise ValueError("ScalarMultiplier not initialized.") - with ScalarMultiplicationAction(self._point, scalar) as action: + with ScalarMultiplicationAction(self._point, self._params, scalar) as action: if scalar == 0: return action.exit(copy(self._params.curve.neutral)) scalar_naf = naf(scalar) @@ -210,7 +210,7 @@ class WindowNAFMultiplier(AccumulatorMultiplier, ScalarMultiplier): def multiply(self, scalar: int) -> Point: if not self._initialized: raise ValueError("ScalarMultiplier not initialized.") - with ScalarMultiplicationAction(self._point, scalar) as action: + with ScalarMultiplicationAction(self._point, self._params, scalar) as action: if scalar == 0: return action.exit(copy(self._params.curve.neutral)) scalar_naf = wnaf(scalar, self.width) diff --git a/pyecsca/ec/mult/window.py b/pyecsca/ec/mult/window.py index b003e40..c200cc5 100644 --- a/pyecsca/ec/mult/window.py +++ b/pyecsca/ec/mult/window.py @@ -103,7 +103,7 @@ class SlidingWindowMultiplier(AccumulatorMultiplier, ScalarMultiplier): def multiply(self, scalar: int) -> Point: if not self._initialized: raise ValueError("ScalarMultiplier not initialized.") - with ScalarMultiplicationAction(self._point, scalar) as action: + with ScalarMultiplicationAction(self._point, self._params, scalar) as action: if scalar == 0: return action.exit(copy(self._params.curve.neutral)) if self.recoding_direction is ProcessingDirection.LTR: @@ -213,7 +213,7 @@ class FixedWindowLTRMultiplier(AccumulatorMultiplier, ScalarMultiplier): def multiply(self, scalar: int) -> Point: if not self._initialized: raise ValueError("ScalarMultiplier not initialized.") - with ScalarMultiplicationAction(self._point, scalar) as action: + with ScalarMultiplicationAction(self._point, self._params, scalar) as action: if scalar == 0: return action.exit(copy(self._params.curve.neutral)) # General case (any m) and special case (m = 2^k) are handled together here @@ -313,7 +313,7 @@ class WindowBoothMultiplier(AccumulatorMultiplier, ScalarMultiplier): def multiply(self, scalar: int) -> Point: if not self._initialized: raise ValueError("ScalarMultiplier not initialized.") - with ScalarMultiplicationAction(self._point, scalar) as action: + with ScalarMultiplicationAction(self._point, self._params, scalar) as action: if scalar == 0: return action.exit(copy(self._params.curve.neutral)) scalar_booth = booth_window( |
