aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJ08nY2025-06-19 15:44:41 +0200
committerJ08nY2025-06-19 15:44:41 +0200
commitb244e5747258ad14e226a6f9df56ebc4be0f353b (patch)
tree61ec77fc351b059a6bf4e4d08ad0ebe79fac50a6
parente355d741135d22a8fcfe620d6961e71aa6c38b31 (diff)
downloadpyecsca-b244e5747258ad14e226a6f9df56ebc4be0f353b.tar.gz
pyecsca-b244e5747258ad14e226a6f9df56ebc4be0f353b.tar.zst
pyecsca-b244e5747258ad14e226a6f9df56ebc4be0f353b.zip
-rw-r--r--pyecsca/sca/re/rpa.py14
-rw-r--r--pyecsca/sca/re/zvp.py10
-rw-r--r--test/sca/test_rpa.py10
-rw-r--r--test/sca/test_zvp.py5
4 files changed, 34 insertions, 5 deletions
diff --git a/pyecsca/sca/re/rpa.py b/pyecsca/sca/re/rpa.py
index adef84d..3fa1e5b 100644
--- a/pyecsca/sca/re/rpa.py
+++ b/pyecsca/sca/re/rpa.py
@@ -81,6 +81,8 @@ class MultipleContext(Context):
def enter_action(self, action: Action) -> None:
if isinstance(action, (ScalarMultiplicationAction, PrecomputationAction)):
self.inside.append(action)
+ print("Entering action:", action)
+ print("base", self.base)
if self.base:
# If we already did some computation with this context try to see if we are building on top of it.
if self.base != action.point:
@@ -104,6 +106,7 @@ class MultipleContext(Context):
self.parents = {self.base: [], self.neutral: []}
self.formulas = {self.base: "", self.neutral: ""}
self.precomp = {}
+ print("after", self.base)
def exit_action(self, action: Action) -> None:
if isinstance(action, (ScalarMultiplicationAction, PrecomputationAction)):
@@ -113,6 +116,8 @@ class MultipleContext(Context):
if isinstance(action, FormulaAction) and self.inside:
action = cast(FormulaAction, action)
shortname = action.formula.shortname
+ print(action.input_points, action.output_points)
+ print(self.points)
if shortname == "dbl":
inp = action.input_points[0]
out = action.output_points[0]
@@ -424,7 +429,10 @@ class RPA(RE):
def _cached_fake_mult(
mult_class: Type[ScalarMultiplier], mult_factory: Callable, params: DomainParameters
) -> ScalarMultiplier:
- return fake_mult(mult_class, mult_factory, params)
+ fm = fake_mult(mult_class, mult_factory, params)
+ if fm.short_circuit:
+ raise ValueError("The multiplier must not short-circuit.")
+ return fm
@public
@@ -454,6 +462,10 @@ def multiples_computed(
:param kind: The kind of multiples to return. Can be one of "all", "input", "necessary", or "precomp+necessary".
:return: A list of tuples, where the first element is the formula shortname (e.g. "add") and the second is a tuple of the dlog
relationships to the input of the input points to the formula.
+
+ .. note::
+ The scalar multiplier must not short-circuit.
+ If `kind` is not "all", `use_init` must be `True`.
"""
if kind != "all" and not use_init:
raise ValueError("Cannot use kind other than 'all' with use_init=False.")
diff --git a/pyecsca/sca/re/zvp.py b/pyecsca/sca/re/zvp.py
index 956d0c2..2b4de20 100644
--- a/pyecsca/sca/re/zvp.py
+++ b/pyecsca/sca/re/zvp.py
@@ -588,7 +588,10 @@ def solve_hard_dcp_cypari(
def _cached_fake_mult(
mult_class: Type[ScalarMultiplier], mult_factory: Callable, params: DomainParameters
) -> ScalarMultiplier:
- return fake_mult(mult_class, mult_factory, params)
+ fm = fake_mult(mult_class, mult_factory, params)
+ if fm.short_circuit:
+ raise ValueError("The multiplier must not short-circuit.")
+ return fm
@public
@@ -611,9 +614,12 @@ def addition_chain(
:param use_multiply: Whether to consider the point multiples that happen in scalarmult multiply (after initialization).
:return: A list of tuples, where the first element is the formula shortname (e.g. "add") and the second is a tuple of the dlog
relationships to the input of the input points to the formula.
+
+ .. note::
+ The scalar multiplier must not short-circuit.
"""
mult = _cached_fake_mult(mult_class, mult_factory, params)
- ctx = MultipleContext()
+ ctx = MultipleContext(keep_base=True)
if use_init:
with local(ctx, copy=False):
mult.init(params, FakePoint(params.curve.coordinate_model))
diff --git a/test/sca/test_rpa.py b/test/sca/test_rpa.py
index 07757fd..8ba719c 100644
--- a/test/sca/test_rpa.py
+++ b/test/sca/test_rpa.py
@@ -82,6 +82,16 @@ def test_multiples(rpa_params):
assert multiples == {1, 2, 4, 8, 16, 17}
+def test_multiples_no_init(rpa_params):
+ multiples = multiples_computed(
+ 78699, rpa_params, LTRMultiplier,
+ lambda add, dbl, *args, **kwargs: LTRMultiplier(
+ add, dbl, None, False, AccumulationOrder.PeqPR, True, False
+ ), False, True
+ )
+ assert multiples
+
+
def test_multiples_bnaf(rpa_params):
mult_partial = partial(BinaryNAFMultiplier, always=True, direction=ProcessingDirection.LTR)
multiples = multiples_computed(
diff --git a/test/sca/test_zvp.py b/test/sca/test_zvp.py
index 496810b..6a06884 100644
--- a/test/sca/test_zvp.py
+++ b/test/sca/test_zvp.py
@@ -248,11 +248,12 @@ def test_addition_chain(secp128r1):
secp128r1,
LTRMultiplier,
lambda add, dbl, *args, **kwargs: LTRMultiplier(
- add, dbl, None, False, AccumulationOrder.PeqPR, True, True
+ add, dbl, None, False, AccumulationOrder.PeqPR, True, False
),
)
assert res is not None
- assert len(res) == 25
+ # Plenty of operations on infty point, due to complete=True and no short_circuit
+ assert len(res) == 138
@pytest.mark.parametrize("k", [7, 25, 31])