summaryrefslogtreecommitdiffhomepage
path: root/test/ec/test_mod.py
blob: 24b3302c5d8f340b1be6cbd89aa17491928cffe7 (plain) (blame)
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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
from unittest import TestCase

from pyecsca.ec.mod import Mod, gcd, extgcd, Undefined, miller_rabin, has_gmp, RawMod
from pyecsca.ec.error import NonInvertibleError, NonResidueError, NonInvertibleWarning, NonResidueWarning
from pyecsca.misc.cfg import getconfig, TemporaryConfig


class ModTests(TestCase):

    def test_gcd(self):
        self.assertEqual(gcd(15, 20), 5)
        self.assertEqual(extgcd(15, 0), (1, 0, 15))
        self.assertEqual(extgcd(15, 20), (-1, 1, 5))

    def test_miller_rabin(self):
        self.assertTrue(miller_rabin(2))
        self.assertTrue(miller_rabin(3))
        self.assertTrue(miller_rabin(5))
        self.assertFalse(miller_rabin(8))
        self.assertTrue(miller_rabin(0xe807561107ccf8fa82af74fd492543a918ca2e9c13750233a9))
        self.assertFalse(miller_rabin(0x6f6889deb08da211927370810f026eb4c17b17755f72ea005))

    def test_inverse(self):
        p = 0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff
        self.assertEqual(Mod(0x702bdafd3c1c837b23a1cb196ed7f9fadb333c5cfe4a462be32adcd67bfb6ac1, p).inverse(), Mod(0x1cb2e5274bba085c4ca88eede75ae77949e7a410c80368376e97ab22eb590f9d, p))
        with self.assertRaises(NonInvertibleError):
            Mod(0, p).inverse()
        with self.assertRaises(NonInvertibleError):
            Mod(5, 10).inverse()
        getconfig().ec.no_inverse_action = "warning"
        with self.assertRaises(NonInvertibleWarning):
            Mod(0, p).inverse()
        with self.assertRaises(NonInvertibleWarning):
            Mod(5, 10).inverse()
        getconfig().ec.no_inverse_action = "ignore"
        Mod(0, p).inverse()
        Mod(5, 10).inverse()
        getconfig().ec.no_inverse_action = "error"

    def test_is_residue(self):
        self.assertTrue(Mod(4, 11).is_residue())
        self.assertFalse(Mod(11, 31).is_residue())
        self.assertTrue(Mod(0, 7).is_residue())
        self.assertTrue(Mod(1, 2).is_residue())

    def test_sqrt(self):
        p = 0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff
        self.assertIn(Mod(0xffffffff00000001000000000000000000000000fffffffffffffffffffffffc, p).sqrt(), (0x9add512515b70d9ec471151c1dec46625cd18b37bde7ca7fb2c8b31d7033599d, 0x6522aed9ea48f2623b8eeae3e213b99da32e74c9421835804d374ce28fcca662))
        with self.assertRaises(NonResidueError):
            Mod(0x702bdafd3c1c837b23a1cb196ed7f9fadb333c5cfe4a462be32adcd67bfb6ac1, p).sqrt()
        getconfig().ec.non_residue_action = "warning"
        with self.assertRaises(NonResidueWarning):
            Mod(0x702bdafd3c1c837b23a1cb196ed7f9fadb333c5cfe4a462be32adcd67bfb6ac1, p).sqrt()
        getconfig().ec.non_residue_action = "ignore"
        Mod(0x702bdafd3c1c837b23a1cb196ed7f9fadb333c5cfe4a462be32adcd67bfb6ac1, p).sqrt()
        with TemporaryConfig() as cfg:
            cfg.ec.non_residue_action = "warning"
            with self.assertRaises(NonResidueWarning):
                Mod(0x702bdafd3c1c837b23a1cb196ed7f9fadb333c5cfe4a462be32adcd67bfb6ac1, p).sqrt()
        self.assertEqual(Mod(0, p).sqrt(), Mod(0, p))
        q = 0x75d44fee9a71841ae8403c0c251fbad
        self.assertIn(Mod(0x591e0db18cf1bd81a11b2985a821eb3, q).sqrt(), (0x113b41a1a2b73f636e73be3f9a3716e, 0x64990e4cf7ba44b779cc7dcc8ae8a3f))
        getconfig().ec.non_residue_action = "error"

    def test_eq(self):
        self.assertEqual(Mod(1, 7), 1)
        self.assertNotEqual(Mod(1, 7), "1")
        self.assertEqual(Mod(1, 7), Mod(1, 7))
        self.assertNotEqual(Mod(1, 7), Mod(5, 7))
        self.assertNotEqual(Mod(1, 7), Mod(1, 5))

    def test_pow(self):
        a = Mod(5, 7)
        self.assertEqual(a**(-1), a.inverse())
        self.assertEqual(a**0, Mod(1, 7))
        self.assertEqual(a**(-2),a.inverse()**2)

    def test_wrong_mod(self):
        a = Mod(5, 7)
        b = Mod(4, 11)
        with self.assertRaises(ValueError):
            a + b

    def test_wrong_pow(self):
        a = Mod(5, 7)
        c = Mod(4, 11)
        with self.assertRaises(TypeError):
            a**c

    def test_other(self):
        a = Mod(5, 7)
        b = Mod(3, 7)
        self.assertEqual(int(-a), 2)
        self.assertEqual(str(a), "5")
        self.assertEqual(6 - a, Mod(1, 7))
        self.assertNotEqual(a, b)
        self.assertEqual(a / b, Mod(4, 7))
        self.assertEqual(a // b, Mod(4, 7))
        self.assertEqual(5 / b, Mod(4, 7))
        self.assertEqual(5 // b, Mod(4, 7))
        self.assertEqual(a / 3, Mod(4, 7))
        self.assertEqual(a // 3, Mod(4, 7))
        self.assertEqual(divmod(a, b), (Mod(1, 7), Mod(2, 7)))
        self.assertEqual(a + b, Mod(1, 7))
        self.assertEqual(5 + b, Mod(1, 7))
        self.assertEqual(a + 3, Mod(1, 7))
        self.assertNotEqual(a, 6)

    def test_undefined(self):
        u = Undefined()
        for k, meth in u.__class__.__dict__.items():
            if k in ("__module__", "__new__", "__init__", "__doc__", "__hash__", "__abstractmethods__", "_abc_impl"):
                continue
            args = [5 for _ in range(meth.__code__.co_argcount - 1)]
            if k == "__repr__":
                self.assertEqual(meth(u), "Undefined")
            elif k in ("__eq__", "__ne__"):
                assert not meth(u, *args)
            else:
                with self.assertRaises(NotImplementedError):
                    meth(u, *args)

    def test_implementation(self):
        if not has_gmp:
            self.skipTest("Only makes sense if more Mod implementations are available.")
        with TemporaryConfig() as cfg:
            cfg.ec.mod_implementation = "python"
            self.assertIsInstance(Mod(5, 7), RawMod)