Commit | Line | Data |
---|---|---|
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 | ||
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.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 | ||
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() |