diff options
| author | J08nY | 2019-03-21 15:35:14 +0100 |
|---|---|---|
| committer | J08nY | 2019-03-21 15:35:14 +0100 |
| commit | fdae772214f70c9caa7920c1cc63f9696c1b4a11 (patch) | |
| tree | 916bce2a52ef9f328e7d769c0dfe98bd4d67fffa | |
| parent | 647dfbbec29d9a4cabf1ca132390c837870535fd (diff) | |
| download | pyecsca-fdae772214f70c9caa7920c1cc63f9696c1b4a11.tar.gz pyecsca-fdae772214f70c9caa7920c1cc63f9696c1b4a11.tar.zst pyecsca-fdae772214f70c9caa7920c1cc63f9696c1b4a11.zip | |
| -rw-r--r-- | pyecsca/ec/curve.py | 24 | ||||
| -rw-r--r-- | pyecsca/ec/mult.py | 2 | ||||
| -rw-r--r-- | pyecsca/sca/trace_set/inspector.py | 8 | ||||
| -rw-r--r-- | pyecsca/sca/ttest.py | 10 | ||||
| -rw-r--r-- | test/ec/curves.py | 26 | ||||
| -rw-r--r-- | test/ec/test_coordinates.py | 7 | ||||
| -rw-r--r-- | test/ec/test_curve.py | 20 | ||||
| -rw-r--r-- | test/ec/test_mult.py | 36 |
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"], |
