diff options
| author | J08nY | 2021-01-16 16:33:43 +0100 |
|---|---|---|
| committer | J08nY | 2021-01-16 16:42:20 +0100 |
| commit | b6d03e0935b21bf35542a282ba66ba25094234ca (patch) | |
| tree | 2533c8098d05e499b49f76155ff7bb6b1ff8831a | |
| parent | cb397341f7e7b0647157ca8225d9dbeda14c7d2b (diff) | |
| download | pyecsca-b6d03e0935b21bf35542a282ba66ba25094234ca.tar.gz pyecsca-b6d03e0935b21bf35542a282ba66ba25094234ca.tar.zst pyecsca-b6d03e0935b21bf35542a282ba66ba25094234ca.zip | |
Also trace precomputation in MultipleContext.
| -rw-r--r-- | pyecsca/ec/context.py | 30 | ||||
| -rw-r--r-- | pyecsca/ec/mult.py | 42 | ||||
| -rw-r--r-- | pyecsca/sca/__init__.py | 1 | ||||
| -rw-r--r-- | pyecsca/sca/re/__init__.py | 3 | ||||
| -rw-r--r-- | pyecsca/sca/re/rpa.py | 22 | ||||
| -rw-r--r-- | test/sca/test_rpa.py | 54 |
6 files changed, 107 insertions, 45 deletions
diff --git a/pyecsca/ec/context.py b/pyecsca/ec/context.py index 02c8a6d..39bf6f0 100644 --- a/pyecsca/ec/context.py +++ b/pyecsca/ec/context.py @@ -156,6 +156,10 @@ class DefaultContext(Context): actions: Tree current: List[Action] + def __init__(self): + self.actions = Tree() + self.current = [] + def enter_action(self, action: Action) -> None: self.actions.get_by_key(self.current)[action] = Tree() self.current.append(action) @@ -165,10 +169,6 @@ class DefaultContext(Context): raise ValueError self.current.pop() - def __init__(self): - self.actions = Tree() - self.current = [] - def __repr__(self): return f"{self.__class__.__name__}({self.actions!r}, current={self.current!r})" @@ -181,6 +181,17 @@ class PathContext(Context): current_depth: int value: Any + def __init__(self, path: Sequence[int]): + """ + Create a :py:class:`PathContext`. + + :param path: The path of an action in the execution tree that will be captured. + """ + self.path = list(path) + self.current = [] + self.current_depth = 0 + self.value = None + def enter_action(self, action: Action) -> None: if self.current_depth == len(self.current): self.current.append(0) @@ -195,17 +206,6 @@ class PathContext(Context): self.current.pop() self.current_depth -= 1 - def __init__(self, path: Sequence[int]): - """ - Create a :py:class:`PathContext`. - - :param path: The path of an action in the execution tree that will be captured. - """ - self.path = list(path) - self.current = [] - self.current_depth = 0 - self.value = None - def __repr__(self): return f"{self.__class__.__name__}({self.current!r}, depth={self.current_depth!r})" diff --git a/pyecsca/ec/mult.py b/pyecsca/ec/mult.py index 5804eef..74325b5 100644 --- a/pyecsca/ec/mult.py +++ b/pyecsca/ec/mult.py @@ -4,7 +4,7 @@ from typing import Mapping, Tuple, Optional, MutableMapping, ClassVar, Set, Type from public import public -from .context import ResultAction +from .context import ResultAction, Action from .formula import (Formula, AdditionFormula, DoublingFormula, DifferentialAdditionFormula, ScalingFormula, LadderFormula, NegationFormula) from .naf import naf, wnaf @@ -28,6 +28,18 @@ class ScalarMultiplicationAction(ResultAction): @public +class PrecomputationAction(Action): + """""" + params: DomainParameters + point: Point + + def __init__(self, params: DomainParameters, point: Point): + super().__init__() + self.params = params + self.point = point + + +@public class ScalarMultiplier(ABC): """ A scalar multiplication algorithm. @@ -46,7 +58,7 @@ class ScalarMultiplier(ABC): _point: Point _initialized: bool = False - def __init__(self, short_circuit=True, **formulas: Optional[Formula]): + def __init__(self, short_circuit: bool = True, **formulas: Optional[Formula]): if len(set(formula.coordinate_model for formula in formulas.values() if formula is not None)) != 1: raise ValueError @@ -380,8 +392,9 @@ class BinaryNAFMultiplier(ScalarMultiplier): super().__init__(short_circuit=short_circuit, add=add, dbl=dbl, neg=neg, scl=scl) def init(self, params: DomainParameters, point: Point): - super().init(params, point) - self._point_neg = self._neg(point) + with PrecomputationAction(params, point): + super().init(params, point) + self._point_neg = self._neg(point) def multiply(self, scalar: int) -> Point: if not self._initialized: @@ -422,16 +435,17 @@ class WindowNAFMultiplier(ScalarMultiplier): self.precompute_negation = precompute_negation def init(self, params: DomainParameters, point: Point): - super().init(params, point) - self._points = {} - self._points_neg = {} - current_point = point - double_point = self._dbl(point) - for i in range(0, 2 ** (self.width - 2)): - self._points[2 * i + 1] = current_point - if self.precompute_negation: - self._points_neg[2 * i + 1] = self._neg(current_point) - current_point = self._add(current_point, double_point) + with PrecomputationAction(params, point): + super().init(params, point) + self._points = {} + self._points_neg = {} + current_point = point + double_point = self._dbl(point) + for i in range(0, 2 ** (self.width - 2)): + self._points[2 * i + 1] = current_point + if self.precompute_negation: + self._points_neg[2 * i + 1] = self._neg(current_point) + current_point = self._add(current_point, double_point) def multiply(self, scalar: int) -> Point: if not self._initialized: diff --git a/pyecsca/sca/__init__.py b/pyecsca/sca/__init__.py index 3117331..1aae9d9 100644 --- a/pyecsca/sca/__init__.py +++ b/pyecsca/sca/__init__.py @@ -1,5 +1,6 @@ """Package for Side-Channel Analysis.""" +from .re import * from .scope import * from .target import * from .trace import * diff --git a/pyecsca/sca/re/__init__.py b/pyecsca/sca/re/__init__.py index e69de29..4ad35ed 100644 --- a/pyecsca/sca/re/__init__.py +++ b/pyecsca/sca/re/__init__.py @@ -0,0 +1,3 @@ +"""Package for reverse-engineering.""" + +from .rpa import * diff --git a/pyecsca/sca/re/rpa.py b/pyecsca/sca/re/rpa.py index 2be2320..73ae569 100644 --- a/pyecsca/sca/re/rpa.py +++ b/pyecsca/sca/re/rpa.py @@ -1,28 +1,33 @@ from public import public -from typing import MutableMapping +from typing import MutableMapping, Optional from ...ec.formula import FormulaAction, DoublingFormula, AdditionFormula, TriplingFormula, NegationFormula, \ DifferentialAdditionFormula, LadderFormula -from ...ec.mult import ScalarMultiplicationAction +from ...ec.mult import ScalarMultiplicationAction, PrecomputationAction from ...ec.point import Point from ...ec.context import Context, Action @public class MultipleContext(Context): - """A context that traces the multiples computed.""" - base: Point + """A context that traces the multiples of points computed.""" + base: Optional[Point] points: MutableMapping[Point, int] inside: bool + def __init__(self): + self.base = None + self.points = {} + self.inside = False + def enter_action(self, action: Action) -> None: - if isinstance(action, ScalarMultiplicationAction): + if isinstance(action, (ScalarMultiplicationAction, PrecomputationAction)): self.base = action.point self.points = {self.base: 1} self.inside = True def exit_action(self, action: Action) -> None: - if isinstance(action, ScalarMultiplicationAction): + if isinstance(action, (ScalarMultiplicationAction, PrecomputationAction)): self.inside = False if isinstance(action, FormulaAction) and self.inside: if isinstance(action.formula, DoublingFormula): @@ -48,5 +53,8 @@ class MultipleContext(Context): elif isinstance(action.formula, LadderFormula): diff, one, other = action.input_points dbl, add = action.output_points - self.points[dbl] = 2 * self.points[one] self.points[add] = self.points[one] + self.points[other] + self.points[dbl] = 2 * self.points[one] + + def __repr__(self): + return f"{self.__class__.__name__}({self.base!r}, multiples={self.points.values()!r})" diff --git a/test/sca/test_rpa.py b/test/sca/test_rpa.py index b442ce2..ee10f89 100644 --- a/test/sca/test_rpa.py +++ b/test/sca/test_rpa.py @@ -3,13 +3,23 @@ from unittest import TestCase from parameterized import parameterized from pyecsca.ec.context import local -from pyecsca.ec.mult import LTRMultiplier +from pyecsca.ec.mult import LTRMultiplier, BinaryNAFMultiplier, WindowNAFMultiplier, LadderMultiplier, \ + DifferentialLadderMultiplier from pyecsca.ec.params import get_params from pyecsca.sca.re.rpa import MultipleContext class MultipleContextTests(TestCase): + def setUp(self): + self.secp128r1 = get_params("secg", "secp128r1", "projective") + self.base = self.secp128r1.generator + self.coords = self.secp128r1.curve.coordinate_model + self.add = self.coords.formulas["add-1998-cmo"] + self.dbl = self.coords.formulas["dbl-1998-cmo"] + self.neg = self.coords.formulas["neg"] + self.scale = self.coords.formulas["z"] + @parameterized.expand([ ("10", 10), ("2355498743", 2355498743), @@ -17,15 +27,41 @@ class MultipleContextTests(TestCase): ("13613624287328732", 13613624287328732) ]) def test_basic(self, name, scalar): - secp128r1 = get_params("secg", "secp128r1", "projective") - base = secp128r1.generator - coords = secp128r1.curve.coordinate_model - add = coords.formulas["add-1998-cmo"] - dbl = coords.formulas["dbl-1998-cmo"] - scl = coords.formulas["z"] - mult = LTRMultiplier(add, dbl, scl, always=False, complete=False, short_circuit=True) + mult = LTRMultiplier(self.add, self.dbl, self.scale, always=False, complete=False, short_circuit=True) with local(MultipleContext()) as ctx: - mult.init(secp128r1, base) + mult.init(self.secp128r1, self.base) mult.multiply(scalar) muls = list(ctx.points.values()) self.assertEqual(muls[-1], scalar) + + def test_precomp(self): + bnaf = BinaryNAFMultiplier(self.add, self.dbl, self.neg, self.scale) + with local(MultipleContext()) as ctx: + bnaf.init(self.secp128r1, self.base) + muls = list(ctx.points.values()) + self.assertListEqual(muls, [1, -1]) + + wnaf = WindowNAFMultiplier(self.add, self.dbl, self.neg, 3, self.scale) + with local(MultipleContext()) as ctx: + wnaf.init(self.secp128r1, self.base) + muls = list(ctx.points.values()) + self.assertListEqual(muls, [1, 2, 3, 5]) + + def test_ladder(self): + curve25519 = get_params("other", "Curve25519", "xz") + base = curve25519.generator + coords = curve25519.curve.coordinate_model + ladd = coords.formulas["ladd-1987-m"] + dadd = coords.formulas["dadd-1987-m"] + dbl = coords.formulas["dbl-1987-m"] + scale = coords.formulas["scale"] + ladd_mult = LadderMultiplier(ladd, dbl, scale) + with local(MultipleContext()) as ctx: + ladd_mult.init(curve25519, base) + ladd_mult.multiply(1339278426732672313) + print(ctx.points.values()) + dadd_mult = DifferentialLadderMultiplier(dadd, dbl, scale) + with local(MultipleContext()) as ctx: + dadd_mult.init(curve25519, base) + dadd_mult.multiply(1339278426732672313) + print(ctx.points.values()) |
