chiark / gitweb /
t/t-*.py: Use the `WriteBuffer.contents' property.
[catacomb-python] / t / t-group.py
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
30 import catacomb as C
31 import unittest as U
32 import testutils as T
33
34 ###--------------------------------------------------------------------------
35 class 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.WriteBuffer().putmp(i).contents)
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.WriteBuffer().zero(G.noctets - 1).putu8(1).contents)
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
247 TestGroups.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
255 if __name__ == "__main__": U.main()