diff options
| author | J08nY | 2020-02-19 16:45:16 +0100 |
|---|---|---|
| committer | J08nY | 2020-02-19 16:45:16 +0100 |
| commit | 9788c9af717a49f5e52d6db85afdcd940bb3578d (patch) | |
| tree | 308aa803db524802336cbf244ec8e73e7585d638 | |
| parent | dacf1e8950031ed01e5d3da0ad0934a209de0a41 (diff) | |
| download | pyecsca-9788c9af717a49f5e52d6db85afdcd940bb3578d.tar.gz pyecsca-9788c9af717a49f5e52d6db85afdcd940bb3578d.tar.zst pyecsca-9788c9af717a49f5e52d6db85afdcd940bb3578d.zip | |
| -rw-r--r-- | pyecsca/ec/context.py | 8 | ||||
| -rw-r--r-- | pyecsca/ec/curve.py | 31 | ||||
| -rw-r--r-- | pyecsca/ec/model.py | 12 | ||||
| -rw-r--r-- | pyecsca/ec/mult.py | 2 | ||||
| -rw-r--r-- | test/ec/test_context.py | 6 | ||||
| -rw-r--r-- | test/ec/test_curve.py | 22 | ||||
| -rw-r--r-- | test/ec/test_curves.py | 11 | ||||
| -rw-r--r-- | test/ec/test_mult.py | 61 | ||||
| -rw-r--r-- | test/ec/test_params.py | 3 |
9 files changed, 119 insertions, 37 deletions
diff --git a/pyecsca/ec/context.py b/pyecsca/ec/context.py index 9b57be6..d01f40e 100644 --- a/pyecsca/ec/context.py +++ b/pyecsca/ec/context.py @@ -38,10 +38,10 @@ class Tree(OrderedDict): if len(path) == 0: return self value = self[path[0]] - if isinstance(value, Tree): - return value.get_by_key(path[1:]) - elif len(path) == 1: + if len(path) == 1: return value + elif isinstance(value, Tree): + return value.get_by_key(path[1:]) else: raise ValueError @@ -134,7 +134,7 @@ class DefaultContext(Context): self.current.append(action) def exit_action(self, action: Action) -> None: - if self.current[-1] != action: + if len(self.current) < 1 or self.current[-1] != action: raise ValueError self.current.pop() diff --git a/pyecsca/ec/curve.py b/pyecsca/ec/curve.py index b161f7b..b9a4770 100644 --- a/pyecsca/ec/curve.py +++ b/pyecsca/ec/curve.py @@ -1,8 +1,9 @@ -from typing import MutableMapping, Union +from ast import Module +from typing import MutableMapping, Union, List from public import public -from .coordinates import CoordinateModel +from .coordinates import CoordinateModel, AffineCoordinateModel from .mod import Mod from .model import CurveModel from .point import Point @@ -33,6 +34,32 @@ class EllipticCurve(object): value = Mod(value, prime) self.parameters[name] = value + def _execute_base_formulas(self, formulas: List[Module], *points: Point) -> Point: + for point in points: + if point.coordinate_model.curve_model != self.model: + raise ValueError + if not isinstance(point.coordinate_model, AffineCoordinateModel): + raise ValueError + locals = {var + str(i + 1): point.coords[var] + for i, point in enumerate(points) for var in point.coords} + locals.update(self.parameters) + for line in formulas: + exec(compile(line, "", mode="exec"), None, locals) + return Point(AffineCoordinateModel(self), x=locals["x"], y=locals["y"]) + + def affine_add(self, one: Point, other: Point) -> Point: + return self._execute_base_formulas(self.model.base_addition, one, other) + + def affine_double(self, one: Point) -> Point: + return self._execute_base_formulas(self.model.base_doubling, one) + + def affine_negate(self, one: Point) -> Point: + return self._execute_base_formulas(self.model.base_negation, one) + + @property + def neutral_is_affine(self): + return bool(self.model.base_neutral) + def is_on_curve(self, point: Point) -> bool: if point.coordinate_model.curve_model != self.model: return False diff --git a/pyecsca/ec/model.py b/pyecsca/ec/model.py index 90c99a3..a28e700 100644 --- a/pyecsca/ec/model.py +++ b/pyecsca/ec/model.py @@ -1,8 +1,9 @@ from ast import parse, Expression, Module from os.path import join +from typing import List, MutableMapping + from pkg_resources import resource_listdir, resource_isdir, resource_stream from public import public -from typing import List, MutableMapping from .coordinates import EFDCoordinateModel, CoordinateModel @@ -23,11 +24,6 @@ class CurveModel(object): to_weierstrass: List[Module] from_weierstrass: List[Module] - # TODO: move the base_formulas into methods, operatin on affine points? - # Also to_weierstrass anf from_weierstrass. - - # TODO: __eq__ - class EFDCurveModel(CurveModel): _efd_name: str @@ -93,10 +89,6 @@ class EFDCurveModel(CurveModel): def __read_coordinate_dir(self, cls, dir_path, name): cls.coordinates[name] = EFDCoordinateModel(dir_path, name, self) - @classmethod - def add(cls, one, other): - pass - def __eq__(self, other): if not isinstance(other, EFDCurveModel): return False diff --git a/pyecsca/ec/mult.py b/pyecsca/ec/mult.py index ae7155b..e13003f 100644 --- a/pyecsca/ec/mult.py +++ b/pyecsca/ec/mult.py @@ -143,7 +143,7 @@ class LTRMultiplier(ScalarMultiplier): r = copy(self._params.neutral) top = self._params.order.bit_length() - 1 else: - q = self._dbl(self._point) + q = copy(self._point) # self._dbl(self._point) r = copy(self._point) top = scalar.bit_length() - 2 for i in range(top, -1, -1): diff --git a/test/ec/test_context.py b/test/ec/test_context.py index ea87b7f..8701046 100644 --- a/test/ec/test_context.py +++ b/test/ec/test_context.py @@ -3,6 +3,7 @@ from unittest import TestCase from pyecsca.ec.context import (local, DefaultContext, NullContext, getcontext, setcontext, resetcontext, Tree) from pyecsca.ec.curves import get_params +from pyecsca.ec.mod import RandomModAction from pyecsca.ec.mult import LTRMultiplier, ScalarMultiplicationAction @@ -68,6 +69,11 @@ class ContextTests(TestCase): self.assertIsInstance(next(iter(ctx.actions.keys())), ScalarMultiplicationAction) self.assertEqual(len(getcontext().actions), 0) + def test_default_no_enter(self): + with local(DefaultContext()) as default: + with self.assertRaises(ValueError): + default.exit_action(RandomModAction(7)) + def test_str(self): with local(DefaultContext()) as default: self.mult.multiply(59) diff --git a/test/ec/test_curve.py b/test/ec/test_curve.py index a68edcf..fa935fa 100644 --- a/test/ec/test_curve.py +++ b/test/ec/test_curve.py @@ -11,7 +11,9 @@ class CurveTests(TestCase): def setUp(self): self.secp128r1 = get_params("secg", "secp128r1", "projective") self.base = self.secp128r1.generator + self.affine_base = self.base.to_affine() self.curve25519 = get_params("other", "Curve25519", "xz") + self.ed25519 = get_params("other", "Ed25519", "projective") def test_init(self): with self.assertRaises(ValueError): @@ -31,13 +33,27 @@ class CurveTests(TestCase): X=Mod(0x161ff7528b899b2d0c28607ca52c5b86, self.secp128r1.curve.prime), Y=Mod(0xcf5ac8395bafeb13c02da292dded7a83, self.secp128r1.curve.prime), Z=Mod(1, self.secp128r1.curve.prime)) - assert self.secp128r1.curve.is_on_curve(pt) - assert self.secp128r1.curve.is_on_curve(pt.to_affine()) + self.assertTrue(self.secp128r1.curve.is_on_curve(pt)) + self.assertTrue(self.secp128r1.curve.is_on_curve(pt.to_affine())) other = Point(self.secp128r1.curve.coordinate_model, X=Mod(0x161ff7528b899b2d0c28607ca52c5b86, self.secp128r1.curve.prime), Y=Mod(0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, self.secp128r1.curve.prime), Z=Mod(1, self.secp128r1.curve.prime)) - assert not self.secp128r1.curve.is_on_curve(other) + self.assertFalse(self.secp128r1.curve.is_on_curve(other)) + + def test_affine_add(self): + self.assertIsNotNone(self.secp128r1.curve.affine_add(self.affine_base, self.affine_base)) + + def test_affine_double(self): + self.assertIsNotNone(self.secp128r1.curve.affine_double(self.affine_base)) + + def test_affine_negate(self): + self.assertIsNotNone(self.secp128r1.curve.affine_negate(self.affine_base)) + + def test_neutral_is_affine(self): + self.assertFalse(self.secp128r1.curve.neutral_is_affine) + self.assertFalse(self.curve25519.curve.neutral_is_affine) + self.assertTrue(self.ed25519.curve.neutral_is_affine) def test_eq(self): self.assertEqual(self.secp128r1.curve, self.secp128r1.curve) diff --git a/test/ec/test_curves.py b/test/ec/test_curves.py index 173aaf2..11861c4 100644 --- a/test/ec/test_curves.py +++ b/test/ec/test_curves.py @@ -30,4 +30,13 @@ class CurvesTests(TestCase): ]) def test_unknown(self, name, coords): with self.assertRaises(ValueError): - get_params(*name.split("/"), coords)
\ No newline at end of file + get_params(*name.split("/"), coords) + + def test_assumption(self): + with self.assertRaises(ValueError): + get_params("secg", "secp128r1", "projective-1") + self.assertIsNotNone(get_params("secg", "secp128r1", "projective-3")) + + def test_no_binary(self): + with self.assertRaises(ValueError): + get_params("secg", "sect163r1", "something")
\ No newline at end of file diff --git a/test/ec/test_mult.py b/test/ec/test_mult.py index 6c89521..63c6d25 100644 --- a/test/ec/test_mult.py +++ b/test/ec/test_mult.py @@ -41,6 +41,7 @@ class ScalarMultiplierTests(TestCase): self.assertPointEquality(res, other, scale) mult.init(params, base) self.assertEqual(InfinityPoint(params.curve.coordinate_model), mult.multiply(0)) + return res @parameterized.expand([ ("scaled", "add-1998-cmo", "dbl-1998-cmo", "z"), @@ -54,12 +55,17 @@ class ScalarMultiplierTests(TestCase): ("none", "add-1998-cmo", "dbl-1998-cmo", None) ]) def test_ltr(self, name, add, dbl, scale): - self.do_basic_test(LTRMultiplier, self.secp128r1, self.base, add, dbl, scale) - self.do_basic_test(LTRMultiplier, self.secp128r1, self.base, add, dbl, scale, always=True) - self.do_basic_test(LTRMultiplier, self.secp128r1, self.base, add, dbl, scale, - complete=False) - self.do_basic_test(LTRMultiplier, self.secp128r1, self.base, add, dbl, scale, always=True, - complete=False) + a = self.do_basic_test(LTRMultiplier, self.secp128r1, self.base, add, dbl, scale) + b = self.do_basic_test(LTRMultiplier, self.secp128r1, self.base, add, dbl, scale, + always=True) + c = self.do_basic_test(LTRMultiplier, self.secp128r1, self.base, add, dbl, scale, + complete=False) + d = self.do_basic_test(LTRMultiplier, self.secp128r1, self.base, add, dbl, scale, + always=True, + complete=False) + self.assertPointEquality(a, b, scale) + self.assertPointEquality(b, c, scale) + self.assertPointEquality(c, d, scale) @parameterized.expand([ ("scaled", "add-1998-cmo", "dbl-1998-cmo", "z"), @@ -69,10 +75,11 @@ class ScalarMultiplierTests(TestCase): self.do_basic_test(CoronMultiplier, self.secp128r1, self.base, add, dbl, scale) def test_ladder(self): - self.do_basic_test(LadderMultiplier, self.curve25519, self.base25519, "ladd-1987-m", - "dbl-1987-m", "scale") - self.do_basic_test(LadderMultiplier, self.curve25519, self.base25519, "ladd-1987-m", - "dbl-1987-m", "scale", complete=False) + a = self.do_basic_test(LadderMultiplier, self.curve25519, self.base25519, "ladd-1987-m", + "dbl-1987-m", "scale") + b = self.do_basic_test(LadderMultiplier, self.curve25519, self.base25519, "ladd-1987-m", + "dbl-1987-m", "scale", complete=False) + self.assertPointEquality(a, b, True) @parameterized.expand([ ("scaled", "add-1998-cmo", "dbl-1998-cmo", "z"), @@ -82,16 +89,21 @@ class ScalarMultiplierTests(TestCase): self.do_basic_test(SimpleLadderMultiplier, self.secp128r1, self.base, add, dbl, scale) @parameterized.expand([ - ("10", 15), - ("2355498743", 2355498743,) + ("10", 15, True), + ("10", 15, False), + ("2355498743", 2355498743, True), + ("2355498743", 2355498743, False), + ("325385790209017329644351321912443757746", 325385790209017329644351321912443757746, True), + ("325385790209017329644351321912443757746", 325385790209017329644351321912443757746, False) ]) - def test_ladder_differential(self, name, num): + def test_ladder_differential(self, name, num, complete): ladder = LadderMultiplier(self.coords25519.formulas["ladd-1987-m"], self.coords25519.formulas["dbl-1987-m"], - self.coords25519.formulas["scale"]) + self.coords25519.formulas["scale"], complete=complete) differential = DifferentialLadderMultiplier(self.coords25519.formulas["dadd-1987-m"], self.coords25519.formulas["dbl-1987-m"], - self.coords25519.formulas["scale"]) + self.coords25519.formulas["scale"], + complete=complete) ladder.init(self.curve25519, self.base25519) res_ladder = ladder.multiply(num) differential.init(self.curve25519, self.base25519) @@ -130,15 +142,20 @@ class ScalarMultiplierTests(TestCase): @parameterized.expand([ ("10", 10), - ("2355498743", 2355498743,) + ("2355498743", 2355498743), + ("325385790209017329644351321912443757746", 325385790209017329644351321912443757746) ]) def test_basic_multipliers(self, name, num): ltr = LTRMultiplier(self.coords.formulas["add-1998-cmo"], self.coords.formulas["dbl-1998-cmo"], self.coords.formulas["z"]) + with self.assertRaises(ValueError): + ltr.multiply(1) ltr.init(self.secp128r1, self.base) res_ltr = ltr.multiply(num) rtl = RTLMultiplier(self.coords.formulas["add-1998-cmo"], self.coords.formulas["dbl-1998-cmo"], self.coords.formulas["z"]) + with self.assertRaises(ValueError): + rtl.multiply(1) rtl.init(self.secp128r1, self.base) res_rtl = rtl.multiply(num) self.assertEqual(res_ltr, res_rtl) @@ -159,6 +176,8 @@ class ScalarMultiplierTests(TestCase): bnaf = BinaryNAFMultiplier(self.coords.formulas["add-1998-cmo"], self.coords.formulas["dbl-1998-cmo"], self.coords.formulas["neg"], self.coords.formulas["z"]) + with self.assertRaises(ValueError): + bnaf.multiply(1) bnaf.init(self.secp128r1, self.base) res_bnaf = bnaf.multiply(num) self.assertEqual(res_bnaf, res_ltr) @@ -166,6 +185,8 @@ class ScalarMultiplierTests(TestCase): wnaf = WindowNAFMultiplier(self.coords.formulas["add-1998-cmo"], self.coords.formulas["dbl-1998-cmo"], self.coords.formulas["neg"], 3, self.coords.formulas["z"]) + with self.assertRaises(ValueError): + wnaf.multiply(1) wnaf.init(self.secp128r1, self.base) res_wnaf = wnaf.multiply(num) self.assertEqual(res_wnaf, res_ltr) @@ -173,6 +194,8 @@ class ScalarMultiplierTests(TestCase): ladder = SimpleLadderMultiplier(self.coords.formulas["add-1998-cmo"], self.coords.formulas["dbl-1998-cmo"], self.coords.formulas["z"]) + with self.assertRaises(ValueError): + ladder.multiply(1) ladder.init(self.secp128r1, self.base) res_ladder = ladder.multiply(num) self.assertEqual(res_ladder, res_ltr) @@ -180,6 +203,8 @@ class ScalarMultiplierTests(TestCase): coron = CoronMultiplier(self.coords.formulas["add-1998-cmo"], self.coords.formulas["dbl-1998-cmo"], self.coords.formulas["z"]) + with self.assertRaises(ValueError): + coron.multiply(1) coron.init(self.secp128r1, self.base) res_coron = coron.multiply(num) self.assertEqual(res_coron, res_ltr) @@ -190,3 +215,7 @@ class ScalarMultiplierTests(TestCase): self.coords25519.formulas["scale"]) with self.assertRaises(ValueError): mult.init(self.secp128r1, self.base) + + with self.assertRaises(ValueError): + LadderMultiplier(self.coords25519.formulas["ladd-1987-m"], + scl=self.coords25519.formulas["scale"], complete=False) diff --git a/test/ec/test_params.py b/test/ec/test_params.py index da293f4..b4d55ee 100644 --- a/test/ec/test_params.py +++ b/test/ec/test_params.py @@ -17,3 +17,6 @@ class DomainParameterTests(TestCase): self.assertEqual(self.secp128r1, self.secp128r1) self.assertNotEqual(self.secp128r1, self.curve25519) self.assertNotEqual(self.secp128r1, None) + + def test_str(self): + self.assertEqual(str(self.secp128r1), "DomainParameters(secg/secp128r1)") |
