aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--pyecsca/ec/curve.py24
-rw-r--r--pyecsca/ec/mult.py2
-rw-r--r--pyecsca/sca/trace_set/inspector.py8
-rw-r--r--pyecsca/sca/ttest.py10
-rw-r--r--test/ec/curves.py26
-rw-r--r--test/ec/test_coordinates.py7
-rw-r--r--test/ec/test_curve.py20
-rw-r--r--test/ec/test_mult.py36
8 files changed, 93 insertions, 40 deletions
diff --git a/pyecsca/ec/curve.py b/pyecsca/ec/curve.py
index ea18233..4b84d24 100644
--- a/pyecsca/ec/curve.py
+++ b/pyecsca/ec/curve.py
@@ -1,7 +1,8 @@
from public import public
-from typing import Mapping
+from typing import Mapping, Union
from .coordinates import CoordinateModel
+from .mod import Mod
from .model import CurveModel
from .point import Point
@@ -10,11 +11,12 @@ from .point import Point
class EllipticCurve(object):
model: CurveModel
coordinate_model: CoordinateModel
- parameters: Mapping[str, int]
+ prime: int
+ parameters: Mapping[str, Mod]
neutral: Point
def __init__(self, model: CurveModel, coordinate_model: CoordinateModel,
- parameters: Mapping[str, int], neutral: Point):
+ prime: int, parameters: Mapping[str, Union[Mod, int]], neutral: Point):
# TODO: Add base_point arg, order arg, cofactor arg.
if coordinate_model not in model.coordinates.values():
raise ValueError
@@ -24,12 +26,22 @@ class EllipticCurve(object):
raise ValueError
self.model = model
self.coordinate_model = coordinate_model
- self.parameters = dict(parameters)
+ self.prime = prime
+ self.parameters = {}
+ for name, value in parameters.items():
+ if isinstance(value, Mod):
+ if value.n != prime:
+ raise ValueError
+ else:
+ value = Mod(value, prime)
+ self.parameters[name] = value
self.neutral = neutral
def is_on_curve(self, point: Point) -> bool:
- #TODO
- pass
+ if point.coordinate_model != self.coordinate_model:
+ return False
+ loc = {**self.parameters, **point.to_affine().coords}
+ return eval(compile(self.model.equation, "", mode="eval"), loc)
def is_neutral(self, point: Point) -> bool:
return self.neutral == point
diff --git a/pyecsca/ec/mult.py b/pyecsca/ec/mult.py
index 36d3896..fa225b3 100644
--- a/pyecsca/ec/mult.py
+++ b/pyecsca/ec/mult.py
@@ -162,6 +162,8 @@ class CoronMultiplier(ScalarMultiplier):
super().__init__(curve, ctx, add=add, dbl=dbl, scl=scl)
def multiply(self, scalar: int, point: Optional[Point] = None):
+ if scalar == 0:
+ return copy(self.curve.neutral)
q = self._init_multiply(point)
p0 = copy(q)
for i in range(scalar.bit_length() - 2, -1, -1):
diff --git a/pyecsca/sca/trace_set/inspector.py b/pyecsca/sca/trace_set/inspector.py
index 067d348..4964f85 100644
--- a/pyecsca/sca/trace_set/inspector.py
+++ b/pyecsca/sca/trace_set/inspector.py
@@ -70,11 +70,11 @@ class InspectorTraceSet(TraceSet):
title_space: int = 0
global_title: str = "title"
- description: str = None
+ description: Optional[str] = None
x_offset: int = 0
- x_label: str = None
- y_label: str = None
+ x_label: Optional[str] = None
+ y_label: Optional[str] = None
x_scale: float = 1
y_scale: float = 1
@@ -85,7 +85,7 @@ class InspectorTraceSet(TraceSet):
scope_coupling: int = 0
scope_offset: float = 0
scope_impedance: float = 0
- scope_id: str = None
+ scope_id: Optional[str] = None
filter_type: int = 0
filter_frequency: float = 0
diff --git a/pyecsca/sca/ttest.py b/pyecsca/sca/ttest.py
index 34e631c..329f37d 100644
--- a/pyecsca/sca/ttest.py
+++ b/pyecsca/sca/ttest.py
@@ -1,13 +1,13 @@
+import numpy as np
from public import public
from scipy.stats import ttest_ind
-import numpy as np
from typing import Sequence, Optional
from .trace import Trace, CombinedTrace
def ttest_func(first_set: Sequence[Trace], second_set: Sequence[Trace],
- equal_var: bool) -> Optional[CombinedTrace]:
+ equal_var: bool) -> Optional[CombinedTrace]:
if not first_set or not second_set or len(first_set) == 0 or len(second_set) == 0:
return None
first_stack = np.stack([first.samples for first in first_set])
@@ -15,8 +15,9 @@ def ttest_func(first_set: Sequence[Trace], second_set: Sequence[Trace],
result = ttest_ind(first_stack, second_stack, axis=0, equal_var=equal_var)
return CombinedTrace(None, None, result[0], parents=[*first_set, *second_set])
+
@public
-def welch_ttest(first_set: Sequence[Trace], second_set: Sequence[Trace]) -> CombinedTrace:
+def welch_ttest(first_set: Sequence[Trace], second_set: Sequence[Trace]) -> Optional[CombinedTrace]:
"""
Perform the Welch's t-test sample wise on two sets of traces `first_set` and `second_set`.
Useful for Test Vector Leakage Analysis (TVLA).
@@ -27,8 +28,9 @@ def welch_ttest(first_set: Sequence[Trace], second_set: Sequence[Trace]) -> Comb
"""
return ttest_func(first_set, second_set, False)
+
@public
-def student_ttest(first_set: Sequence[Trace], second_set: Sequence[Trace]) -> CombinedTrace:
+def student_ttest(first_set: Sequence[Trace], second_set: Sequence[Trace]) -> Optional[CombinedTrace]:
"""
Perform the Students's t-test sample wise on two sets of traces `first_set` and `second_set`.
Useful for Test Vector Leakage Analysis (TVLA).
diff --git a/test/ec/curves.py b/test/ec/curves.py
new file mode 100644
index 0000000..d36e702
--- /dev/null
+++ b/test/ec/curves.py
@@ -0,0 +1,26 @@
+from pyecsca.ec.curve import EllipticCurve
+from pyecsca.ec.mod import Mod
+from pyecsca.ec.model import ShortWeierstrassModel, MontgomeryModel
+from pyecsca.ec.point import InfinityPoint, Point
+
+
+def get_secp128r1():
+ prime = 0xfffffffdffffffffffffffffffffffff
+ model = ShortWeierstrassModel()
+ coords = ShortWeierstrassModel().coordinates["projective"]
+ return (EllipticCurve(model, coords, prime, dict(a=0xfffffffdfffffffffffffffffffffffc,
+ b=0xe87579c11079f43dd824993c2cee5ed3),
+ InfinityPoint(coords)),
+ Point(coords, X=Mod(0x161ff7528b899b2d0c28607ca52c5b86, prime),
+ Y=Mod(0xcf5ac8395bafeb13c02da292dded7a83, prime),
+ Z=Mod(1, prime)))
+
+
+def get_curve25519():
+ prime = 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed
+ model = MontgomeryModel()
+ coords = model.coordinates["xz"]
+ return (EllipticCurve(model, coords, prime,
+ dict(a=486662, b=1),
+ InfinityPoint(coords)),
+ Point(coords, X=Mod(9, prime), Z=Mod(1, prime)))
diff --git a/test/ec/test_coordinates.py b/test/ec/test_coordinates.py
index 7532308..31f3edf 100644
--- a/test/ec/test_coordinates.py
+++ b/test/ec/test_coordinates.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
-from pyecsca.ec.point import Point
+from pyecsca.ec.point import Point, InfinityPoint
class CoordinateTests(TestCase):
@@ -11,11 +11,10 @@ class CoordinateTests(TestCase):
def setUp(self):
self.p = 0xfffffffdffffffffffffffffffffffff
self.coords = ShortWeierstrassModel().coordinates["projective"]
- self.secp128r1 = EllipticCurve(ShortWeierstrassModel(), self.coords,
+ self.secp128r1 = EllipticCurve(ShortWeierstrassModel(), self.coords, self.p,
dict(a=0xfffffffdfffffffffffffffffffffffc,
b=0xe87579c11079f43dd824993c2cee5ed3),
- Point(self.coords, X=Mod(0, self.p), Y=Mod(1, self.p),
- Z=Mod(0, self.p)))
+ InfinityPoint(self.coords))
def test_affine(self):
pt = Point(self.coords, X=Mod(0x161ff7528b899b2d0c28607ca52c5b86, self.p),
diff --git a/test/ec/test_curve.py b/test/ec/test_curve.py
new file mode 100644
index 0000000..7e8e7eb
--- /dev/null
+++ b/test/ec/test_curve.py
@@ -0,0 +1,20 @@
+from unittest import TestCase
+
+from pyecsca.ec.mod import Mod
+from pyecsca.ec.point import Point, InfinityPoint
+from test.ec.curves import get_secp128r1
+
+
+class CurveTests(TestCase):
+ def setUp(self):
+ self.secp128r1, self.base = get_secp128r1()
+
+ def test_is_on_curve(self):
+ pt = Point(self.secp128r1.coordinate_model,
+ X=Mod(0x161ff7528b899b2d0c28607ca52c5b86, self.secp128r1.prime),
+ Y=Mod(0xcf5ac8395bafeb13c02da292dded7a83, self.secp128r1.prime),
+ Z=Mod(1, self.secp128r1.prime))
+ assert self.secp128r1.is_on_curve(pt)
+
+ def test_is_neutral(self):
+ assert self.secp128r1.is_neutral(InfinityPoint(self.secp128r1.coordinate_model))
diff --git a/test/ec/test_mult.py b/test/ec/test_mult.py
index 29e23ba..8a82e3a 100644
--- a/test/ec/test_mult.py
+++ b/test/ec/test_mult.py
@@ -1,35 +1,19 @@
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, SimpleLadderMultiplier, CoronMultiplier)
-from pyecsca.ec.point import Point
+from pyecsca.ec.point import InfinityPoint
+from test.ec.curves import get_secp128r1, get_curve25519
class ScalarMultiplierTests(TestCase):
def setUp(self):
- self.p = 0xfffffffdffffffffffffffffffffffff
- self.coords = ShortWeierstrassModel().coordinates["projective"]
- self.base = Point(self.coords, X=Mod(0x161ff7528b899b2d0c28607ca52c5b86, self.p),
- Y=Mod(0xcf5ac8395bafeb13c02da292dded7a83, self.p),
- Z=Mod(1, self.p))
- 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)))
+ self.secp128r1, self.base = get_secp128r1()
+ self.coords = self.secp128r1.coordinate_model
- self.coords25519 = MontgomeryModel().coordinates["xz"]
- self.p25519 = 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed
- self.base25519 = Point(self.coords25519, X=Mod(9, self.p25519),
- Z=Mod(1, self.p25519))
- self.curve25519 = EllipticCurve(MontgomeryModel(), self.coords25519,
- dict(a=486662, b=1),
- Point(self.coords25519,
- X=Mod(0, self.p25519), Z=Mod(1, self.p25519)))
+ self.curve25519, self.base25519 = get_curve25519()
+ self.coords25519 = self.curve25519.coordinate_model
def test_rtl(self):
mult = RTLMultiplier(self.secp128r1, self.coords.formulas["add-1998-cmo"],
@@ -38,6 +22,7 @@ class ScalarMultiplierTests(TestCase):
other = mult.multiply(5, self.base)
other = mult.multiply(2, other)
self.assertEqual(res, other)
+ self.assertEqual(InfinityPoint(self.coords), mult.multiply(0, self.base))
def test_ltr(self):
mult = LTRMultiplier(self.secp128r1, self.coords.formulas["add-1998-cmo"],
@@ -46,6 +31,7 @@ class ScalarMultiplierTests(TestCase):
other = mult.multiply(5, self.base)
other = mult.multiply(2, other)
self.assertEqual(res, other)
+ self.assertEqual(InfinityPoint(self.coords), mult.multiply(0, self.base))
def test_coron(self):
mult = CoronMultiplier(self.secp128r1, self.coords.formulas["add-1998-cmo"],
@@ -54,6 +40,7 @@ class ScalarMultiplierTests(TestCase):
other = mult.multiply(5, self.base)
other = mult.multiply(2, other)
self.assertEqual(res, other)
+ self.assertEqual(InfinityPoint(self.coords), mult.multiply(0, self.base))
def test_ladder(self):
mult = LadderMultiplier(self.curve25519, self.coords25519.formulas["ladd-1987-m"],
@@ -63,6 +50,7 @@ class ScalarMultiplierTests(TestCase):
other = mult.multiply(5, self.base25519)
other = mult.multiply(3, other)
self.assertEqual(res, other)
+ self.assertEqual(InfinityPoint(self.coords25519), mult.multiply(0, self.base25519))
def test_simple_ladder(self):
mult = SimpleLadderMultiplier(self.secp128r1, self.coords.formulas["add-1998-cmo"],
@@ -72,6 +60,7 @@ class ScalarMultiplierTests(TestCase):
other = mult.multiply(5, self.base)
other = mult.multiply(2, other)
self.assertEqual(res, other)
+ self.assertEqual(InfinityPoint(self.coords), mult.multiply(0, self.base))
def test_ladder_differential(self):
ladder = LadderMultiplier(self.curve25519, self.coords25519.formulas["ladd-1987-m"],
@@ -84,6 +73,7 @@ class ScalarMultiplierTests(TestCase):
res_ladder = ladder.multiply(15, self.base25519)
res_differential = differential.multiply(15, self.base25519)
self.assertEqual(res_ladder, res_differential)
+ self.assertEqual(InfinityPoint(self.coords25519), differential.multiply(0, self.base25519))
def test_binary_naf(self):
mult = BinaryNAFMultiplier(self.secp128r1, self.coords.formulas["add-1998-cmo"],
@@ -93,6 +83,7 @@ class ScalarMultiplierTests(TestCase):
other = mult.multiply(5, self.base)
other = mult.multiply(2, other)
self.assertEqual(res, other)
+ self.assertEqual(InfinityPoint(self.coords), mult.multiply(0, self.base))
def test_window_naf(self):
mult = WindowNAFMultiplier(self.secp128r1, self.coords.formulas["add-1998-cmo"],
@@ -102,6 +93,7 @@ class ScalarMultiplierTests(TestCase):
other = mult.multiply(5, self.base)
other = mult.multiply(2, other)
self.assertEqual(res, other)
+ self.assertEqual(InfinityPoint(self.coords), mult.multiply(0, self.base))
mult = WindowNAFMultiplier(self.secp128r1, self.coords.formulas["add-1998-cmo"],
self.coords.formulas["dbl-1998-cmo"],