aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJ08nY2018-12-15 16:43:44 +0100
committerJ08nY2019-03-21 11:00:14 +0100
commitbec2c56a86ce1d0b2285aaed50726fbdba42d620 (patch)
tree65e4266481ed851a0f41367ecc8ba399de8f4240
parentba8212dbc9cee4c098838534c096486ad5bf759a (diff)
downloadpyecsca-bec2c56a86ce1d0b2285aaed50726fbdba42d620.tar.gz
pyecsca-bec2c56a86ce1d0b2285aaed50726fbdba42d620.tar.zst
pyecsca-bec2c56a86ce1d0b2285aaed50726fbdba42d620.zip
-rw-r--r--pyecsca/ec/context.py16
-rw-r--r--pyecsca/ec/formula.py28
-rw-r--r--pyecsca/ec/mult.py35
-rw-r--r--test/ec/test_mult.py37
4 files changed, 93 insertions, 23 deletions
diff --git a/pyecsca/ec/context.py b/pyecsca/ec/context.py
index b4667cf..e691184 100644
--- a/pyecsca/ec/context.py
+++ b/pyecsca/ec/context.py
@@ -13,7 +13,9 @@ class Context(object):
self.intermediates = []
self.actions = []
- def execute(self, formula: Formula, *points: Point, **params: Mod) -> Point:
+ def execute(self, formula: Formula, *points: Point, **params: Mod) -> Tuple[Point, ...]:
+ if len(points) != formula.num_inputs:
+ raise ValueError
self.actions.append((formula, tuple(points)))
coords = {}
for i, point in enumerate(points):
@@ -29,7 +31,11 @@ class Context(object):
previous_locals = set(locals.keys())
for key in diff:
self.intermediates.append((key, locals[key]))
- resulting = {variable: locals[variable + "3"]
- for variable in formula.coordinate_model.variables
- if variable + "3" in locals}
- return Point(formula.coordinate_model, **resulting)
+ result = []
+ for i in range(formula.num_outputs):
+ ind = str(i + 3)
+ resulting = {variable: locals[variable + ind]
+ for variable in formula.coordinate_model.variables
+ if variable + ind in locals}
+ result.append(Point(formula.coordinate_model, **resulting))
+ return tuple(result)
diff --git a/pyecsca/ec/formula.py b/pyecsca/ec/formula.py
index 877f4d5..80139b7 100644
--- a/pyecsca/ec/formula.py
+++ b/pyecsca/ec/formula.py
@@ -10,6 +10,8 @@ class Formula(object):
parameters: List[str]
assumptions: List[Expression]
code: List[Module]
+ _inputs: int
+ _outputs: int
def __init__(self, path: str, name: str, coordinate_model: Any):
self.name = name
@@ -39,29 +41,43 @@ class Formula(object):
for line in f.readlines():
self.code.append(parse(line.decode("ascii").replace("^", "**"), path, mode="exec"))
+ @property
+ def num_inputs(self):
+ return self._inputs
+
+ @property
+ def num_outputs(self):
+ return self._outputs
+
def __repr__(self):
return self.__class__.__name__ + "({} for {})".format(self.name, self.coordinate_model)
class AdditionFormula(Formula):
- pass
+ _inputs = 2
+ _outputs = 1
class DoublingFormula(Formula):
- pass
+ _inputs = 1
+ _outputs = 1
class TriplingFormula(Formula):
- pass
+ _inputs = 1
+ _outputs = 1
class ScalingFormula(Formula):
- pass
+ _inputs = 1
+ _outputs = 1
class DifferentialAdditionFormula(Formula):
- pass
+ _inputs = 3
+ _outputs = 1
class LadderFormula(Formula):
- pass
+ _inputs = 3
+ _outputs = 2
diff --git a/pyecsca/ec/mult.py b/pyecsca/ec/mult.py
index 4dd0f5b..a32a54b 100644
--- a/pyecsca/ec/mult.py
+++ b/pyecsca/ec/mult.py
@@ -1,9 +1,9 @@
from copy import copy
-from typing import Mapping
+from typing import Mapping, Tuple
from .context import Context
from .curve import EllipticCurve
-from .formula import Formula, AdditionFormula, DoublingFormula, ScalingFormula
+from .formula import Formula, AdditionFormula, DoublingFormula, ScalingFormula, LadderFormula
from .point import Point
@@ -30,19 +30,25 @@ class ScalarMultiplier(object):
return copy(other)
if other == self.curve.neutral:
return copy(one)
- return self.context.execute(self.formulas["add"], one, other, **self.curve.parameters)
+ return self.context.execute(self.formulas["add"], one, other, **self.curve.parameters)[0]
def _dbl(self, point: Point) -> Point:
if "dbl" not in self.formulas:
raise NotImplementedError
if point == self.curve.neutral:
return copy(point)
- return self.context.execute(self.formulas["dbl"], point, **self.curve.parameters)
+ return self.context.execute(self.formulas["dbl"], point, **self.curve.parameters)[0]
def _scl(self, point: Point) -> Point:
if "scl" not in self.formulas:
raise NotImplementedError
- return self.context.execute(self.formulas["scl"], point, **self.curve.parameters)
+ return self.context.execute(self.formulas["scl"], point, **self.curve.parameters)[0]
+
+ def _ladd(self, start: Point, to_dbl: Point, to_add: Point) -> Tuple[Point, Point]:
+ if "ladd" not in self.formulas:
+ raise NotImplementedError
+ return self.context.execute(self.formulas["ladd"], start, to_dbl, to_add,
+ **self.curve.parameters)
def multiply(self, scalar: int, point: Point) -> Point:
raise NotImplementedError
@@ -91,3 +97,22 @@ class RTLMultiplier(ScalarMultiplier):
if "scl" in self.formulas:
r = self._scl(r)
return r
+
+
+class LadderMultiplier(ScalarMultiplier):
+
+ def __init__(self, curve: EllipticCurve, ladd: LadderFormula, scl: ScalingFormula = None,
+ ctx: Context = None):
+ super().__init__(curve, ctx, ladd=ladd, scl=scl)
+
+ def multiply(self, scalar: int, point: Point) -> Point:
+ p0 = copy(point)
+ p1 = self._ladd(self.curve.neutral, point, point)[1]
+ for i in range(scalar.bit_length(), -1, -1):
+ if scalar & i != 0:
+ p0, p1 = self._ladd(point, p1, p0)
+ else:
+ p0, p1 = self._ladd(point, p0, p1)
+ if "scl" in self.formulas:
+ p0 = self._scl(p0)
+ return p0
diff --git a/test/ec/test_mult.py b/test/ec/test_mult.py
index ec26335..38c7367 100644
--- a/test/ec/test_mult.py
+++ b/test/ec/test_mult.py
@@ -2,8 +2,8 @@ from unittest import TestCase
from pyecsca.ec.curve import EllipticCurve
from pyecsca.ec.mod import Mod
-from pyecsca.ec.model import ShortWeierstrassModel
-from pyecsca.ec.mult import LTRMultiplier, RTLMultiplier
+from pyecsca.ec.model import ShortWeierstrassModel, MontgomeryModel
+from pyecsca.ec.mult import LTRMultiplier, RTLMultiplier, LadderMultiplier
from pyecsca.ec.point import Point
@@ -12,24 +12,47 @@ class ScalarMultiplierTests(TestCase):
def setUp(self):
self.p = 0xfffffffdffffffffffffffffffffffff
self.coords = ShortWeierstrassModel.coordinates["projective"]
+ self.base = Point(self.coords, X=Mod(0x161ff7528b899b2d0c28607ca52c5b86, self.p),
+ Y=Mod(0xcf5ac8395bafeb13c02da292dded7a83, self.p),
+ Z=Mod(1, self.p))
self.secp128r1 = EllipticCurve(ShortWeierstrassModel, self.coords,
dict(a=0xfffffffdfffffffffffffffffffffffc,
b=0xe87579c11079f43dd824993c2cee5ed3),
Point(self.coords, X=Mod(0, self.p), Y=Mod(1, self.p),
Z=Mod(0, self.p)))
- self.base = Point(self.coords, X=Mod(0x161ff7528b899b2d0c28607ca52c5b86, self.p),
- Y=Mod(0xcf5ac8395bafeb13c02da292dded7a83, self.p),
- Z=Mod(1, self.p))
+
+ self.coords25519 = MontgomeryModel.coordinates["xz"]
+ self.p25519 = 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed
+ self.base25519 = Point(self.coords25519, X=Mod(9, self.p25519),
+ Z=Mod(1, self.p25519))
+ self.curve25519 = EllipticCurve(MontgomeryModel, self.coords25519,
+ dict(a=486662, b=1),
+ Point(self.coords25519,
+ X=Mod(0, self.p25519), Z=Mod(1, self.p25519)))
def test_rtl_simple(self):
mult = RTLMultiplier(self.secp128r1, self.coords.formulas["add-1998-cmo"],
self.coords.formulas["dbl-1998-cmo"], self.coords.formulas["z"])
- mult.multiply(10, self.base)
+ res = mult.multiply(10, self.base)
+ other = mult.multiply(5, self.base)
+ other = mult.multiply(2, other)
+ self.assertEqual(res, other)
def test_ltr_simple(self):
mult = LTRMultiplier(self.secp128r1, self.coords.formulas["add-1998-cmo"],
self.coords.formulas["dbl-1998-cmo"], self.coords.formulas["z"])
- mult.multiply(10, self.base)
+ res = mult.multiply(10, self.base)
+ other = mult.multiply(5, self.base)
+ other = mult.multiply(2, other)
+ self.assertEqual(res, other)
+
+ def test_ladder_simple(self):
+ mult = LadderMultiplier(self.curve25519, self.coords25519.formulas["ladd-1987-m"],
+ self.coords25519.formulas["scale"])
+ res = mult.multiply(15, self.base25519)
+ other = mult.multiply(3, self.base25519)
+ other = mult.multiply(5, other)
+ self.assertEqual(res, other)
def test_basic_multipliers(self):
ltr = LTRMultiplier(self.secp128r1, self.coords.formulas["add-1998-cmo"],