/gdata/Crypto/Util/test.py
Python | 453 lines | 383 code | 46 blank | 24 comment | 126 complexity | f69e446cf4498387aaf8c0f10a919d89 MD5 | raw file
1#
2# test.py : Functions used for testing the modules
3#
4# Part of the Python Cryptography Toolkit
5#
6# Distribute and use freely; there are no restrictions on further
7# dissemination and usage except those imposed by the laws of your
8# country of residence. This software is provided "as is" without
9# warranty of fitness for use or suitability for any purpose, express
10# or implied. Use at your own risk or not at all.
11#
12
13__revision__ = "$Id: test.py,v 1.16 2004/08/13 22:24:18 akuchling Exp $"
14
15import binascii
16import string
17import testdata
18
19from Crypto.Cipher import *
20
21def die(string):
22 import sys
23 print '***ERROR: ', string
24# sys.exit(0) # Will default to continuing onward...
25
26def print_timing (size, delta, verbose):
27 if verbose:
28 if delta == 0:
29 print 'Unable to measure time -- elapsed time too small'
30 else:
31 print '%.2f K/sec' % (size/delta)
32
33def exerciseBlockCipher(cipher, verbose):
34 import string, time
35 try:
36 ciph = eval(cipher)
37 except NameError:
38 print cipher, 'module not available'
39 return None
40 print cipher+ ':'
41 str='1' # Build 128K of test data
42 for i in xrange(0, 17):
43 str=str+str
44 if ciph.key_size==0: ciph.key_size=16
45 password = 'password12345678Extra text for password'[0:ciph.key_size]
46 IV = 'Test IV Test IV Test IV Test'[0:ciph.block_size]
47
48 if verbose: print ' ECB mode:',
49 obj=ciph.new(password, ciph.MODE_ECB)
50 if obj.block_size != ciph.block_size:
51 die("Module and cipher object block_size don't match")
52
53 text='1234567812345678'[0:ciph.block_size]
54 c=obj.encrypt(text)
55 if (obj.decrypt(c)!=text): die('Error encrypting "'+text+'"')
56 text='KuchlingKuchling'[0:ciph.block_size]
57 c=obj.encrypt(text)
58 if (obj.decrypt(c)!=text): die('Error encrypting "'+text+'"')
59 text='NotTodayNotEver!'[0:ciph.block_size]
60 c=obj.encrypt(text)
61 if (obj.decrypt(c)!=text): die('Error encrypting "'+text+'"')
62
63 start=time.time()
64 s=obj.encrypt(str)
65 s2=obj.decrypt(s)
66 end=time.time()
67 if (str!=s2):
68 die('Error in resulting plaintext from ECB mode')
69 print_timing(256, end-start, verbose)
70 del obj
71
72 if verbose: print ' CFB mode:',
73 obj1=ciph.new(password, ciph.MODE_CFB, IV)
74 obj2=ciph.new(password, ciph.MODE_CFB, IV)
75 start=time.time()
76 ciphertext=obj1.encrypt(str[0:65536])
77 plaintext=obj2.decrypt(ciphertext)
78 end=time.time()
79 if (plaintext!=str[0:65536]):
80 die('Error in resulting plaintext from CFB mode')
81 print_timing(64, end-start, verbose)
82 del obj1, obj2
83
84 if verbose: print ' CBC mode:',
85 obj1=ciph.new(password, ciph.MODE_CBC, IV)
86 obj2=ciph.new(password, ciph.MODE_CBC, IV)
87 start=time.time()
88 ciphertext=obj1.encrypt(str)
89 plaintext=obj2.decrypt(ciphertext)
90 end=time.time()
91 if (plaintext!=str):
92 die('Error in resulting plaintext from CBC mode')
93 print_timing(256, end-start, verbose)
94 del obj1, obj2
95
96 if verbose: print ' PGP mode:',
97 obj1=ciph.new(password, ciph.MODE_PGP, IV)
98 obj2=ciph.new(password, ciph.MODE_PGP, IV)
99 start=time.time()
100 ciphertext=obj1.encrypt(str)
101 plaintext=obj2.decrypt(ciphertext)
102 end=time.time()
103 if (plaintext!=str):
104 die('Error in resulting plaintext from PGP mode')
105 print_timing(256, end-start, verbose)
106 del obj1, obj2
107
108 if verbose: print ' OFB mode:',
109 obj1=ciph.new(password, ciph.MODE_OFB, IV)
110 obj2=ciph.new(password, ciph.MODE_OFB, IV)
111 start=time.time()
112 ciphertext=obj1.encrypt(str)
113 plaintext=obj2.decrypt(ciphertext)
114 end=time.time()
115 if (plaintext!=str):
116 die('Error in resulting plaintext from OFB mode')
117 print_timing(256, end-start, verbose)
118 del obj1, obj2
119
120 def counter(length=ciph.block_size):
121 return length * 'a'
122
123 if verbose: print ' CTR mode:',
124 obj1=ciph.new(password, ciph.MODE_CTR, counter=counter)
125 obj2=ciph.new(password, ciph.MODE_CTR, counter=counter)
126 start=time.time()
127 ciphertext=obj1.encrypt(str)
128 plaintext=obj2.decrypt(ciphertext)
129 end=time.time()
130 if (plaintext!=str):
131 die('Error in resulting plaintext from CTR mode')
132 print_timing(256, end-start, verbose)
133 del obj1, obj2
134
135 # Test the IV handling
136 if verbose: print ' Testing IV handling'
137 obj1=ciph.new(password, ciph.MODE_CBC, IV)
138 plaintext='Test'*(ciph.block_size/4)*3
139 ciphertext1=obj1.encrypt(plaintext)
140 obj1.IV=IV
141 ciphertext2=obj1.encrypt(plaintext)
142 if ciphertext1!=ciphertext2:
143 die('Error in setting IV')
144
145 # Test keyword arguments
146 obj1=ciph.new(key=password)
147 obj1=ciph.new(password, mode=ciph.MODE_CBC)
148 obj1=ciph.new(mode=ciph.MODE_CBC, key=password)
149 obj1=ciph.new(IV=IV, mode=ciph.MODE_CBC, key=password)
150
151 return ciph
152
153def exerciseStreamCipher(cipher, verbose):
154 import string, time
155 try:
156 ciph = eval(cipher)
157 except (NameError):
158 print cipher, 'module not available'
159 return None
160 print cipher + ':',
161 str='1' # Build 128K of test data
162 for i in xrange(0, 17):
163 str=str+str
164 key_size = ciph.key_size or 16
165 password = 'password12345678Extra text for password'[0:key_size]
166
167 obj1=ciph.new(password)
168 obj2=ciph.new(password)
169 if obj1.block_size != ciph.block_size:
170 die("Module and cipher object block_size don't match")
171 if obj1.key_size != ciph.key_size:
172 die("Module and cipher object key_size don't match")
173
174 text='1234567812345678Python'
175 c=obj1.encrypt(text)
176 if (obj2.decrypt(c)!=text): die('Error encrypting "'+text+'"')
177 text='B1FF I2 A R3A11Y |<00L D00D!!!!!'
178 c=obj1.encrypt(text)
179 if (obj2.decrypt(c)!=text): die('Error encrypting "'+text+'"')
180 text='SpamSpamSpamSpamSpamSpamSpamSpamSpam'
181 c=obj1.encrypt(text)
182 if (obj2.decrypt(c)!=text): die('Error encrypting "'+text+'"')
183
184 start=time.time()
185 s=obj1.encrypt(str)
186 str=obj2.decrypt(s)
187 end=time.time()
188 print_timing(256, end-start, verbose)
189 del obj1, obj2
190
191 return ciph
192
193def TestStreamModules(args=['arc4', 'XOR'], verbose=1):
194 import sys, string
195 args=map(string.lower, args)
196
197 if 'arc4' in args:
198 # Test ARC4 stream cipher
199 arc4=exerciseStreamCipher('ARC4', verbose)
200 if (arc4!=None):
201 for entry in testdata.arc4:
202 key,plain,cipher=entry
203 key=binascii.a2b_hex(key)
204 plain=binascii.a2b_hex(plain)
205 cipher=binascii.a2b_hex(cipher)
206 obj=arc4.new(key)
207 ciphertext=obj.encrypt(plain)
208 if (ciphertext!=cipher):
209 die('ARC4 failed on entry '+`entry`)
210
211 if 'xor' in args:
212 # Test XOR stream cipher
213 XOR=exerciseStreamCipher('XOR', verbose)
214 if (XOR!=None):
215 for entry in testdata.xor:
216 key,plain,cipher=entry
217 key=binascii.a2b_hex(key)
218 plain=binascii.a2b_hex(plain)
219 cipher=binascii.a2b_hex(cipher)
220 obj=XOR.new(key)
221 ciphertext=obj.encrypt(plain)
222 if (ciphertext!=cipher):
223 die('XOR failed on entry '+`entry`)
224
225
226def TestBlockModules(args=['aes', 'arc2', 'des', 'blowfish', 'cast', 'des3',
227 'idea', 'rc5'],
228 verbose=1):
229 import string
230 args=map(string.lower, args)
231 if 'aes' in args:
232 ciph=exerciseBlockCipher('AES', verbose) # AES
233 if (ciph!=None):
234 if verbose: print ' Verifying against test suite...'
235 for entry in testdata.aes:
236 key,plain,cipher=entry
237 key=binascii.a2b_hex(key)
238 plain=binascii.a2b_hex(plain)
239 cipher=binascii.a2b_hex(cipher)
240 obj=ciph.new(key, ciph.MODE_ECB)
241 ciphertext=obj.encrypt(plain)
242 if (ciphertext!=cipher):
243 die('AES failed on entry '+`entry`)
244 for i in ciphertext:
245 if verbose: print hex(ord(i)),
246 if verbose: print
247
248 for entry in testdata.aes_modes:
249 mode, key, plain, cipher, kw = entry
250 key=binascii.a2b_hex(key)
251 plain=binascii.a2b_hex(plain)
252 cipher=binascii.a2b_hex(cipher)
253 obj=ciph.new(key, mode, **kw)
254 obj2=ciph.new(key, mode, **kw)
255 ciphertext=obj.encrypt(plain)
256 if (ciphertext!=cipher):
257 die('AES encrypt failed on entry '+`entry`)
258 for i in ciphertext:
259 if verbose: print hex(ord(i)),
260 if verbose: print
261
262 plain2=obj2.decrypt(ciphertext)
263 if plain2!=plain:
264 die('AES decrypt failed on entry '+`entry`)
265 for i in plain2:
266 if verbose: print hex(ord(i)),
267 if verbose: print
268
269
270 if 'arc2' in args:
271 ciph=exerciseBlockCipher('ARC2', verbose) # Alleged RC2
272 if (ciph!=None):
273 if verbose: print ' Verifying against test suite...'
274 for entry in testdata.arc2:
275 key,plain,cipher=entry
276 key=binascii.a2b_hex(key)
277 plain=binascii.a2b_hex(plain)
278 cipher=binascii.a2b_hex(cipher)
279 obj=ciph.new(key, ciph.MODE_ECB)
280 ciphertext=obj.encrypt(plain)
281 if (ciphertext!=cipher):
282 die('ARC2 failed on entry '+`entry`)
283 for i in ciphertext:
284 if verbose: print hex(ord(i)),
285 print
286
287 if 'blowfish' in args:
288 ciph=exerciseBlockCipher('Blowfish',verbose)# Bruce Schneier's Blowfish cipher
289 if (ciph!=None):
290 if verbose: print ' Verifying against test suite...'
291 for entry in testdata.blowfish:
292 key,plain,cipher=entry
293 key=binascii.a2b_hex(key)
294 plain=binascii.a2b_hex(plain)
295 cipher=binascii.a2b_hex(cipher)
296 obj=ciph.new(key, ciph.MODE_ECB)
297 ciphertext=obj.encrypt(plain)
298 if (ciphertext!=cipher):
299 die('Blowfish failed on entry '+`entry`)
300 for i in ciphertext:
301 if verbose: print hex(ord(i)),
302 if verbose: print
303
304 if 'cast' in args:
305 ciph=exerciseBlockCipher('CAST', verbose) # CAST-128
306 if (ciph!=None):
307 if verbose: print ' Verifying against test suite...'
308 for entry in testdata.cast:
309 key,plain,cipher=entry
310 key=binascii.a2b_hex(key)
311 plain=binascii.a2b_hex(plain)
312 cipher=binascii.a2b_hex(cipher)
313 obj=ciph.new(key, ciph.MODE_ECB)
314 ciphertext=obj.encrypt(plain)
315 if (ciphertext!=cipher):
316 die('CAST failed on entry '+`entry`)
317 for i in ciphertext:
318 if verbose: print hex(ord(i)),
319 if verbose: print
320
321 if 0:
322 # The full-maintenance test; it requires 4 million encryptions,
323 # and correspondingly is quite time-consuming. I've disabled
324 # it; it's faster to compile block/cast.c with -DTEST and run
325 # the resulting program.
326 a = b = '\x01\x23\x45\x67\x12\x34\x56\x78\x23\x45\x67\x89\x34\x56\x78\x9A'
327
328 for i in range(0, 1000000):
329 obj = cast.new(b, cast.MODE_ECB)
330 a = obj.encrypt(a[:8]) + obj.encrypt(a[-8:])
331 obj = cast.new(a, cast.MODE_ECB)
332 b = obj.encrypt(b[:8]) + obj.encrypt(b[-8:])
333
334 if a!="\xEE\xA9\xD0\xA2\x49\xFD\x3B\xA6\xB3\x43\x6F\xB8\x9D\x6D\xCA\x92":
335 if verbose: print 'CAST test failed: value of "a" doesn\'t match'
336 if b!="\xB2\xC9\x5E\xB0\x0C\x31\xAD\x71\x80\xAC\x05\xB8\xE8\x3D\x69\x6E":
337 if verbose: print 'CAST test failed: value of "b" doesn\'t match'
338
339 if 'des' in args:
340 # Test/benchmark DES block cipher
341 des=exerciseBlockCipher('DES', verbose)
342 if (des!=None):
343 # Various tests taken from the DES library packaged with Kerberos V4
344 obj=des.new(binascii.a2b_hex('0123456789abcdef'), des.MODE_ECB)
345 s=obj.encrypt('Now is t')
346 if (s!=binascii.a2b_hex('3fa40e8a984d4815')):
347 die('DES fails test 1')
348 obj=des.new(binascii.a2b_hex('08192a3b4c5d6e7f'), des.MODE_ECB)
349 s=obj.encrypt('\000\000\000\000\000\000\000\000')
350 if (s!=binascii.a2b_hex('25ddac3e96176467')):
351 die('DES fails test 2')
352 obj=des.new(binascii.a2b_hex('0123456789abcdef'), des.MODE_CBC,
353 binascii.a2b_hex('1234567890abcdef'))
354 s=obj.encrypt("Now is the time for all ")
355 if (s!=binascii.a2b_hex('e5c7cdde872bf27c43e934008c389c0f683788499a7c05f6')):
356 die('DES fails test 3')
357 obj=des.new(binascii.a2b_hex('0123456789abcdef'), des.MODE_CBC,
358 binascii.a2b_hex('fedcba9876543210'))
359 s=obj.encrypt("7654321 Now is the time for \000\000\000\000")
360 if (s!=binascii.a2b_hex("ccd173ffab2039f4acd8aefddfd8a1eb468e91157888ba681d269397f7fe62b4")):
361 die('DES fails test 4')
362 del obj,s
363
364 # R. Rivest's test: see http://theory.lcs.mit.edu/~rivest/destest.txt
365 x=binascii.a2b_hex('9474B8E8C73BCA7D')
366 for i in range(0, 16):
367 obj=des.new(x, des.MODE_ECB)
368 if (i & 1): x=obj.decrypt(x)
369 else: x=obj.encrypt(x)
370 if x!=binascii.a2b_hex('1B1A2DDB4C642438'):
371 die("DES fails Rivest's test")
372
373 if verbose: print ' Verifying against test suite...'
374 for entry in testdata.des:
375 key,plain,cipher=entry
376 key=binascii.a2b_hex(key)
377 plain=binascii.a2b_hex(plain)
378 cipher=binascii.a2b_hex(cipher)
379 obj=des.new(key, des.MODE_ECB)
380 ciphertext=obj.encrypt(plain)
381 if (ciphertext!=cipher):
382 die('DES failed on entry '+`entry`)
383 for entry in testdata.des_cbc:
384 key, iv, plain, cipher=entry
385 key, iv, cipher=binascii.a2b_hex(key),binascii.a2b_hex(iv),binascii.a2b_hex(cipher)
386 obj1=des.new(key, des.MODE_CBC, iv)
387 obj2=des.new(key, des.MODE_CBC, iv)
388 ciphertext=obj1.encrypt(plain)
389 if (ciphertext!=cipher):
390 die('DES CBC mode failed on entry '+`entry`)
391
392 if 'des3' in args:
393 ciph=exerciseBlockCipher('DES3', verbose) # Triple DES
394 if (ciph!=None):
395 if verbose: print ' Verifying against test suite...'
396 for entry in testdata.des3:
397 key,plain,cipher=entry
398 key=binascii.a2b_hex(key)
399 plain=binascii.a2b_hex(plain)
400 cipher=binascii.a2b_hex(cipher)
401 obj=ciph.new(key, ciph.MODE_ECB)
402 ciphertext=obj.encrypt(plain)
403 if (ciphertext!=cipher):
404 die('DES3 failed on entry '+`entry`)
405 for i in ciphertext:
406 if verbose: print hex(ord(i)),
407 if verbose: print
408 for entry in testdata.des3_cbc:
409 key, iv, plain, cipher=entry
410 key, iv, cipher=binascii.a2b_hex(key),binascii.a2b_hex(iv),binascii.a2b_hex(cipher)
411 obj1=ciph.new(key, ciph.MODE_CBC, iv)
412 obj2=ciph.new(key, ciph.MODE_CBC, iv)
413 ciphertext=obj1.encrypt(plain)
414 if (ciphertext!=cipher):
415 die('DES3 CBC mode failed on entry '+`entry`)
416
417 if 'idea' in args:
418 ciph=exerciseBlockCipher('IDEA', verbose) # IDEA block cipher
419 if (ciph!=None):
420 if verbose: print ' Verifying against test suite...'
421 for entry in testdata.idea:
422 key,plain,cipher=entry
423 key=binascii.a2b_hex(key)
424 plain=binascii.a2b_hex(plain)
425 cipher=binascii.a2b_hex(cipher)
426 obj=ciph.new(key, ciph.MODE_ECB)
427 ciphertext=obj.encrypt(plain)
428 if (ciphertext!=cipher):
429 die('IDEA failed on entry '+`entry`)
430
431 if 'rc5' in args:
432 # Ronald Rivest's RC5 algorithm
433 ciph=exerciseBlockCipher('RC5', verbose)
434 if (ciph!=None):
435 if verbose: print ' Verifying against test suite...'
436 for entry in testdata.rc5:
437 key,plain,cipher=entry
438 key=binascii.a2b_hex(key)
439 plain=binascii.a2b_hex(plain)
440 cipher=binascii.a2b_hex(cipher)
441 obj=ciph.new(key[4:], ciph.MODE_ECB,
442 version =ord(key[0]),
443 word_size=ord(key[1]),
444 rounds =ord(key[2]) )
445 ciphertext=obj.encrypt(plain)
446 if (ciphertext!=cipher):
447 die('RC5 failed on entry '+`entry`)
448 for i in ciphertext:
449 if verbose: print hex(ord(i)),
450 if verbose: print
451
452
453