aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorJ08nY2021-01-19 18:07:31 +0100
committerJ08nY2021-01-19 18:07:31 +0100
commit950811a3e6a995e8bd3b2063777aeddd2bee1b0f (patch)
tree8c9676e27d973215c96402c815a54075a174feb0
parent616255ba3c8346e58152610941270d864caa89d9 (diff)
downloadpyecsca-950811a3e6a995e8bd3b2063777aeddd2bee1b0f.tar.gz
pyecsca-950811a3e6a995e8bd3b2063777aeddd2bee1b0f.tar.zst
pyecsca-950811a3e6a995e8bd3b2063777aeddd2bee1b0f.zip
Introduce explicit field argument to formula calls.
-rw-r--r--pyecsca/ec/formula.py26
-rw-r--r--pyecsca/ec/mult.py12
-rw-r--r--pyecsca/ec/point.py14
-rw-r--r--pyecsca/ec/signature.py2
-rw-r--r--test/ec/test_formula.py12
-rw-r--r--test/ec/test_regress.py4
6 files changed, 44 insertions, 26 deletions
diff --git a/pyecsca/ec/formula.py b/pyecsca/ec/formula.py
index 38701cb..7a2736a 100644
--- a/pyecsca/ec/formula.py
+++ b/pyecsca/ec/formula.py
@@ -113,7 +113,12 @@ class Formula(ABC):
unified: bool
"""Whether the formula is specifies that it is unified."""
- def __validate_points(self, points, params):
+ def __validate_params(self, field, params):
+ for key, value in params.items():
+ if not isinstance(value, Mod) or value.n != field:
+ raise ValueError(f"Wrong param input {key} = {value}.")
+
+ def __validate_points(self, field, points, params):
# Validate number of inputs.
if len(points) != self.num_inputs:
raise ValueError(f"Wrong number of inputs for {self}.")
@@ -122,6 +127,8 @@ class Formula(ABC):
if point.coordinate_model != self.coordinate_model:
raise ValueError(f"Wrong coordinate model of point {point}.")
for coord, value in point.coords.items():
+ if not isinstance(value, Mod) or value.n != field:
+ raise ValueError(f"Wrong coordinate input {coord} = {value} of point {i}.")
params[coord + str(i + 1)] = value
def __validate_assumptions(self, field, params):
@@ -147,11 +154,11 @@ class Formula(ABC):
raise ValueError(
f"This formula couldn't be executed due to an unsupported assumption ({assumption_string}).")
- def resolve(expr):
- if not expr.args:
- return expr
+ def resolve(expression):
+ if not expression.args:
+ return expression
args = []
- for arg in expr.args:
+ for arg in expression.args:
if isinstance(arg, Rational):
a = arg.numerator()
b = arg.denominator()
@@ -159,7 +166,7 @@ class Formula(ABC):
else:
arg = resolve(arg)
args.append(arg)
- return expr.func(*args)
+ return expression.func(*args)
expr = resolve(expr)
poly = Poly(expr, symbols(param), domain=k)
@@ -170,17 +177,18 @@ class Formula(ABC):
else:
raise UnsatisfiedAssumptionError(f"Unsatisfied assumption in the formula ({assumption_string}).")
- def __call__(self, *points: Any, **params: Mod) -> Tuple[Any, ...]:
+ def __call__(self, field: int, *points: Any, **params: Mod) -> Tuple[Any, ...]:
"""
Execute a formula.
+ :param field: The field over which the computation is performed.
:param points: Points to pass into the formula.
:param params: Parameters of the curve.
:return: The resulting point(s).
"""
from .point import Point
- self.__validate_points(points, params)
- field = int(params[next(iter(params.keys()))].n) # TODO: This is nasty...
+ self.__validate_params(field, params)
+ self.__validate_points(field, points, params)
self.__validate_assumptions(field, params)
# Execute the actual formula.
with FormulaAction(self, *points, **params) as action:
diff --git a/pyecsca/ec/mult.py b/pyecsca/ec/mult.py
index 74325b5..1650736 100644
--- a/pyecsca/ec/mult.py
+++ b/pyecsca/ec/mult.py
@@ -73,7 +73,7 @@ class ScalarMultiplier(ABC):
return copy(other)
if other == self._params.curve.neutral:
return copy(one)
- return self.formulas["add"](one, other, **self._params.curve.parameters)[0]
+ return self.formulas["add"](self._params.curve.prime, one, other, **self._params.curve.parameters)[0]
def _dbl(self, point: Point) -> Point:
if "dbl" not in self.formulas:
@@ -81,12 +81,12 @@ class ScalarMultiplier(ABC):
if self.short_circuit:
if point == self._params.curve.neutral:
return copy(point)
- return self.formulas["dbl"](point, **self._params.curve.parameters)[0]
+ return self.formulas["dbl"](self._params.curve.prime, point, **self._params.curve.parameters)[0]
def _scl(self, point: Point) -> Point:
if "scl" not in self.formulas:
raise NotImplementedError
- return self.formulas["scl"](point, **self._params.curve.parameters)[0]
+ return self.formulas["scl"](self._params.curve.prime, point, **self._params.curve.parameters)[0]
def _ladd(self, start: Point, to_dbl: Point, to_add: Point) -> Tuple[Point, ...]:
if "ladd" not in self.formulas:
@@ -96,7 +96,7 @@ class ScalarMultiplier(ABC):
return to_dbl, to_add
if to_add == self._params.curve.neutral:
return self._dbl(to_dbl), to_dbl
- return self.formulas["ladd"](start, to_dbl, to_add, **self._params.curve.parameters)
+ return self.formulas["ladd"](self._params.curve.prime, start, to_dbl, to_add, **self._params.curve.parameters)
def _dadd(self, start: Point, one: Point, other: Point) -> Point:
if "dadd" not in self.formulas:
@@ -106,12 +106,12 @@ class ScalarMultiplier(ABC):
return copy(other)
if other == self._params.curve.neutral:
return copy(one)
- return self.formulas["dadd"](start, one, other, **self._params.curve.parameters)[0]
+ return self.formulas["dadd"](self._params.curve.prime, start, one, other, **self._params.curve.parameters)[0]
def _neg(self, point: Point) -> Point:
if "neg" not in self.formulas:
raise NotImplementedError
- return self.formulas["neg"](point, **self._params.curve.parameters)[0]
+ return self.formulas["neg"](self._params.curve.prime, point, **self._params.curve.parameters)[0]
def init(self, params: DomainParameters, point: Point):
"""
diff --git a/pyecsca/ec/point.py b/pyecsca/ec/point.py
index df9e054..11aee7d 100644
--- a/pyecsca/ec/point.py
+++ b/pyecsca/ec/point.py
@@ -33,14 +33,24 @@ class Point(object):
"""A point with coordinates in a coordinate model."""
coordinate_model: CoordinateModel
coords: Mapping[str, Mod]
+ field: int
def __init__(self, model: CoordinateModel, **coords: Mod):
if not set(model.variables) == set(coords.keys()):
raise ValueError
self.coordinate_model = model
self.coords = coords
+ field = None
+ for value in self.coords.values():
+ if field is None:
+ field = value.n
+ else:
+ if field != value.n:
+ raise ValueError(f"Mismatched coordinate field of definition, {field} vs {value.n}.")
+ self.field = field
def __getattribute__(self, name):
+ # Do the magic such that point.X1 works!
if "coords" in super().__getattribute__("__dict__"):
coords = super().__getattribute__("coords")
if name in coords:
@@ -141,8 +151,8 @@ class Point(object):
return False
if "z" in self.coordinate_model.formulas:
formula = self.coordinate_model.formulas["z"]
- self_mapped = formula(self)
- other_mapped = formula(other)
+ self_mapped = formula(self.field, self)
+ other_mapped = formula(self.field, other)
return self_mapped == other_mapped
else:
raise ValueError("No scaling formula available.")
diff --git a/pyecsca/ec/signature.py b/pyecsca/ec/signature.py
index e61dc1b..a97594b 100644
--- a/pyecsca/ec/signature.py
+++ b/pyecsca/ec/signature.py
@@ -186,7 +186,7 @@ class Signature(object):
p1 = self.mult.multiply(int(u1))
self.mult.init(self.params, self.pubkey)
p2 = self.mult.multiply(int(u2))
- p = self.add(p1, p2, **self.params.curve.parameters)[0]
+ p = self.add(self.params.curve.prime, p1, p2, **self.params.curve.parameters)[0]
affine = p.to_affine()
v = Mod(int(affine.x), self.params.order)
return signature.r == int(v)
diff --git a/test/ec/test_formula.py b/test/ec/test_formula.py
index 779b140..a7ef691 100644
--- a/test/ec/test_formula.py
+++ b/test/ec/test_formula.py
@@ -18,9 +18,9 @@ class FormulaTests(TestCase):
def test_wrong_call(self):
with self.assertRaises(ValueError):
- self.add()
+ self.add(self.secp128r1.curve.prime)
with self.assertRaises(ValueError):
- self.add(self.secp128r1.generator.to_affine(), self.secp128r1.generator.to_affine())
+ self.add(self.secp128r1.curve.prime, self.secp128r1.generator.to_affine(), self.secp128r1.generator.to_affine())
def test_indices(self):
self.assertEqual(self.add.input_index, 1)
@@ -44,18 +44,18 @@ class FormulaTests(TestCase):
self.assertEqual(self.add.num_addsubs, 10)
def test_assumptions(self):
- res = self.mdbl(self.secp128r1.generator, **self.secp128r1.curve.parameters)
+ res = self.mdbl(self.secp128r1.curve.prime, self.secp128r1.generator, **self.secp128r1.curve.parameters)
self.assertIsNotNone(res)
coords = {name: value * 5 for name, value in self.secp128r1.generator.coords.items()}
other = Point(self.secp128r1.generator.coordinate_model, **coords)
with self.assertRaises(UnsatisfiedAssumptionError):
- self.mdbl(other, **self.secp128r1.curve.parameters)
+ self.mdbl(self.secp128r1.curve.prime, other, **self.secp128r1.curve.parameters)
with TemporaryConfig() as cfg:
cfg.ec.unsatisfied_formula_assumption_action = "ignore"
- pt = self.mdbl(other, **self.secp128r1.curve.parameters)
+ pt = self.mdbl(self.secp128r1.curve.prime, other, **self.secp128r1.curve.parameters)
self.assertIsNotNone(pt)
def test_parameters(self):
- res = self.jac_dbl(self.jac_secp128r1.generator, **self.jac_secp128r1.curve.parameters)
+ res = self.jac_dbl(self.secp128r1.curve.prime, self.jac_secp128r1.generator, **self.jac_secp128r1.curve.parameters)
self.assertIsNotNone(res)
diff --git a/test/ec/test_regress.py b/test/ec/test_regress.py
index fe14eb3..ef593fc 100644
--- a/test/ec/test_regress.py
+++ b/test/ec/test_regress.py
@@ -47,12 +47,12 @@ class RegressionTests(TestCase):
curve = EllipticCurve(model, coords, p, neutral, {"a": Mod(8, p), "b": Mod(1, p)})
base = Point(coords, X=Mod(12, p), Z=Mod(1, p))
formula = coords.formulas["dbl-1987-m-2"]
- res = formula(base, **curve.parameters)[0]
+ res = formula(p, base, **curve.parameters)[0]
self.assertIsNotNone(res)
affine_base = Point(AffineCoordinateModel(model), x=Mod(12, p), y=Mod(2, p))
dbase = curve.affine_double(affine_base).to_model(coords, curve)
ladder = coords.formulas["ladd-1987-m-3"]
- one, other = ladder(base, dbase, base, **curve.parameters)
+ one, other = ladder(p, base, dbase, base, **curve.parameters)
self.assertIsNotNone(one)
self.assertIsNotNone(other)