diff options
| author | J08nY | 2018-12-18 20:42:57 +0100 |
|---|---|---|
| committer | J08nY | 2019-03-21 11:00:14 +0100 |
| commit | fe1d8873331109342348d7ab58c3415c65aec57c (patch) | |
| tree | a433f020bc3611ccb523e354cbd05cc9d6be5571 | |
| parent | f4c73c9cc111d8975a7bac6a8ca3cd5d1c49804b (diff) | |
| download | pyecsca-fe1d8873331109342348d7ab58c3415c65aec57c.tar.gz pyecsca-fe1d8873331109342348d7ab58c3415c65aec57c.tar.zst pyecsca-fe1d8873331109342348d7ab58c3415c65aec57c.zip | |
| -rw-r--r-- | pyecsca/ec/curve.py | 2 | ||||
| -rw-r--r-- | pyecsca/ec/formula.py | 8 | ||||
| -rw-r--r-- | pyecsca/ec/mod.py | 7 | ||||
| -rw-r--r-- | pyecsca/ec/mult.py | 37 | ||||
| -rw-r--r-- | test/ec/test_mult.py | 25 |
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 |
