aboutsummaryrefslogtreecommitdiff
path: root/test/ec/test_formula.py
blob: ffae4c4787654658f4da6150ebd376b54ceeca4d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
from unittest import TestCase

from sympy import FF, symbols

from pyecsca.ec.mod import SymbolicMod, Mod
from pyecsca.misc.cfg import TemporaryConfig
from pyecsca.ec.error import UnsatisfiedAssumptionError
from pyecsca.ec.params import get_params
from pyecsca.ec.point import Point


class FormulaTests(TestCase):
    def setUp(self):
        self.secp128r1 = get_params("secg", "secp128r1", "projective")
        self.add = self.secp128r1.curve.coordinate_model.formulas["add-2007-bl"]
        self.dbl = self.secp128r1.curve.coordinate_model.formulas["dbl-2007-bl"]
        self.mdbl = self.secp128r1.curve.coordinate_model.formulas["mdbl-2007-bl"]
        self.jac_secp128r1 = get_params("secg", "secp128r1", "jacobian")
        self.jac_dbl = self.jac_secp128r1.curve.coordinate_model.formulas[
            "dbl-1998-hnm"
        ]

    def test_wrong_call(self):
        with self.assertRaises(ValueError):
            self.add(self.secp128r1.curve.prime)
        with self.assertRaises(ValueError):
            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)
        self.assertEqual(self.add.output_index, 3)

    def test_inputs_outputs(self):
        self.assertEqual(self.add.inputs, {"X1", "Y1", "Z1", "X2", "Y2", "Z2"})
        self.assertEqual(self.add.outputs, {"X3", "Y3", "Z3"})

    def test_eq(self):
        self.assertEqual(self.add, self.add)
        self.assertNotEqual(self.add, self.dbl)

    def test_num_ops(self):
        self.assertEqual(self.add.num_operations, 33)
        self.assertEqual(self.add.num_multiplications, 17)
        self.assertEqual(self.add.num_divisions, 0)
        self.assertEqual(self.add.num_inversions, 0)
        self.assertEqual(self.add.num_powers, 0)
        self.assertEqual(self.add.num_squarings, 6)
        self.assertEqual(self.add.num_addsubs, 10)

    def test_assumptions(self):
        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(
                self.secp128r1.curve.prime, other, **self.secp128r1.curve.parameters
            )
        with TemporaryConfig() as cfg:
            cfg.ec.unsatisfied_formula_assumption_action = "ignore"
            pt = self.mdbl(
                self.secp128r1.curve.prime, other, **self.secp128r1.curve.parameters
            )
            self.assertIsNotNone(pt)

    def test_parameters(self):
        res = self.jac_dbl(
            self.secp128r1.curve.prime,
            self.jac_secp128r1.generator,
            **self.jac_secp128r1.curve.parameters
        )
        self.assertIsNotNone(res)

    def test_symbolic(self):
        p = self.secp128r1.curve.prime
        k = FF(p)
        coords = self.secp128r1.curve.coordinate_model
        sympy_params = {
            key: SymbolicMod(k(int(value)), p)
            for key, value in self.secp128r1.curve.parameters.items()
        }
        symbolic_point = Point(
            coords, **{key: SymbolicMod(symbols(key), p) for key in coords.variables}
        )
        symbolic_double = self.dbl(p, symbolic_point, **sympy_params)[0]
        generator_double = self.dbl(
            p, self.secp128r1.generator, **self.secp128r1.curve.parameters
        )[0]
        for outer_var in coords.variables:
            symbolic_val = getattr(symbolic_double, outer_var).x
            generator_val = getattr(generator_double, outer_var).x
            for inner_var in coords.variables:
                symbolic_val = symbolic_val.subs(
                    inner_var, k(getattr(self.secp128r1.generator, inner_var).x)
                )
            self.assertEqual(Mod(int(symbolic_val), p), Mod(generator_val, p))