1 ### -*- mode: python, coding: utf-8 -*-
3 ### Test symmetric algorithms
5 ### (c) 2019 Straylight/Edgeware
8 ###----- Licensing notice ---------------------------------------------------
10 ### This file is part of the Python interface to Catacomb.
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.
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.
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,
27 ###--------------------------------------------------------------------------
34 ###--------------------------------------------------------------------------
37 def bad_key_size(ksz
):
38 if isinstance(ksz
, C
.KeySZAny
): return None
39 elif isinstance(ksz
, C
.KeySZRange
):
40 if ksz
.mod
!= 1: return ksz
.min + 1
41 elif ksz
.max != 0: return ksz
.max + 1
42 elif ksz
.min != 0: return ksz
.min - 1
44 elif isinstance(ksz
, C
.KeySZSet
):
45 for sz
in sorted(ksz
.set):
46 if sz
+ 1 not in ksz
.set: return sz
+ 1
47 assert False, "That should have worked."
51 def different_key_size(ksz
, sz
):
52 if isinstance(ksz
, C
.KeySZAny
): return sz
+ 1
53 elif isinstance(ksz
, C
.KeySZRange
):
54 if sz
> ksz
.min: return sz
- ksz
.mod
55 elif ksz
.max == 0 or sz
< ksz
.max: return sz
+ ksz
.mod
57 elif isinstance(ksz
, C
.KeySZSet
):
58 for sz1
in sorted(ksz
.set):
59 if sz
!= sz1
: return sz1
64 class HashBufferTestMixin (U
.TestCase
):
65 """Mixin class for testing all of the various `hash...' methods."""
67 def check_hashbuffer_hashn(me
, w
, bigendp
, makefn
, hashfn
):
70 ## Check encoding an integer.
71 h0
, donefn0
= makefn(w
+ 2)
72 hashfn(h0
.hashu8(0x00), T
.bytes_as_int(w
, bigendp
)).hashu8(w
+ 1)
73 h1
, donefn1
= makefn(w
+ 2)
74 h1
.hash(T
.span(w
+ 2))
75 me
.assertEqual(donefn0(), donefn1())
77 ## Check overflow detection.
79 me
.assertRaises((OverflowError, ValueError),
82 def check_hashbuffer_bufn(me
, w
, bigendp
, makefn
, hashfn
):
83 """Check `hashbufN'."""
85 ## Go through a number of different sizes.
86 for n
in [0, 1, 7, 8, 19, 255, 12345, 65535, 123456]:
87 if n
>= 1 << 8*w
: continue
88 h0
, donefn0
= makefn(2 + w
+ n
)
89 hashfn(h0
.hashu8(0x00), T
.span(n
)).hashu8(0xff)
90 h1
, donefn1
= makefn(2 + w
+ n
)
91 h1
.hash(T
.prep_lenseq(w
, n
, bigendp
, True))
92 me
.assertEqual(donefn0(), donefn1())
94 ## Check blocks which are too large for the length prefix.
98 me
.assertRaises((ValueError, OverflowError, TypeError),
99 hashfn
, h0
, C
.ByteString
.zero(n
))
101 def check_hashbuffer(me
, makefn
):
102 """Test the various `hash...' methods."""
105 me
.check_hashbuffer_hashn(1, True, makefn
, lambda h
, n
: h
.hashu8(n
))
106 me
.check_hashbuffer_hashn(2, True, makefn
, lambda h
, n
: h
.hashu16(n
))
107 me
.check_hashbuffer_hashn(2, True, makefn
, lambda h
, n
: h
.hashu16b(n
))
108 me
.check_hashbuffer_hashn(2, False, makefn
, lambda h
, n
: h
.hashu16l(n
))
109 if hasattr(makefn(0)[0], "hashu24"):
110 me
.check_hashbuffer_hashn(3, True, makefn
, lambda h
, n
: h
.hashu24(n
))
111 me
.check_hashbuffer_hashn(3, True, makefn
, lambda h
, n
: h
.hashu24b(n
))
112 me
.check_hashbuffer_hashn(3, False, makefn
, lambda h
, n
: h
.hashu24l(n
))
113 me
.check_hashbuffer_hashn(4, True, makefn
, lambda h
, n
: h
.hashu32(n
))
114 me
.check_hashbuffer_hashn(4, True, makefn
, lambda h
, n
: h
.hashu32b(n
))
115 me
.check_hashbuffer_hashn(4, False, makefn
, lambda h
, n
: h
.hashu32l(n
))
116 if hasattr(makefn(0)[0], "hashu64"):
117 me
.check_hashbuffer_hashn(8, True, makefn
, lambda h
, n
: h
.hashu64(n
))
118 me
.check_hashbuffer_hashn(8, True, makefn
, lambda h
, n
: h
.hashu64b(n
))
119 me
.check_hashbuffer_hashn(8, False, makefn
, lambda h
, n
: h
.hashu64l(n
))
122 me
.check_hashbuffer_bufn(1, True, makefn
, lambda h
, x
: h
.hashbuf8(x
))
123 me
.check_hashbuffer_bufn(2, True, makefn
, lambda h
, x
: h
.hashbuf16(x
))
124 me
.check_hashbuffer_bufn(2, True, makefn
, lambda h
, x
: h
.hashbuf16b(x
))
125 me
.check_hashbuffer_bufn(2, False, makefn
, lambda h
, x
: h
.hashbuf16l(x
))
126 if hasattr(makefn(0)[0], "hashbuf24"):
127 me
.check_hashbuffer_bufn(3, True, makefn
, lambda h
, x
: h
.hashbuf24(x
))
128 me
.check_hashbuffer_bufn(3, True, makefn
, lambda h
, x
: h
.hashbuf24b(x
))
129 me
.check_hashbuffer_bufn(3, False, makefn
, lambda h
, x
: h
.hashbuf24l(x
))
130 me
.check_hashbuffer_bufn(4, True, makefn
, lambda h
, x
: h
.hashbuf32(x
))
131 me
.check_hashbuffer_bufn(4, True, makefn
, lambda h
, x
: h
.hashbuf32b(x
))
132 me
.check_hashbuffer_bufn(4, False, makefn
, lambda h
, x
: h
.hashbuf32l(x
))
133 if hasattr(makefn(0)[0], "hashbuf64"):
134 me
.check_hashbuffer_bufn(8, True, makefn
, lambda h
, x
: h
.hashbuf64(x
))
135 me
.check_hashbuffer_bufn(8, True, makefn
, lambda h
, x
: h
.hashbuf64b(x
))
136 me
.check_hashbuffer_bufn(8, False, makefn
, lambda h
, x
: h
.hashbuf64l(x
))
138 ###--------------------------------------------------------------------------
139 class TestKeysize (U
.TestCase
):
143 ## A typical one-byte spec.
145 me
.assertEqual(type(ksz
), C
.KeySZAny
)
146 me
.assertEqual(ksz
.default
, 20)
147 me
.assertEqual(ksz
.min, 0)
148 me
.assertEqual(ksz
.max, 0)
149 for n
in [0, 12, 20, 5000]:
150 me
.assertTrue(ksz
.check(n
))
151 me
.assertEqual(ksz
.best(n
), n
)
152 me
.assertEqual(ksz
.pad(n
), n
)
154 ## A typical two-byte spec. (No published algorithms actually /need/ a
155 ## two-byte key-size spec, but all of the HMAC variants use one anyway.)
156 ksz
= C
.sha256_hmac
.keysz
157 me
.assertEqual(type(ksz
), C
.KeySZAny
)
158 me
.assertEqual(ksz
.default
, 32)
159 me
.assertEqual(ksz
.min, 0)
160 me
.assertEqual(ksz
.max, 0)
161 for n
in [0, 12, 20, 5000]:
162 me
.assertTrue(ksz
.check(n
))
163 me
.assertEqual(ksz
.best(n
), n
)
164 me
.assertEqual(ksz
.pad(n
), n
)
166 ## Check construction.
168 me
.assertEqual(ksz
.default
, 15)
169 me
.assertEqual(ksz
.min, 0)
170 me
.assertEqual(ksz
.max, 0)
171 me
.assertRaises(ValueError, lambda: C
.KeySZAny(-8))
172 me
.assertEqual(C
.KeySZAny(0).default
, 0)
175 ## Note that no published algorithm uses a 16-bit `set' spec.
178 ksz
= C
.salsa20
.keysz
179 me
.assertEqual(type(ksz
), C
.KeySZSet
)
180 me
.assertEqual(ksz
.default
, 32)
181 me
.assertEqual(ksz
.min, 10)
182 me
.assertEqual(ksz
.max, 32)
183 me
.assertEqual(set(ksz
.set), set([10, 16, 32]))
184 for x
, best
, pad
in [(9, None, 10), (10, 10, 10), (11, 10, 16),
185 (15, 10, 16), (16, 16, 16), (17, 16, 32),
186 (31, 16, 32), (32, 32, 32), (33, 32, None)]:
187 if x
== best
== pad
: me
.assertTrue(ksz
.check(x
))
188 else: me
.assertFalse(ksz
.check(x
))
189 if best
is None: me
.assertRaises(ValueError, ksz
.best
, x
)
190 else: me
.assertEqual(ksz
.best(x
), best
)
191 if pad
is None: me
.assertRaises(ValueError, ksz
.pad
, x
)
192 else: me
.assertEqual(ksz
.pad(x
), pad
)
194 ## Check construction.
196 me
.assertEqual(ksz
.default
, 7)
197 me
.assertEqual(set(ksz
.set), set([7]))
198 me
.assertEqual(ksz
.min, 7)
199 me
.assertEqual(ksz
.max, 7)
200 ksz
= C
.KeySZSet(7, [3, 6, 9])
201 me
.assertEqual(ksz
.default
, 7)
202 me
.assertEqual(set(ksz
.set), set([3, 6, 7, 9]))
203 me
.assertEqual(ksz
.min, 3)
204 me
.assertEqual(ksz
.max, 9)
207 ## Note that no published algorithm uses a 16-bit `range' spec, or an
208 ## unbounded `range'.
211 ksz
= C
.rijndael
.keysz
212 me
.assertEqual(type(ksz
), C
.KeySZRange
)
213 me
.assertEqual(ksz
.default
, 32)
214 me
.assertEqual(ksz
.min, 4)
215 me
.assertEqual(ksz
.max, 32)
216 me
.assertEqual(ksz
.mod
, 4)
217 for x
, best
, pad
in [(3, None, 4), (4, 4, 4), (5, 4, 8),
218 (15, 12, 16), (16, 16, 16), (17, 16, 20),
219 (31, 28, 32), (32, 32, 32), (33, 32, None)]:
220 if x
== best
== pad
: me
.assertTrue(ksz
.check(x
))
221 else: me
.assertFalse(ksz
.check(x
))
222 if best
is None: me
.assertRaises(ValueError, ksz
.best
, x
)
223 else: me
.assertEqual(ksz
.best(x
), best
)
224 if pad
is None: me
.assertRaises(ValueError, ksz
.pad
, x
)
225 else: me
.assertEqual(ksz
.pad(x
), pad
)
227 ## Check construction.
228 ksz
= C
.KeySZRange(28, 21, 35, 7)
229 me
.assertEqual(ksz
.default
, 28)
230 me
.assertEqual(ksz
.min, 21)
231 me
.assertEqual(ksz
.max, 35)
232 me
.assertEqual(ksz
.mod
, 7)
233 me
.assertRaises(ValueError, C
.KeySZRange
, 29, 21, 35, 7)
234 me
.assertRaises(ValueError, C
.KeySZRange
, 28, 20, 35, 7)
235 me
.assertRaises(ValueError, C
.KeySZRange
, 28, 21, 34, 7)
236 me
.assertRaises(ValueError, C
.KeySZRange
, 28, -7, 35, 7)
237 me
.assertRaises(ValueError, C
.KeySZRange
, 28, 35, 21, 7)
238 me
.assertRaises(ValueError, C
.KeySZRange
, 35, 21, 28, 7)
239 me
.assertRaises(ValueError, C
.KeySZRange
, 21, 28, 35, 7)
241 def test_conversions(me
):
242 me
.assertEqual(C
.KeySZ
.fromec(256), 128)
243 me
.assertEqual(C
.KeySZ
.fromschnorr(256), 128)
244 me
.assertEqual(round(C
.KeySZ
.fromdl(2958.6875)), 128)
245 me
.assertEqual(round(C
.KeySZ
.fromif(2958.6875)), 128)
246 me
.assertEqual(C
.KeySZ
.toec(128), 256)
247 me
.assertEqual(C
.KeySZ
.toschnorr(128), 256)
248 me
.assertEqual(C
.KeySZ
.todl(128), 2958.6875)
249 me
.assertEqual(C
.KeySZ
.toif(128), 2958.6875)
251 ###--------------------------------------------------------------------------
252 class TestCipher (T
.GenericTestMixin
):
253 """Test basic symmetric ciphers."""
255 def _test_cipher(me
, ccls
):
257 ## Check the class properties.
258 me
.assertEqual(type(ccls
.name
), str)
259 me
.assertTrue(isinstance(ccls
.keysz
, C
.KeySZ
))
260 me
.assertEqual(type(ccls
.blksz
), int)
262 ## Check round-tripping.
263 k
= T
.span(ccls
.keysz
.default
)
264 iv
= T
.span(ccls
.blksz
)
269 except ValueError: can_setiv
= False
273 c0
= enc
.encrypt(m
[0:57])
275 c1
= enc
.encrypt(m
[57:189])
278 except ValueError: can_bdry
= False
282 c2
= enc
.encrypt(m
[189:253])
284 me
.assertEqual(len(c0
) + len(c1
) + len(c2
), len(m
))
285 me
.assertEqual(m0
, m
[0:57])
286 me
.assertEqual(m1
, m
[57:189])
287 me
.assertEqual(m2
, m
[189:253])
289 ## Check the `enczero' and `deczero' methods.
291 me
.assertEqual(dec
.decrypt(c3
), C
.ByteString
.zero(32))
293 me
.assertEqual(enc
.encrypt(m4
), C
.ByteString
.zero(32))
295 ## Check that ciphers which support a `boundary' operation actually
299 if can_setiv
: dec
.setiv(iv
)
300 m01
= dec
.decrypt(c0
+ c1
)
301 me
.assertEqual(m01
, m
[0:189])
303 ## Check that the boundary actually does something.
306 if can_setiv
: dec
.setiv(iv
)
307 m012
= dec
.decrypt(c0
+ c1
+ c2
)
308 me
.assertNotEqual(m012
, m
)
310 ## Check that bad key lengths are rejected.
311 badlen
= bad_key_size(ccls
.keysz
)
312 if badlen
is not None: me
.assertRaises(ValueError, ccls
, T
.span(badlen
))
314 TestCipher
.generate_testcases((name
, C
.gcciphers
[name
]) for name
in
315 ["des-ecb", "rijndael-cbc", "twofish-cfb", "serpent-ofb",
316 "blowfish-counter", "rc4", "seal", "salsa20/8", "shake128-xof"])
318 ###--------------------------------------------------------------------------
319 class BaseTestHash (HashBufferTestMixin
):
320 """Base class for testing hash functions."""
322 def check_hash(me
, hcls
, need_bufsz
= True):
324 Check hash class HCLS.
326 If NEED_BUFSZ is false, then don't insist that HCLS have working `bufsz',
327 `name', or `hashsz' attributes. This test is mostly reused for MACs,
328 which don't have these attributes.
330 ## Check the class properties.
332 me
.assertEqual(type(hcls
.name
), str)
333 me
.assertEqual(type(hcls
.bufsz
), int)
334 me
.assertEqual(type(hcls
.hashsz
), int)
336 ## Set some initial values.
338 h
= hcls().hash(m
).done()
340 ## Check that hash length comes out right.
341 if need_bufsz
: me
.assertEqual(len(h
), hcls
.hashsz
)
343 ## Check that we get the same answer if we split the message up.
344 me
.assertEqual(h
, hcls().hash(m
[0:73]).hash(m
[73:131]).done())
346 ## Check the `check' method.
347 me
.assertTrue(hcls().hash(m
).check(h
))
348 me
.assertFalse(hcls().hash(m
).check(h ^
len(h
)*C
.bytes("aa")))
350 ## Check the menagerie of random hashing methods.
354 me
.check_hashbuffer(mkhash
)
356 class TestHash (BaseTestHash
, T
.GenericTestMixin
):
357 """Test hash functions."""
358 def _test_hash(me
, hcls
): me
.check_hash(hcls
, need_bufsz
= True)
360 TestHash
.generate_testcases((name
, C
.gchashes
[name
]) for name
in
361 ["md5", "sha", "whirlpool", "sha256", "sha512/224", "sha3-384", "shake256",
364 ###--------------------------------------------------------------------------
365 class TestMessageAuthentication (BaseTestHash
, T
.GenericTestMixin
):
366 """Test message authentication codes."""
368 def _test_mac(me
, mcls
):
370 ## Check the MAC properties.
371 me
.assertEqual(type(mcls
.name
), str)
372 me
.assertTrue(isinstance(mcls
.keysz
, C
.KeySZ
))
373 me
.assertEqual(type(mcls
.tagsz
), int)
376 k
= T
.span(mcls
.keysz
.default
)
378 me
.check_hash(key
, need_bufsz
= False)
380 ## Check that bad key lengths are rejected.
381 badlen
= bad_key_size(mcls
.keysz
)
382 if badlen
is not None: me
.assertRaises(ValueError, mcls
, T
.span(badlen
))
384 TestMessageAuthentication
.generate_testcases \
385 ((name
, C
.gcmacs
[name
]) for name
in
386 ["sha-hmac", "rijndael-cmac", "twofish-pmac1", "kmac128"])
388 class TestPoly1305 (HashBufferTestMixin
):
389 """Check the Poly1305 one-time message authentication function."""
391 def test_poly1305(me
):
393 ## Check the MAC properties.
394 me
.assertEqual(C
.poly1305
.name
, "poly1305")
395 me
.assertEqual(type(C
.poly1305
.keysz
), C
.KeySZSet
)
396 me
.assertEqual(C
.poly1305
.keysz
.default
, 16)
397 me
.assertEqual(set(C
.poly1305
.keysz
.set), set([16]))
398 me
.assertEqual(C
.poly1305
.tagsz
, 16)
399 me
.assertEqual(C
.poly1305
.masksz
, 16)
401 ## Set some initial values.
406 t
= key(u
).hash(m
).done()
408 ## Check the key properties.
409 me
.assertEqual(len(t
), 16)
411 ## Check that we get the same answer if we split the message up.
412 me
.assertEqual(t
, key(u
).hash(m
[0:86]).hash(m
[86:149]).done())
414 ## Check the `check' method.
415 me
.assertTrue(key(u
).hash(m
).check(t
))
416 me
.assertFalse(key(u
).hash(m
).check(t ^
16*C
.bytes("cc")))
418 ## Check the menagerie of random hashing methods.
422 me
.check_hashbuffer(mkhash
)
424 ## Check that we can't complete hashing without a mask.
425 me
.assertRaises(ValueError, key().hash(m
).done
)
428 h0
= key().hash(m
[0:96])
429 h1
= key().hash(m
[96:117])
430 me
.assertEqual(t
, key(u
).concat(h0
, h1
).hash(m
[117:149]).done())
432 me
.assertRaises(TypeError, key().concat
, key1().hash(m
[0:96]), h1
)
433 me
.assertRaises(TypeError, key().concat
, h0
, key1().hash(m
[96:117]))
434 me
.assertRaises(ValueError, key().concat
, key().hash(m
[0:93]), h1
)
436 ###--------------------------------------------------------------------------
437 class TestHLatin (U
.TestCase
):
438 """Test the `hsalsa20' and `hchacha20' functions."""
441 kk
= [T
.span(sz
) for sz
in [32]]
445 for fn
in [C
.hsalsa208_prf
, C
.hsalsa2012_prf
, C
.hsalsa20_prf
,
446 C
.hchacha8_prf
, C
.hchacha12_prf
, C
.hchacha20_prf
]:
449 me
.assertEqual(len(h
), 32)
450 me
.assertRaises(ValueError, fn
, bad_k
, n
)
451 me
.assertRaises(ValueError, fn
, k
, bad_n
)
453 ###--------------------------------------------------------------------------
454 class TestKeccak (HashBufferTestMixin
):
455 """Test the Keccak-p[1600, n] sponge function."""
459 ## Make a state and feed some stuff into it.
460 m0
= T
.bin("some initial string")
461 m1
= T
.bin("awesome follow-up string")
463 me
.assertEqual(st0
.nround
, 24)
466 ## Make another step with a different round count.
467 st1
= C
.Keccak1600(23)
469 me
.assertNotEqual(st0
.extract(32), st1
.extract(32))
471 ## Check error conditions.
473 me
.assertRaises(ValueError, st0
.extract
, 201)
475 me
.assertRaises(ValueError, st0
.mix
, T
.span(201))
477 def check_shake(me
, xcls
, c
, done_matches_xof
= True):
479 Test the SHAKE and cSHAKE XOFs.
481 This is also used for testing KMAC, but that sets DONE_MATCHES_XOF false
482 to indicate that the XOF output is range-separated from the fixed-length
483 outputs (unlike the basic SHAKE functions).
486 ## Check the hash attributes.
488 me
.assertEqual(x
.rate
, 200 - c
)
489 me
.assertEqual(x
.buffered
, 0)
490 me
.assertEqual(x
.state
, "absorb")
492 ## Set some initial values.
493 func
= T
.bin("TESTXOF")
494 perso
= T
.bin("catacomb-python test")
496 h0
= xcls().hash(m
).done(193)
497 me
.assertEqual(len(h0
), 193)
498 h1
= xcls(func
= func
, perso
= perso
).hash(m
).done(193)
499 me
.assertEqual(len(h1
), 193)
500 me
.assertNotEqual(h0
, h1
)
502 ## Check input and output in pieces, and the state machine.
503 if done_matches_xof
: h
= h0
504 else: h
= xcls().hash(m
).xof().get(len(h0
))
505 x
= xcls().hash(m
[0:76]).hash(m
[76:167]).xof()
506 me
.assertEqual(h
, x
.get(98) + x
.get(95))
509 x
= xcls().hash(m
).xof()
510 me
.assertEqual(x
.mask(m
), C
.ByteString(m
) ^ C
.ByteString(h
[0:len(m
)]))
512 ## Check the `check' method.
513 me
.assertTrue(xcls().hash(m
).check(h0
))
514 me
.assertFalse(xcls().hash(m
).check(h1
))
516 ## Check the menagerie of random hashing methods.
518 x
= xcls(func
= func
, perso
= perso
)
519 return x
, lambda: x
.done(100 - x
.rate
//2)
520 me
.check_hashbuffer(mkhash
)
522 ## Check the state machine tracking.
523 x
= xcls(); me
.assertEqual(x
.state
, "absorb")
524 x
.hash(m
); me
.assertEqual(x
.state
, "absorb")
526 h
= xx
.done(100 - x
.rate
//2)
527 me
.assertEqual(xx
.state
, "dead")
528 me
.assertRaises(ValueError, xx
.done
, 1)
529 me
.assertRaises(ValueError, xx
.get
, 1)
530 me
.assertEqual(x
.state
, "absorb")
531 me
.assertRaises(ValueError, x
.get
, 1)
532 x
.xof(); me
.assertEqual(x
.state
, "squeeze")
533 me
.assertRaises(ValueError, x
.done
, 1)
535 yy
= x
.copy(); me
.assertEqual(yy
.state
, "squeeze")
537 def test_shake128(me
): me
.check_shake(C
.Shake128
, 32)
538 def test_shake256(me
): me
.check_shake(C
.Shake256
, 64)
540 def check_kmac(me
, mcls
, c
):
542 me
.check_shake(lambda func
= None, perso
= T
.bin(""):
543 mcls(k
, perso
= perso
),
544 c
, done_matches_xof
= False)
546 def test_kmac128(me
): me
.check_kmac(C
.KMAC128
, 32)
547 def test_kmac256(me
): me
.check_kmac(C
.KMAC256
, 64)
549 ###--------------------------------------------------------------------------
550 class TestPRP (T
.GenericTestMixin
):
551 """Test pseudorandom permutations (PRPs)."""
553 def _test_prp(me
, pcls
):
555 ## Check the PRP properties.
556 me
.assertEqual(type(pcls
.name
), str)
557 me
.assertTrue(isinstance(pcls
.keysz
, C
.KeySZ
))
558 me
.assertEqual(type(pcls
.blksz
), int)
560 ## Check round-tripping.
561 k
= T
.span(pcls
.keysz
.default
)
563 m
= T
.span(pcls
.blksz
)
565 me
.assertEqual(len(c
), pcls
.blksz
)
566 me
.assertEqual(m
, key
.decrypt(c
))
568 ## Check that bad key lengths are rejected.
569 badlen
= bad_key_size(pcls
.keysz
)
570 if badlen
is not None: me
.assertRaises(ValueError, pcls
, T
.span(badlen
))
572 ## Check that bad blocks are rejected.
573 badblk
= T
.span(pcls
.blksz
+ 1)
574 me
.assertRaises(ValueError, key
.encrypt
, badblk
)
575 me
.assertRaises(ValueError, key
.decrypt
, badblk
)
577 TestPRP
.generate_testcases((name
, C
.gcprps
[name
]) for name
in
578 ["desx", "blowfish", "rijndael"])
580 ###----- That's all, folks --------------------------------------------------
582 if __name__
== "__main__": U
.main()