aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--pyecsca/ec/curve.py2
-rw-r--r--pyecsca/ec/formula.py8
-rw-r--r--pyecsca/ec/mod.py7
-rw-r--r--pyecsca/ec/mult.py37
-rw-r--r--test/ec/test_mult.py25
5 files changed, 66 insertions, 13 deletions
diff --git a/pyecsca/ec/curve.py b/pyecsca/ec/curve.py
index 4c9d401..20dd3e0 100644
--- a/pyecsca/ec/curve.py
+++ b/pyecsca/ec/curve.py
@@ -1,3 +1,4 @@
+from public import public
from typing import Mapping
from .coordinates import CoordinateModel
@@ -5,6 +6,7 @@ from .model import CurveModel
from .point import Point
+@public
class EllipticCurve(object):
model: CurveModel
coordinate_model: CoordinateModel
diff --git a/pyecsca/ec/formula.py b/pyecsca/ec/formula.py
index 5b6f028..e155282 100644
--- a/pyecsca/ec/formula.py
+++ b/pyecsca/ec/formula.py
@@ -1,5 +1,6 @@
from ast import parse, Expression, Module
from pkg_resources import resource_stream
+from public import public
from typing import List, Any
@@ -53,36 +54,43 @@ class Formula(object):
return f"{self.__class__.__name__}({self.name} for {self.coordinate_model})"
+@public
class AdditionFormula(Formula):
_inputs = 2
_outputs = 1
+@public
class DoublingFormula(Formula):
_inputs = 1
_outputs = 1
+@public
class TriplingFormula(Formula):
_inputs = 1
_outputs = 1
+@public
class NegationFormula(Formula):
_inputs = 1
_outputs = 1
+@public
class ScalingFormula(Formula):
_inputs = 1
_outputs = 1
+@public
class DifferentialAdditionFormula(Formula):
_inputs = 3
_outputs = 1
+@public
class LadderFormula(Formula):
_inputs = 3
_outputs = 2
diff --git a/pyecsca/ec/mod.py b/pyecsca/ec/mod.py
index bc1ebff..c8c9a92 100644
--- a/pyecsca/ec/mod.py
+++ b/pyecsca/ec/mod.py
@@ -1,6 +1,7 @@
from functools import wraps
+from public import public
-
+@public
def gcd(a, b):
if abs(a) < abs(b):
return gcd(b, a)
@@ -11,7 +12,7 @@ def gcd(a, b):
return a
-
+@public
def extgcd(a, b):
if abs(b) > abs(a):
(x, y, d) = extgcd(b, a)
@@ -42,7 +43,7 @@ def check(func):
return method
-
+@public
class Mod(object):
def __init__(self, x: int, n: int):
diff --git a/pyecsca/ec/mult.py b/pyecsca/ec/mult.py
index c0fe994..d7c5bc6 100644
--- a/pyecsca/ec/mult.py
+++ b/pyecsca/ec/mult.py
@@ -1,4 +1,5 @@
from copy import copy
+from public import public
from typing import Mapping, Tuple, Optional, MutableMapping
from pyecsca.ec.naf import naf, wnaf
@@ -74,6 +75,7 @@ class ScalarMultiplier(object):
raise NotImplementedError
+@public
class LTRMultiplier(ScalarMultiplier):
always: bool
@@ -97,6 +99,7 @@ class LTRMultiplier(ScalarMultiplier):
return r
+@public
class RTLMultiplier(ScalarMultiplier):
always: bool
@@ -121,6 +124,7 @@ class RTLMultiplier(ScalarMultiplier):
return r
+@public
class LadderMultiplier(ScalarMultiplier):
def __init__(self, curve: EllipticCurve, ladd: LadderFormula, scl: ScalingFormula = None,
@@ -131,16 +135,40 @@ class LadderMultiplier(ScalarMultiplier):
q = self._init_multiply(point)
p0 = copy(q)
p1 = self._ladd(self.curve.neutral, q, q)[1]
- for i in range(scalar.bit_length(), -1, -1):
- if scalar & i != 0:
- p0, p1 = self._ladd(q, p1, p0)
- else:
+ for i in range(scalar.bit_length() - 1, -1, -1):
+ if scalar & (1 << i) != 0:
p0, p1 = self._ladd(q, p0, p1)
+ else:
+ p1, p0 = self._ladd(q, p1, p0)
+ if "scl" in self.formulas:
+ p0 = self._scl(p0)
+ return p0
+
+
+@public
+class SimpleLadderMultiplier(ScalarMultiplier):
+
+ def __init__(self, curve: EllipticCurve, add: AdditionFormula, dbl: DoublingFormula,
+ scl: ScalingFormula = None, ctx: Context = None):
+ super().__init__(curve, ctx, add=add, dbl=dbl, scl=scl)
+
+ def multiply(self, scalar: int, point: Optional[Point] = None) -> Point:
+ q = self._init_multiply(point)
+ p0 = copy(q)
+ p1 = self._dbl(q)
+ for i in range(scalar.bit_length() - 2, -1, -1):
+ if scalar & (1 << i) != 0:
+ p0 = self._add(p0, p1)
+ p1 = self._dbl(p1)
+ else:
+ p1 = self._add(p0, p1)
+ p0 = self._dbl(p0)
if "scl" in self.formulas:
p0 = self._scl(p0)
return p0
+@public
class BinaryNAFMultiplier(ScalarMultiplier):
_point_neg: Point
@@ -167,6 +195,7 @@ class BinaryNAFMultiplier(ScalarMultiplier):
return q
+@public
class WindowNAFMultiplier(ScalarMultiplier):
_points: MutableMapping[int, Point]
_width: int
diff --git a/test/ec/test_mult.py b/test/ec/test_mult.py
index 258a525..cda9f76 100644
--- a/test/ec/test_mult.py
+++ b/test/ec/test_mult.py
@@ -3,7 +3,7 @@ from unittest import TestCase
from pyecsca.ec.curve import EllipticCurve
from pyecsca.ec.mod import Mod
from pyecsca.ec.model import ShortWeierstrassModel, MontgomeryModel
-from pyecsca.ec.mult import LTRMultiplier, RTLMultiplier, LadderMultiplier, BinaryNAFMultiplier, WindowNAFMultiplier
+from pyecsca.ec.mult import LTRMultiplier, RTLMultiplier, LadderMultiplier, BinaryNAFMultiplier, WindowNAFMultiplier, SimpleLadderMultiplier
from pyecsca.ec.point import Point
@@ -30,7 +30,7 @@ class ScalarMultiplierTests(TestCase):
Point(self.coords25519,
X=Mod(0, self.p25519), Z=Mod(1, self.p25519)))
- def test_rtl_simple(self):
+ def test_rtl(self):
mult = RTLMultiplier(self.secp128r1, self.coords.formulas["add-1998-cmo"],
self.coords.formulas["dbl-1998-cmo"], self.coords.formulas["z"])
res = mult.multiply(10, self.base)
@@ -38,7 +38,7 @@ class ScalarMultiplierTests(TestCase):
other = mult.multiply(2, other)
self.assertEqual(res, other)
- def test_ltr_simple(self):
+ def test_ltr(self):
mult = LTRMultiplier(self.secp128r1, self.coords.formulas["add-1998-cmo"],
self.coords.formulas["dbl-1998-cmo"], self.coords.formulas["z"])
res = mult.multiply(10, self.base)
@@ -46,7 +46,7 @@ class ScalarMultiplierTests(TestCase):
other = mult.multiply(2, other)
self.assertEqual(res, other)
- def test_ladder_simple(self):
+ def test_ladder(self):
mult = LadderMultiplier(self.curve25519, self.coords25519.formulas["ladd-1987-m"],
self.coords25519.formulas["scale"])
res = mult.multiply(15, self.base25519)
@@ -54,7 +54,15 @@ class ScalarMultiplierTests(TestCase):
other = mult.multiply(5, other)
self.assertEqual(res, other)
- def test_binary_naf_simple(self):
+ def test_simple_ladder(self):
+ mult = SimpleLadderMultiplier(self.secp128r1, self.coords.formulas["add-1998-cmo"],
+ self.coords.formulas["dbl-1998-cmo"], self.coords.formulas["z"])
+ res = mult.multiply(10, self.base)
+ other = mult.multiply(5, self.base)
+ other = mult.multiply(2, other)
+ self.assertEqual(res, other)
+
+ def test_binary_naf(self):
mult = BinaryNAFMultiplier(self.secp128r1, self.coords.formulas["add-1998-cmo"],
self.coords.formulas["dbl-1998-cmo"],
self.coords.formulas["neg"], self.coords.formulas["z"])
@@ -63,7 +71,7 @@ class ScalarMultiplierTests(TestCase):
other = mult.multiply(2, other)
self.assertEqual(res, other)
- def test_window_naf_simple(self):
+ def test_window_naf(self):
mult = WindowNAFMultiplier(self.secp128r1, self.coords.formulas["add-1998-cmo"],
self.coords.formulas["dbl-1998-cmo"],
self.coords.formulas["neg"], 3, self.coords.formulas["z"])
@@ -103,3 +111,8 @@ class ScalarMultiplierTests(TestCase):
self.coords.formulas["neg"], 3, self.coords.formulas["z"])
res_wnaf = wnaf.multiply(10, self.base)
self.assertEqual(res_wnaf, res_ltr)
+
+ ladder = SimpleLadderMultiplier(self.secp128r1, self.coords.formulas["add-1998-cmo"],
+ self.coords.formulas["dbl-1998-cmo"], self.coords.formulas["z"])
+ res_ladder = ladder.multiply(10, self.base)
+ self.assertEqual(res_ladder, res_ltr) \ No newline at end of file