chiark / gitweb /
t/: Add a test suite.
[catacomb-python] / t / t-group.py
CommitLineData
553d59fe
MW
1### -*-python-*-
2###
3### Testing cyclic-group functionality
4###
5### (c) 2019 Straylight/Edgeware
6###
7
8###----- Licensing notice ---------------------------------------------------
9###
10### This file is part of the Python interface to Catacomb.
11###
12### Catacomb/Python is free software: you can redistribute it and/or
13### modify it under the terms of the GNU General Public License as
14### published by the Free Software Foundation; either version 2 of the
15### License, or (at your option) any later version.
16###
17### Catacomb/Python is distributed in the hope that it will be useful, but
18### WITHOUT ANY WARRANTY; without even the implied warranty of
19### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20### General Public License for more details.
21###
22### You should have received a copy of the GNU General Public License
23### along with Catacomb/Python. If not, write to the Free Software
24### Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
25### USA.
26
27###--------------------------------------------------------------------------
28### Imported modules.
29
30import catacomb as C
31import unittest as U
32import testutils as T
33
34###--------------------------------------------------------------------------
35class TestGroups (T.GenericTestMixin):
36 """Test cyclic groups."""
37
38 def _test_group(me, G):
39
40 ## Some initial values.
41 id = G.i
42 g = G.g
43 x = g**2014319630
44 y = g**721326623
45
46 ## Check that they're all different.
47 v = [id, g, x, y]
48 for i in T.range(len(v)):
49 for j in T.range(len(v)):
50 if i == j: me.assertEqual(v[i], v[j])
51 else: me.assertNotEqual(v[i], v[j])
52
53 ## Basic arithmetic. Knowing the answers is too hard. For now, just
54 ## check that the field laws hold.
55 t = x*y; me.assertEqual(t/x, y); me.assertEqual(t/y, x)
56 me.assertEqual(x*x.inv(), id)
57 me.assertEqual(x.sqr(), x*x)
58 me.assertEqual(x/x, id)
59
60 ## Exponentiation.
61 me.assertEqual(x**G.r, id)
62 me.assertEqual(G.mexp((x, 5), (y, 7)), g**15120884511)
63
64 ## Comparisons. We've already done equality and inequality, and nothing
65 ## else should work.
66 me.assertRaises(TypeError, T.lt, x, y)
67 me.assertRaises(TypeError, T.le, x, y)
68 me.assertRaises(TypeError, T.ge, x, y)
69 me.assertRaises(TypeError, T.gt, x, y)
70
71 if isinstance(G, C.ECGroup):
72
73 ## Properties.
74 me.assertEqual(G.noctets, 2*G.info.curve.field.noctets + 1)
75 me.assertEqual(G.nbits, 2*G.info.curve.field.nbits)
76
77 ## Conversion to integer.
78 i = y.toint(); me.assertEqual(type(i), C.MP)
79 t = G(i); me.assertTrue(t == y or t == y.inv())
80
81 ## Conversion to elliptic curve.
82 Q = y.toec()
83 me.assertTrue(isinstance(Q, C.ECPtCurve))
84 me.assertEqual(G(Q), y)
85
86 ## Encoding.
87 t = y.tobuf()
88 me.assertEqual(t, Q.tobuf())
89 me.assertEqual(G.frombuf(t)[0], y)
90 me.assertEqual(id.tobuf(), C.ByteString.zero(2))
91 t = y.toraw()
92 me.assertEqual(t, Q.ec2osp())
93 me.assertEqual(G.fromraw(t)[0], y)
94 me.assertEqual(id.toraw(), C.ByteString.zero(1))
95
96 else:
97
98 ## Properties.
99 me.assertEqual(G.noctets, G.info.p.noctets)
100 if isinstance(G.info, C.BinDHInfo):
101 me.assertEqual(G.nbits, G.info.p.degree)
102 else:
103 me.assertEqual(G.nbits, G.info.p.nbits)
104
105 ## Conversion to integer.
106 i = y.toint(); me.assertEqual(type(i), C.MP)
107 me.assertTrue(G(i) == y)
108
109 ## Conversion to elliptic curve.
110 me.assertRaises(TypeError, G.toec, x)
111
112 ## Encoding.
113 t = y.tobuf()
114 me.assertEqual(t, C.ByteString(C.WriteBuffer().putmp(i)))
115 me.assertEqual(G.frombuf(t)[0], y)
116 me.assertEqual(id.tobuf(), C.bytes("000101"))
117 t = y.toraw()
118 me.assertEqual(t, i.storeb(G.noctets))
119 me.assertEqual(G.fromraw(t)[0], y)
120 me.assertEqual(id.toraw(),
121 C.ByteString(C.WriteBuffer().zero(G.noctets - 1).putu8(1)))
122
123 ## String conversion.
124 ystr = str(y)
125 me.assertEqual(G.fromstring(ystr), (y, ""))
126
127 ## Checking operations.
128 me.assertRaises(ValueError, id.check)
129 x.check()
130 y.check()
131 G.checkgroup()
132
133 def test_dhinfo(me):
134 dhinfo = C.DHInfo.parse("127, 7, 2")
135 me.assertEqual(dhinfo.p, 127)
136 me.assertEqual(dhinfo.r, 7)
137 me.assertEqual(dhinfo.g, 2)
138 dhinfo.group().checkgroup()
139
140 def test_bindhinfo(me):
141 bindhinfo = C.BinDHInfo.parse("0x805, 89, 0x22")
142 me.assertEqual(bindhinfo.p, C.GF(0x805))
143 me.assertEqual(bindhinfo.r, 89)
144 me.assertEqual(bindhinfo.g, C.GF(0x22))
145 bindhinfo.group().checkgroup()
146
147 def test_parse(me):
148
149 G = C.Group.parse("prime 127, 7, 2")
150 me.assertEqual(G.info.p, 127)
151 me.assertEqual(G.r, 7)
152 me.assertEqual(G.info.g, 2)
153 G.checkgroup()
154
155 G = C.Group.parse("bin 0x805, 89, 0x22")
156 me.assertEqual(G.info.p, C.GF(0x805))
157 me.assertEqual(G.r, 89)
158 me.assertEqual(G.info.g, C.GF(0x22))
159 G.checkgroup()
160
161 def test_gen_schnorr(me):
162 ev = T.EventRecorder()
163 dhinfo = C.DHInfo.generate(512, 64, event = ev,
164 rng = T.detrand("schnorr"))
165 me.assertEqual(dhinfo.p.nbits, 512)
166 me.assertEqual(dhinfo.r.nbits, 64)
167 me.assertTrue(dhinfo.p.primep())
168 me.assertTrue(dhinfo.r.primep())
169 me.assertEqual(dhinfo.p%dhinfo.r, 1)
170 me._test_group(dhinfo.group())
171 me.assertEqual(ev.events, "[q:F4/P26/D][p:F5/P5/D][g:D]")
172
173 def test_gen_limlee(me):
174 ev = T.EventRecorder()
175 dhinfo, ff = C.DHInfo.genlimlee(512, 64, event = ev, ievent = ev,
176 rng = T.detrand("limlee"))
177 me.assertEqual(dhinfo.p.nbits, 512)
178 me.assertEqual(dhinfo.r.nbits, 64)
179 me.assertTrue(dhinfo.p.primep())
180 me.assertTrue(dhinfo.r.primep())
181 for f in ff:
182 me.assertTrue(f.primep())
183 me.assertTrue(f.nbits >= 64)
184 me.assertEqual(C.MPMul().factor(2).factor(ff).done() + 1, dhinfo.p)
185 me._test_group(dhinfo.group())
186 me.assertEqual(ev.events,
187 "[p:"
188 "[p_0:F8/P26/D]"
189 "[p_1:P26/D]"
190 "[p_2:F4/P26/D]"
191 "[p_3:P26/D]"
192 "[p_4:F1/P26/D]"
193 "[p_5:F1/P26/D]"
194 "[p_6:P26/D]"
195 "[p*_7:P26/D]"
196 "[p_8:F1/P26/D]"
197 "[p_9:F1/P26/D]"
198 "[p*_10:P26/D]"
199 "[p_11:F6/P26/D]"
200 "[p_12:P26/D]"
201 "[p_13:P26/D]"
202 "[p_14:F4/P26/D]"
203 "[p_15:F1/P26/D]"
204 "[p_16:F1/P26/D]"
205 "[p_17:F1/P26/D]"
206 "[p_18:F6/P26/D]"
207 "[p_19:F1/P26/D]"
208 "[p_20:F3/P26/D]"
209 "[p_21:P26/D]"
210 "[p_22:F2/P26/D]"
211 "[p_23:F4/P26/D]"
212 "[p_24:F7/P26/D]"
213 "[p_25:F2/P26/D]"
214 "[p_26:F9/P26/D]"
215 "[p_27:F4/P26/D]"
216 "[p*_28:F11/P26/D]"
217 "[p*_29:F4/P26/D]"
218 "[p*_30:F1/P26/D]"
219 "[p*_31:F6/P26/D]"
220 "[p*_32:F4/P26/D]"
221 "[p*_33:F3/P26/D]"
222 "[p*_34:P26/D]"
223 "[p*_35:F3/P26/D]"
224 "[p*_36:F1/P26/D]"
225 "[p*_37:F1/P26/D]"
226 "[p*_38:F4/P26/D]"
227 "[p*_39:P26/D]"
228 "[p*_40:P26/D]"
229 "[p*_41:F2/P26/D]"
230 "[p*_42:F1/P26/D]"
231 "F22/P5/D]"
232 "[g:D]")
233
234 def test_gen_kcdsa(me):
235 ev = T.EventRecorder()
236 dhinfo, h = C.DHInfo.genkcdsa(512, 64, event = ev,
237 rng = T.detrand("kcdsa"))
238 me.assertEqual(dhinfo.p.nbits, 512)
239 me.assertEqual(dhinfo.r.nbits, 64)
240 me.assertTrue(dhinfo.p.primep())
241 me.assertTrue(dhinfo.r.primep())
242 me.assertTrue(h.primep())
243 me.assertEqual(2*h*dhinfo.r + 1, dhinfo.p)
244 me._test_group(dhinfo.group())
245 me.assertEqual(ev.events, "[v:F23/P6/D][p:F86/P26/D][g:D]")
246
247TestGroups.generate_testcases((name, map[name].group()) for name, map in
248 [("nist-p256", C.eccurves),
249 ("nist-b283", C.eccurves),
250 ("catacomb-ll-128-512", C.primegroups),
251 ("p1363-64", C.bingroups)])
252
253###----- That's all, folks --------------------------------------------------
254
255if __name__ == "__main__": U.main()