aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJ08nY2019-03-21 14:55:14 +0100
committerJ08nY2019-03-21 14:55:14 +0100
commit647dfbbec29d9a4cabf1ca132390c837870535fd (patch)
treeef2c7148bbe6365916abc6b3e4c5f83ccdaa6c49
parent626102a3885d5c9bea88cafcb143fe626685f4b6 (diff)
downloadpyecsca-647dfbbec29d9a4cabf1ca132390c837870535fd.tar.gz
pyecsca-647dfbbec29d9a4cabf1ca132390c837870535fd.tar.zst
pyecsca-647dfbbec29d9a4cabf1ca132390c837870535fd.zip
-rw-r--r--pyecsca/ec/coordinates.py26
-rw-r--r--pyecsca/ec/mod.py70
-rw-r--r--pyecsca/ec/model.py2
-rw-r--r--pyecsca/ec/op.py8
-rw-r--r--pyecsca/ec/point.py74
-rw-r--r--test/ec/test_coordinates.py25
-rw-r--r--test/ec/test_mult.py1
7 files changed, 182 insertions, 24 deletions
diff --git a/pyecsca/ec/coordinates.py b/pyecsca/ec/coordinates.py
index 795a935..817bff9 100644
--- a/pyecsca/ec/coordinates.py
+++ b/pyecsca/ec/coordinates.py
@@ -1,6 +1,6 @@
-from ast import parse, Expression
+from ast import parse, Expression, Module
from pkg_resources import resource_listdir, resource_isdir, resource_stream
-from typing import List, Any, MutableMapping
+from typing import List, Any, MutableMapping, Union
from .formula import (Formula, EFDFormula, AdditionEFDFormula, DoublingEFDFormula,
TriplingEFDFormula,
@@ -13,7 +13,7 @@ class CoordinateModel(object):
full_name: str
curve_model: Any
variables: List[str]
- satisfying: List[Expression]
+ satisfying: List[Union[Module, Expression]]
parameters: List[str]
assumptions: List[Expression]
formulas: MutableMapping[str, Formula]
@@ -34,15 +34,10 @@ class AffineCoordinateModel(CoordinateModel):
self.assumptions = []
self.formulas = {}
- def from_other(self, point):
- if point.coordinate_model.curve_model != self.curve_model:
- raise ValueError
- # TODO
- pass
-
- def to_other(self, other: CoordinateModel, point):
- # TODO
- pass
+ def __eq__(self, other):
+ if not isinstance(other, AffineCoordinateModel):
+ return False
+ return self.curve_model == other.curve_model
class EFDCoordinateModel(CoordinateModel):
@@ -88,8 +83,11 @@ class EFDCoordinateModel(CoordinateModel):
elif line.startswith("variable"):
self.variables.append(line[9:])
elif line.startswith("satisfying"):
- self.satisfying.append(
- parse(line[11:].replace("=", "==").replace("^", "**"), mode="eval"))
+ try:
+ code = parse(line[11:].replace("^", "**"), mode="exec")
+ except SyntaxError:
+ code = parse(line[11:].replace("=", "==").replace("^", "**"), mode="eval")
+ self.satisfying.append(code)
elif line.startswith("parameter"):
self.parameters.append(line[10:])
elif line.startswith("assume"):
diff --git a/pyecsca/ec/mod.py b/pyecsca/ec/mod.py
index c8c9a92..e9c5657 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):
@@ -12,6 +13,7 @@ def gcd(a, b):
return a
+
@public
def extgcd(a, b):
if abs(b) > abs(a):
@@ -43,6 +45,7 @@ def check(func):
return method
+
@public
class Mod(object):
@@ -141,3 +144,70 @@ class Mod(object):
r = (q * r)
i = i << 1
return r
+
+
+@public
+class Undefined(Mod):
+
+ def __init__(self):
+ pass
+
+ def __add__(self, other):
+ raise NotImplementedError
+
+ def __radd__(self, other):
+ raise NotImplementedError
+
+ def __sub__(self, other):
+ raise NotImplementedError
+
+ def __rsub__(self, other):
+ raise NotImplementedError
+
+ def __neg__(self):
+ raise NotImplementedError
+
+ def __invert__(self):
+ raise NotImplementedError
+
+ def __mul__(self, other):
+ raise NotImplementedError
+
+ def __rmul__(self, other):
+ raise NotImplementedError
+
+ def __truediv__(self, other):
+ raise NotImplementedError
+
+ def __rtruediv__(self, other):
+ raise NotImplementedError
+
+ def __floordiv__(self, other):
+ raise NotImplementedError
+
+ def __rfloordiv__(self, other):
+ raise NotImplementedError
+
+ def __div__(self, other):
+ raise NotImplementedError
+
+ def __rdiv__(self, other):
+ raise NotImplementedError
+
+ def __divmod__(self, divisor):
+ raise NotImplementedError
+
+ def __int__(self):
+ raise NotImplementedError
+
+ def __eq__(self, other):
+ return False
+
+ def __ne__(self, other):
+ return False
+
+ def __repr__(self):
+ return "Undefined"
+
+ def __pow__(self, n):
+ raise NotImplementedError
diff --git a/pyecsca/ec/model.py b/pyecsca/ec/model.py
index 397b0ee..53d530a 100644
--- a/pyecsca/ec/model.py
+++ b/pyecsca/ec/model.py
@@ -29,9 +29,9 @@ class EFDCurveModel(CurveModel):
_loaded: bool = False
def __init__(self, efd_name: str):
+ self._efd_name = efd_name
if self._loaded:
return
- self._efd_name = efd_name
self.__class__._loaded = True
self.__class__.coordinates = {}
self.__class__.parameter_names = []
diff --git a/pyecsca/ec/op.py b/pyecsca/ec/op.py
index b366617..ea2254f 100644
--- a/pyecsca/ec/op.py
+++ b/pyecsca/ec/op.py
@@ -1,4 +1,5 @@
from ast import Module, walk, Name
+from types import CodeType
from typing import FrozenSet
from .mod import Mod
@@ -15,6 +16,7 @@ class Op(object):
class CodeOp(Op):
code: Module
+ compiled: CodeType
def __init__(self, code: Module):
self.code = code
@@ -31,8 +33,12 @@ class CodeOp(Op):
params.add(name)
self.parameters = frozenset(params)
self.variables = frozenset(variables)
+ self.compiled = compile(self.code, "", mode="exec")
+
+ def __repr__(self):
+ return f"CodeOp({self.result} = f(params={self.parameters}, vars={self.variables}))"
def __call__(self, *args, **kwargs) -> Mod:
loc = dict(kwargs)
- exec(compile(self.code, "", mode="exec"), {}, loc)
+ exec(self.compiled, {}, loc)
return loc[self.result]
diff --git a/pyecsca/ec/point.py b/pyecsca/ec/point.py
index 0b9e9b3..052165f 100644
--- a/pyecsca/ec/point.py
+++ b/pyecsca/ec/point.py
@@ -1,10 +1,13 @@
+from copy import copy
+from public import public
from typing import Mapping
-from pyecsca.ec.formula import ScalingFormula
-from .coordinates import CoordinateModel
+from .coordinates import CoordinateModel, AffineCoordinateModel
from .mod import Mod
+from .op import CodeOp
+@public
class Point(object):
coordinate_model: CoordinateModel
coords: Mapping[str, Mod]
@@ -15,14 +18,41 @@ class Point(object):
self.coordinate_model = model
self.coords = coords
+ def to_affine(self):
+ if isinstance(self.coordinate_model, AffineCoordinateModel):
+ return copy(self)
+ ops = set()
+ for s in self.coordinate_model.satisfying:
+ try:
+ ops.add(CodeOp(s))
+ except:
+ pass
+ affine_model = AffineCoordinateModel(self.coordinate_model.curve_model)
+ # TODO: just fill in with undefined
+ if not set(map(lambda x: x.result, ops)).issuperset(affine_model.variables):
+ raise NotImplementedError
+ result = {}
+ for op in ops:
+ result[op.result] = op(**self.coords)
+ return Point(affine_model, **result)
+
+ @staticmethod
+ def from_affine(affine_point):
+ # TODO
+ pass
+
+ def equals(self, other):
+ if not isinstance(other, Point):
+ return False
+ if self.coordinate_model.curve_model != other.coordinate_model.curve_model:
+ return False
+ return self.to_affine() == other.to_affine()
+
def __eq__(self, other):
- # TODO: Somehow compare projective points. Via a map to an affinepoint?
- if type(other) is not Point:
+ if not isinstance(other, Point):
return False
- if self.coordinate_model != other.coordinate_model:
+ if self.coordinate_model != other.coordinate_model:
return False
- self_scaling = list(filter(lambda x: isinstance(x, ScalingFormula), self.coordinate_model.formulas.items()))
- other_scaling = list(filter(lambda x: isinstance(x, ScalingFormula), other.coordinate_model.formulas.items()))
return self.coords == other.coords
def __str__(self):
@@ -31,3 +61,33 @@ class Point(object):
def __repr__(self):
return f"Point([{str(self)}] in {self.coordinate_model})"
+
+
+@public
+class InfinityPoint(Point):
+
+ def __init__(self, model: CoordinateModel):
+ self.coordinate_model = model
+ self.coords = {}
+
+ def to_affine(self):
+ return InfinityPoint(AffineCoordinateModel(self.coordinate_model.curve_model))
+
+ @staticmethod
+ def from_affine(affine_point):
+ raise NotImplementedError
+
+ def equals(self, other):
+ return self == other
+
+ def __eq__(self, other):
+ if type(other) is not InfinityPoint:
+ return False
+ else:
+ return self.coordinate_model == other.coordinate_model
+
+ def __str__(self):
+ return "Infinity"
+
+ def __repr__(self):
+ return f"InfinityPoint({self.coordinate_model})"
diff --git a/test/ec/test_coordinates.py b/test/ec/test_coordinates.py
new file mode 100644
index 0000000..7532308
--- /dev/null
+++ b/test/ec/test_coordinates.py
@@ -0,0 +1,25 @@
+from unittest import TestCase
+
+from pyecsca.ec.curve import EllipticCurve
+from pyecsca.ec.mod import Mod
+from pyecsca.ec.model import ShortWeierstrassModel
+from pyecsca.ec.point import Point
+
+
+class CoordinateTests(TestCase):
+
+ def setUp(self):
+ self.p = 0xfffffffdffffffffffffffffffffffff
+ self.coords = ShortWeierstrassModel().coordinates["projective"]
+ self.secp128r1 = EllipticCurve(ShortWeierstrassModel(), self.coords,
+ dict(a=0xfffffffdfffffffffffffffffffffffc,
+ b=0xe87579c11079f43dd824993c2cee5ed3),
+ Point(self.coords, X=Mod(0, self.p), Y=Mod(1, self.p),
+ Z=Mod(0, self.p)))
+
+ def test_affine(self):
+ pt = Point(self.coords, X=Mod(0x161ff7528b899b2d0c28607ca52c5b86, self.p),
+ Y=Mod(0xcf5ac8395bafeb13c02da292dded7a83, self.p),
+ Z=Mod(1, self.p))
+ affine_Point = pt.to_affine()
+ assert pt.equals(affine_Point)
diff --git a/test/ec/test_mult.py b/test/ec/test_mult.py
index 82ed9eb..29e23ba 100644
--- a/test/ec/test_mult.py
+++ b/test/ec/test_mult.py
@@ -77,7 +77,6 @@ class ScalarMultiplierTests(TestCase):
ladder = LadderMultiplier(self.curve25519, self.coords25519.formulas["ladd-1987-m"],
self.coords25519.formulas["dbl-1987-m"],
self.coords25519.formulas["scale"])
- # TODO: fix this
differential = SimpleLadderMultiplier(self.curve25519,
self.coords25519.formulas["dadd-1987-m"],
self.coords25519.formulas["dbl-1987-m"],