aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorJ08nY2021-01-16 16:33:43 +0100
committerJ08nY2021-01-16 16:42:20 +0100
commitb6d03e0935b21bf35542a282ba66ba25094234ca (patch)
tree2533c8098d05e499b49f76155ff7bb6b1ff8831a
parentcb397341f7e7b0647157ca8225d9dbeda14c7d2b (diff)
downloadpyecsca-b6d03e0935b21bf35542a282ba66ba25094234ca.tar.gz
pyecsca-b6d03e0935b21bf35542a282ba66ba25094234ca.tar.zst
pyecsca-b6d03e0935b21bf35542a282ba66ba25094234ca.zip
Also trace precomputation in MultipleContext.
-rw-r--r--pyecsca/ec/context.py30
-rw-r--r--pyecsca/ec/mult.py42
-rw-r--r--pyecsca/sca/__init__.py1
-rw-r--r--pyecsca/sca/re/__init__.py3
-rw-r--r--pyecsca/sca/re/rpa.py22
-rw-r--r--test/sca/test_rpa.py54
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())