chiark / gitweb /
t/: Add a test suite.
[catacomb-python] / t / t-rand.py
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)
124     me.assertEqual(rng.seed, (n + 153 + 3).storeb(16))
125
126   def test_bbs(me):
127     ev = T.EventRecorder()
128     drng = T.detrand("bbs")
129     rngpriv = C.BBSPriv.generate(1536, event = ev, rng = drng)
130     me.assertEqual(rngpriv.n.nbits, 1536)
131     me.assertEqual(rngpriv.p&3, 3)
132     me.assertEqual(rngpriv.q&3, 3)
133     me.assertTrue(rngpriv.p.primep())
134     me.assertTrue(rngpriv.q.primep())
135     me.assertEqual(rngpriv.n, rngpriv.p*rngpriv.q)
136     me.assertEqual(ev.events,
137                    "[p [s]:F10/P7/D]"
138                    "[p [t]:F2/P7/D]"
139                    "[p [r]:F7/P7/D]"
140                    "[p:F6/P3/D]"
141                    "[q [s]:P7/D]"
142                    "[q [t]:F33/P7/D]"
143                    "[q [r]:F33/P7/D]"
144                    "[q:F55/P3/D]")
145
146     x0 = drng.range(rngpriv.n)
147     rngpriv.seedmp(x0)
148     rng = C.BlumBlumShub(rngpriv.n, x0)
149     me.check_rand(rngpriv)
150     me.check_rand(rng)
151     me.assertEqual(rngpriv.x, rng.x)
152
153     msg = T.span(123)
154     rng.wrap()
155     ct = rng.mask(msg)
156     rng.wrap()
157
158     rngpriv.x = rng.x
159     nsteps = (123*8 + 7)//(rng.stepsz)
160     rngpriv.rew(nsteps + 1)
161     me.assertEqual(rngpriv.mask(ct), msg)
162
163 ###----- That's all, folks --------------------------------------------------
164
165 if __name__ == "__main__": U.main()