aboutsummaryrefslogtreecommitdiff
path: root/pyecsca/ec/mult
diff options
context:
space:
mode:
authorJ08nY2023-08-27 16:38:00 +0200
committerJ08nY2023-08-27 16:38:00 +0200
commit54e9958c811a57b7adbc052cc86fedaa582c102f (patch)
treeec3f5002e12bd1cb4a3e1f3f7bdf27f7d151342b /pyecsca/ec/mult
parent19bc2ed369cbcd41c08132edb74d7a1afd843962 (diff)
downloadpyecsca-54e9958c811a57b7adbc052cc86fedaa582c102f.tar.gz
pyecsca-54e9958c811a57b7adbc052cc86fedaa582c102f.tar.zst
pyecsca-54e9958c811a57b7adbc052cc86fedaa582c102f.zip
Diffstat (limited to 'pyecsca/ec/mult')
-rw-r--r--pyecsca/ec/mult/base.py21
-rw-r--r--pyecsca/ec/mult/binary.py16
-rw-r--r--pyecsca/ec/mult/naf.py31
-rw-r--r--pyecsca/ec/mult/window.py84
4 files changed, 103 insertions, 49 deletions
diff --git a/pyecsca/ec/mult/base.py b/pyecsca/ec/mult/base.py
index 027320c..a0584d1 100644
--- a/pyecsca/ec/mult/base.py
+++ b/pyecsca/ec/mult/base.py
@@ -206,3 +206,24 @@ class ScalarMultiplier(ABC):
:return: The resulting multiple.
"""
raise NotImplementedError
+
+
+@public
+class AccumulatorMultiplier(ScalarMultiplier, ABC):
+ """
+ A scalar multiplication algorithm mix-in class for a multiplier that accumulates.
+
+ :param accumulation_order: The order of accumulation of points.
+ """
+ accumulation_order: AccumulationOrder
+
+ def __init__(self, *args, accumulation_order: AccumulationOrder = AccumulationOrder.PeqPR, **kwargs):
+ super().__init__(*args, **kwargs)
+ self.accumulation_order = accumulation_order
+
+ def _accumulate(self, p: Point, r: Point) -> Point:
+ if self.accumulation_order is AccumulationOrder.PeqPR:
+ p = self._add(p, r)
+ elif self.accumulation_order is AccumulationOrder.PeqRP:
+ p = self._add(r, p)
+ return p
diff --git a/pyecsca/ec/mult/binary.py b/pyecsca/ec/mult/binary.py
index dda3388..6145828 100644
--- a/pyecsca/ec/mult/binary.py
+++ b/pyecsca/ec/mult/binary.py
@@ -4,7 +4,8 @@ from typing import Optional
from public import public
-from .base import ScalarMultiplier, ProcessingDirection, AccumulationOrder, ScalarMultiplicationAction
+from .base import ScalarMultiplier, ProcessingDirection, AccumulationOrder, ScalarMultiplicationAction, \
+ AccumulatorMultiplier
from ..formula import (
AdditionFormula,
DoublingFormula,
@@ -14,7 +15,7 @@ from ..point import Point
@public
-class DoubleAndAddMultiplier(ScalarMultiplier, ABC):
+class DoubleAndAddMultiplier(AccumulatorMultiplier, ScalarMultiplier, ABC):
"""
Classic double and add scalar multiplication algorithm.
@@ -27,7 +28,6 @@ class DoubleAndAddMultiplier(ScalarMultiplier, ABC):
optionals = {ScalingFormula}
always: bool
direction: ProcessingDirection
- accumulation_order: AccumulationOrder
complete: bool
def __init__(
@@ -41,10 +41,9 @@ class DoubleAndAddMultiplier(ScalarMultiplier, ABC):
complete: bool = True,
short_circuit: bool = True,
):
- super().__init__(short_circuit=short_circuit, 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.accumulation_order = accumulation_order
self.complete = complete
def __hash__(self):
@@ -58,13 +57,6 @@ class DoubleAndAddMultiplier(ScalarMultiplier, ABC):
def __repr__(self):
return f"{self.__class__.__name__}({tuple(self.formulas.values())}, short_circuit={self.short_circuit}, accumulation_order={self.accumulation_order}, always={self.always}, complete={self.complete})"
- def _accumulate(self, p: Point, r: Point) -> Point:
- if self.accumulation_order is AccumulationOrder.PeqPR:
- p = self._add(p, r)
- elif self.accumulation_order is AccumulationOrder.PeqRP:
- p = self._add(r, p)
- return p
-
def _ltr(self, scalar: int) -> Point:
if self.complete:
q = self._point
diff --git a/pyecsca/ec/mult/naf.py b/pyecsca/ec/mult/naf.py
index b3409db..1cec8b0 100644
--- a/pyecsca/ec/mult/naf.py
+++ b/pyecsca/ec/mult/naf.py
@@ -2,7 +2,8 @@ from copy import copy
from typing import Optional, List, MutableMapping
from public import public
-from .base import ScalarMultiplier, ScalarMultiplicationAction, ProcessingDirection, AccumulationOrder, PrecomputationAction
+from .base import ScalarMultiplier, ScalarMultiplicationAction, ProcessingDirection, AccumulationOrder, \
+ PrecomputationAction, AccumulatorMultiplier
from ..formula import (
AdditionFormula,
DoublingFormula,
@@ -15,13 +16,12 @@ from ..scalar import naf, wnaf
@public
-class BinaryNAFMultiplier(ScalarMultiplier):
+class BinaryNAFMultiplier(AccumulatorMultiplier, ScalarMultiplier):
"""Binary NAF (Non Adjacent Form) multiplier."""
requires = {AdditionFormula, DoublingFormula, NegationFormula}
optionals = {ScalingFormula}
direction: ProcessingDirection
- accumulation_order: AccumulationOrder
_point_neg: Point
def __init__(
@@ -35,10 +35,9 @@ class BinaryNAFMultiplier(ScalarMultiplier):
short_circuit: bool = True,
):
super().__init__(
- short_circuit=short_circuit, 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
- self.accumulation_order = accumulation_order
def __hash__(self):
return id(self)
@@ -53,13 +52,6 @@ class BinaryNAFMultiplier(ScalarMultiplier):
super().init(params, point)
self._point_neg = self._neg(point)
- def _accumulate(self, p: Point, r: Point) -> Point:
- if self.accumulation_order is AccumulationOrder.PeqPR:
- p = self._add(p, r)
- elif self.accumulation_order is AccumulationOrder.PeqRP:
- p = self._add(r, p)
- return p
-
def _ltr(self, scalar_naf: List[int]) -> Point:
q = copy(self._params.curve.neutral)
for val in scalar_naf:
@@ -100,14 +92,13 @@ class BinaryNAFMultiplier(ScalarMultiplier):
@public
-class WindowNAFMultiplier(ScalarMultiplier):
+class WindowNAFMultiplier(AccumulatorMultiplier, ScalarMultiplier):
"""Window NAF (Non Adjacent Form) multiplier, left-to-right."""
requires = {AdditionFormula, DoublingFormula, NegationFormula}
optionals = {ScalingFormula}
_points: MutableMapping[int, Point]
_points_neg: MutableMapping[int, Point]
- accumulation_order: AccumulationOrder
precompute_negation: bool = False
width: int
@@ -123,10 +114,9 @@ class WindowNAFMultiplier(ScalarMultiplier):
short_circuit: bool = True,
):
super().__init__(
- short_circuit=short_circuit, 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.accumulation_order = accumulation_order
self.precompute_negation = precompute_negation
def __hash__(self):
@@ -135,7 +125,7 @@ class WindowNAFMultiplier(ScalarMultiplier):
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
+ 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 init(self, params: DomainParameters, point: Point):
with PrecomputationAction(params, point):
@@ -150,13 +140,6 @@ class WindowNAFMultiplier(ScalarMultiplier):
self._points_neg[2 * i + 1] = self._neg(current_point)
current_point = self._add(current_point, double_point)
- def _accumulate(self, p: Point, r: Point) -> Point:
- if self.accumulation_order is AccumulationOrder.PeqPR:
- p = self._add(p, r)
- elif self.accumulation_order is AccumulationOrder.PeqRP:
- p = self._add(r, p)
- return p
-
def multiply(self, scalar: int) -> Point:
if not self._initialized:
raise ValueError("ScalarMultiplier not initialized.")
diff --git a/pyecsca/ec/mult/window.py b/pyecsca/ec/mult/window.py
index f2c2c70..15126a7 100644
--- a/pyecsca/ec/mult/window.py
+++ b/pyecsca/ec/mult/window.py
@@ -3,25 +3,90 @@ from typing import Optional, MutableMapping
from public import public
from ..params import DomainParameters
-from .base import ScalarMultiplier, AccumulationOrder, ScalarMultiplicationAction, PrecomputationAction
+from .base import ScalarMultiplier, AccumulationOrder, ScalarMultiplicationAction, PrecomputationAction, \
+ ProcessingDirection, AccumulatorMultiplier
from ..formula import (
AdditionFormula,
DoublingFormula,
ScalingFormula,
)
from ..point import Point
-from ..scalar import convert_base
+from ..scalar import convert_base, sliding_window_rtl, sliding_window_ltr
@public
-class FixedWindowLTRMultiplier(ScalarMultiplier):
+class SlidingWindowMultiplier(AccumulatorMultiplier, ScalarMultiplier):
+ """"""
+
+ requires = {AdditionFormula, DoublingFormula}
+ optionals = {ScalingFormula}
+ complete: bool
+ width: int
+ recoding_direction: ProcessingDirection
+ _points: MutableMapping[int, Point]
+
+ def __init__(
+ self,
+ add: AdditionFormula,
+ dbl: DoublingFormula,
+ width: int,
+ scl: Optional[ScalingFormula] = None,
+ recoding_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, scl=scl
+ )
+ self.width = width
+ self.recoding_direction = recoding_direction
+
+ def __hash__(self):
+ return id(self)
+
+ def __eq__(self, other):
+ if not isinstance(other, SlidingWindowMultiplier):
+ return False
+ return self.formulas == other.formulas and self.short_circuit == other.short_circuit and self.width == other.width and self.recoding_direction == other.recoding_direction and self.accumulation_order == other.accumulation_order
+
+ def init(self, params: DomainParameters, point: Point):
+ with PrecomputationAction(params, point):
+ super().init(params, point)
+ self._points = {}
+ current_point = point
+ double_point = self._dbl(point)
+ for i in range(0, 2 ** (self.width - 1)):
+ self._points[2 * i + 1] = current_point
+ current_point = self._add(current_point, double_point)
+
+ def multiply(self, scalar: int) -> Point:
+ if not self._initialized:
+ raise ValueError("ScalarMultiplier not initialized.")
+ with ScalarMultiplicationAction(self._point, scalar) as action:
+ if scalar == 0:
+ return action.exit(copy(self._params.curve.neutral))
+ if self.recoding_direction is ProcessingDirection.LTR:
+ scalar_sliding = sliding_window_ltr(scalar, self.width)
+ elif self.recoding_direction is ProcessingDirection.RTL:
+ scalar_sliding = sliding_window_rtl(scalar, self.width)
+ q = copy(self._params.curve.neutral)
+ for val in scalar_sliding:
+ q = self._dbl(q)
+ if val != 0:
+ q = self._accumulate(q, self._points[val])
+ if "scl" in self.formulas:
+ q = self._scl(q)
+ return action.exit(q)
+
+
+@public
+class FixedWindowLTRMultiplier(AccumulatorMultiplier, ScalarMultiplier):
"""Like LTRMultiplier, but not binary, but m-ary."""
requires = {AdditionFormula, DoublingFormula}
optionals = {ScalingFormula}
complete: bool
m: int
- accumulation_order: AccumulationOrder
_points: MutableMapping[int, Point]
def __init__(
@@ -34,7 +99,7 @@ class FixedWindowLTRMultiplier(ScalarMultiplier):
short_circuit: bool = True,
):
super().__init__(
- short_circuit=short_circuit, add=add, dbl=dbl, scl=scl
+ short_circuit=short_circuit, accumulation_order=accumulation_order, add=add, dbl=dbl, scl=scl
)
if m < 2:
raise ValueError("Invalid base.")
@@ -47,7 +112,7 @@ class FixedWindowLTRMultiplier(ScalarMultiplier):
def __eq__(self, other):
if not isinstance(other, FixedWindowLTRMultiplier):
return False
- return self.formulas == other.formulas and self.short_circuit == other.short_circuit and self.m == other.m
+ return self.formulas == other.formulas and self.short_circuit == other.short_circuit and self.m == other.m and self.accumulation_order == other.accumulation_order
def init(self, params: DomainParameters, point: Point):
with PrecomputationAction(params, point):
@@ -74,13 +139,6 @@ class FixedWindowLTRMultiplier(ScalarMultiplier):
q = self._accumulate(q, r)
return q
- def _accumulate(self, p: Point, r: Point) -> Point:
- if self.accumulation_order is AccumulationOrder.PeqPR:
- p = self._add(p, r)
- elif self.accumulation_order is AccumulationOrder.PeqRP:
- p = self._add(r, p)
- return p
-
def multiply(self, scalar: int) -> Point:
if not self._initialized:
raise ValueError("ScalarMultiplier not initialized.")