diff options
| author | J08nY | 2023-07-29 16:08:03 +0200 |
|---|---|---|
| committer | J08nY | 2023-07-29 16:08:03 +0200 |
| commit | 58b3e0f862ab13f7125d40c9360b4b348366370a (patch) | |
| tree | e6dc34a67e75585ed0125e133d6c7bc8e21dc2d4 | |
| parent | b003b1d2437b842beafca0f13bea368c92a422fe (diff) | |
| download | pyecsca-58b3e0f862ab13f7125d40c9360b4b348366370a.tar.gz pyecsca-58b3e0f862ab13f7125d40c9360b4b348366370a.tar.zst pyecsca-58b3e0f862ab13f7125d40c9360b4b348366370a.zip | |
Add ZVP formula unroll.
| -rw-r--r-- | pyecsca/ec/formula.py | 1 | ||||
| -rw-r--r-- | pyecsca/ec/mod.py | 10 | ||||
| -rw-r--r-- | pyecsca/misc/cfg.py | 5 | ||||
| -rw-r--r-- | pyecsca/sca/re/zvp.py | 26 | ||||
| -rw-r--r-- | test/sca/test_zvp.py | 21 |
5 files changed, 55 insertions, 8 deletions
diff --git a/pyecsca/ec/formula.py b/pyecsca/ec/formula.py index 267aba0..7855622 100644 --- a/pyecsca/ec/formula.py +++ b/pyecsca/ec/formula.py @@ -40,6 +40,7 @@ class OpResult: return self.name def __repr__(self): + # TODO: This repr is broken for square and neg and inv. char = self.op.op_str parents = char.join(str(parent) for parent in self.parents) return f"{self.name} = {parents}" diff --git a/pyecsca/ec/mod.py b/pyecsca/ec/mod.py index 2d0893c..301bd70 100644 --- a/pyecsca/ec/mod.py +++ b/pyecsca/ec/mod.py @@ -10,7 +10,7 @@ dispatches to the implementation chosen by the runtime configuration of the libr import random import secrets from functools import wraps, lru_cache -from typing import Type, Dict, Any, Tuple, Union +from typing import Type, Dict, Any, Tuple, Union, Optional from public import public from sympy import Expr, FF @@ -564,13 +564,11 @@ class SymbolicMod(Mod): return hash(("SymbolicMod", self.x, self.n)) def __pow__(self, n) -> "SymbolicMod": - try: - x = pow(self.x, n, self.n) - except TypeError: - x = pow(self.x, n) % self.n - return SymbolicMod(x, self.n) + return self.__class__(pow(self.x, n), self.n) +_mod_classes["symbolic"] = SymbolicMod + if has_gmp: @lru_cache diff --git a/pyecsca/misc/cfg.py b/pyecsca/misc/cfg.py index 2affb27..ee9c95d 100644 --- a/pyecsca/misc/cfg.py +++ b/pyecsca/misc/cfg.py @@ -111,13 +111,14 @@ class ECConfig: - ``"gmp"``: Requires the GMP library and `gmpy2` package. - ``"python"``: Doesn't require anything. + - ``"symbolic"``: Requires sympy. """ return self._mod_implementation @mod_implementation.setter def mod_implementation(self, value: str): - if value not in ("python", "gmp"): - raise ValueError("Bad Mod implementaiton, can be one of 'python' or 'gmp'.") + if value not in ("python", "gmp", "symbolic"): + raise ValueError("Bad Mod implementaiton, can be one of 'python', 'gmp' or 'symbolic'.") self._mod_implementation = value diff --git a/pyecsca/sca/re/zvp.py b/pyecsca/sca/re/zvp.py new file mode 100644 index 0000000..46d4337 --- /dev/null +++ b/pyecsca/sca/re/zvp.py @@ -0,0 +1,26 @@ +""" +Provides functionality inspired by the Zero-value point attack + + Zero-Value Point Attacks on Elliptic Curve Cryptosystem, Toru Akishita & Tsuyoshi Takagi , ISC '03 + `<https://doi.org/10.1007/10958513_17>`_ +""" + +from sympy import symbols, FF, poly + +from pyecsca.ec.context import DefaultContext, local +from pyecsca.ec.formula import Formula +from pyecsca.ec.mod import SymbolicMod +from pyecsca.ec.point import Point +from pyecsca.misc.cfg import TemporaryConfig + + +def unroll_formula(formula: Formula, prime: int): + inputs = [Point(formula.coordinate_model, + **{var: SymbolicMod(symbols(var + str(i)), prime) for var in formula.coordinate_model.variables}) + for i in + range(1, 1 + formula.num_inputs)] + params = {var: SymbolicMod(symbols(var), prime) for var in formula.coordinate_model.curve_model.parameter_names} + with local(DefaultContext()) as ctx, TemporaryConfig() as cfg: + cfg.ec.mod_implementation = "symbolic" + formula(prime, *inputs, **params) + return [op_result.value for op_result in ctx.actions.get_by_index([0])[0].op_results] diff --git a/test/sca/test_zvp.py b/test/sca/test_zvp.py new file mode 100644 index 0000000..a6ce015 --- /dev/null +++ b/test/sca/test_zvp.py @@ -0,0 +1,21 @@ +from unittest import TestCase + +from pyecsca.ec.model import ShortWeierstrassModel +from pyecsca.sca.re.zvp import unroll_formula + + +class ZVPTests(TestCase): + def setUp(self): + self.model = ShortWeierstrassModel() + self.coords = self.model.coordinates["projective"] + self.add = self.coords.formulas["add-2007-bl"] + self.dbl = self.coords.formulas["dbl-2007-bl"] + self.neg = self.coords.formulas["neg"] + + def test_unroll(self): + results = unroll_formula(self.add, 11) + self.assertIsNotNone(results) + results = unroll_formula(self.dbl, 11) + self.assertIsNotNone(results) + results = unroll_formula(self.neg, 11) + self.assertIsNotNone(results) |
