Commit | Line | Data |
---|---|---|
553d59fe MW |
1 | ### -*-python-*- |
2 | ### | |
3 | ### Testing random-generator 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 TestRandomGenerator (U.TestCase): | |
36 | ||
37 | def check_rand(me, rng): | |
38 | ||
39 | for i in T.range(50): | |
40 | x = rng.byte() | |
41 | me.assertEqual(type(x), int) | |
42 | me.assertTrue(0 <= x < 256) | |
43 | ||
44 | x = rng.word() | |
45 | me.assertTrue(0 <= x <= 0xffffffff) | |
46 | ||
47 | for i in T.range(50): | |
48 | x = rng.range(10) | |
49 | me.assertEqual(type(x), int) | |
50 | me.assertTrue(0 <= x < 10) | |
51 | x = rng.range(T.MAXFIXNUM + 1) | |
52 | me.assertEqual(type(x), C.MP) | |
53 | ||
54 | for i in T.range(50): | |
55 | x = rng.mp(123, 7) | |
56 | me.assertEqual(type(x), C.MP) | |
57 | me.assertEqual(x.nbits, 123) | |
58 | me.assertEqual(x&7, 7) | |
59 | me.assertRaises((OverflowError, ValueError), rng.mp, 128, -1) | |
60 | me.assertRaises((OverflowError, ValueError), rng.mp, 128, C.MPW_MAX + 1) | |
61 | ||
62 | x = rng.block(17) | |
63 | me.assertEqual(type(x), C.ByteString) | |
64 | me.assertEqual(len(x), 17) | |
65 | ||
66 | def test_lcrand(me): | |
67 | rng = C.LCRand(0) | |
68 | me.assertFalse(rng.cryptop) | |
69 | w0 = rng.word() | |
70 | rng.seedint(0) | |
71 | me.assertEqual(rng.word(), w0) | |
72 | ||
73 | def test_firand(me): | |
74 | rng = C.FibRand(0) | |
75 | me.assertFalse(rng.cryptop) | |
76 | w0 = rng.word() | |
77 | rng.seedint(0) | |
78 | me.assertEqual(rng.word(), w0) | |
79 | ||
80 | def test_truerand(me): | |
81 | rng = C.TrueRand() | |
82 | me.assertTrue(rng.cryptop) | |
83 | me.check_rand(rng) | |
84 | rng.key(T.span(23)) | |
85 | rng.seed(256) | |
86 | me.assertRaises(ValueError, rng.seed, C.RAND_IBITS + 1) | |
87 | rng.seedint(-314) | |
88 | rng.seedword(0x12345678) | |
89 | rng.seedrand(T.detrand("seed-truerand")) | |
90 | rng.seedblock(T.span(123)) | |
91 | rng.add(T.span(123), 978) | |
92 | rng.gate() | |
93 | rng.stretch() | |
94 | rng.timer() | |
95 | me.check_rand(rng) | |
96 | ||
97 | def test_cryptorand(me): | |
98 | for r, kw in [("rijndael-counter", {}), | |
99 | ("rc4", {}), | |
100 | ("xchacha20", { "nonce": T.span(24) }), | |
101 | ("seal", { "i": 12345678 }), | |
102 | ("shake128", { "func": T.bin("TEST"), | |
103 | "perso": T.bin("Catacomb/Python test") }), | |
104 | ("kmac256", { "perso": T.bin("Catacomb/Python test") })]: | |
105 | rcls = C.gccrands[r] | |
106 | rng = rcls(T.span(rcls.keysz.default), **kw) | |
107 | me.assertTrue(rng.cryptop) | |
108 | ||
109 | def test_sslrand(me): | |
110 | rng = C.SSLRand(T.span(16), T.span(32), C.md5, C.sha) | |
111 | me.check_rand(rng) | |
112 | def test_tlsdx(me): | |
113 | rng = C.TLSDataExpansion(T.span(16), T.span(32), C.sha256_hmac) | |
114 | me.check_rand(rng) | |
115 | def test_tlsprf(me): | |
116 | rng = C.TLSPRF(T.span(16), T.span(32), C.md5_hmac, C.sha_hmac) | |
117 | me.check_rand(rng) | |
118 | ||
119 | def test_dsarand(me): | |
120 | seed = T.span(16) | |
121 | n = C.MP.loadb(seed) | |
122 | rng = C.DSARand(seed) | |
123 | me.check_rand(rng) | |
eac76e37 MW |
124 | if T.MAXFIXNUM == (1 << 31) - 1: steps = 153 + 3 |
125 | elif T.MAXFIXNUM == (1 << 63) - 1: steps = 153 | |
126 | else: steps = None | |
127 | if steps is not None: me.assertEqual(rng.seed, (n + steps).storeb(16)) | |
553d59fe MW |
128 | |
129 | def test_bbs(me): | |
130 | ev = T.EventRecorder() | |
131 | drng = T.detrand("bbs") | |
132 | rngpriv = C.BBSPriv.generate(1536, event = ev, rng = drng) | |
133 | me.assertEqual(rngpriv.n.nbits, 1536) | |
134 | me.assertEqual(rngpriv.p&3, 3) | |
135 | me.assertEqual(rngpriv.q&3, 3) | |
136 | me.assertTrue(rngpriv.p.primep()) | |
137 | me.assertTrue(rngpriv.q.primep()) | |
138 | me.assertEqual(rngpriv.n, rngpriv.p*rngpriv.q) | |
139 | me.assertEqual(ev.events, | |
140 | "[p [s]:F10/P7/D]" | |
141 | "[p [t]:F2/P7/D]" | |
142 | "[p [r]:F7/P7/D]" | |
143 | "[p:F6/P3/D]" | |
144 | "[q [s]:P7/D]" | |
145 | "[q [t]:F33/P7/D]" | |
146 | "[q [r]:F33/P7/D]" | |
147 | "[q:F55/P3/D]") | |
148 | ||
149 | x0 = drng.range(rngpriv.n) | |
150 | rngpriv.seedmp(x0) | |
151 | rng = C.BlumBlumShub(rngpriv.n, x0) | |
152 | me.check_rand(rngpriv) | |
153 | me.check_rand(rng) | |
154 | me.assertEqual(rngpriv.x, rng.x) | |
155 | ||
156 | msg = T.span(123) | |
157 | rng.wrap() | |
158 | ct = rng.mask(msg) | |
159 | rng.wrap() | |
160 | ||
161 | rngpriv.x = rng.x | |
162 | nsteps = (123*8 + 7)//(rng.stepsz) | |
163 | rngpriv.rew(nsteps + 1) | |
164 | me.assertEqual(rngpriv.mask(ct), msg) | |
165 | ||
166 | ###----- That's all, folks -------------------------------------------------- | |
167 | ||
168 | if __name__ == "__main__": U.main() |