aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJ08nY2020-02-19 16:45:16 +0100
committerJ08nY2020-02-19 16:45:16 +0100
commit9788c9af717a49f5e52d6db85afdcd940bb3578d (patch)
tree308aa803db524802336cbf244ec8e73e7585d638
parentdacf1e8950031ed01e5d3da0ad0934a209de0a41 (diff)
downloadpyecsca-9788c9af717a49f5e52d6db85afdcd940bb3578d.tar.gz
pyecsca-9788c9af717a49f5e52d6db85afdcd940bb3578d.tar.bz2
pyecsca-9788c9af717a49f5e52d6db85afdcd940bb3578d.zip
Fix LTR multiplier, add affine formula stuff.
-rw-r--r--pyecsca/ec/context.py8
-rw-r--r--pyecsca/ec/curve.py31
-rw-r--r--pyecsca/ec/model.py12
-rw-r--r--pyecsca/ec/mult.py2
-rw-r--r--test/ec/test_context.py6
-rw-r--r--test/ec/test_curve.py22
-rw-r--r--test/ec/test_curves.py11
-rw-r--r--test/ec/test_mult.py61
-rw-r--r--test/ec/test_params.py3
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)")