PageRenderTime 54ms CodeModel.GetById 14ms app.highlight 35ms RepoModel.GetById 1ms app.codeStats 0ms

/gdata/Crypto/Util/test.py

http://radioappz.googlecode.com/
Python | 453 lines | 383 code | 46 blank | 24 comment | 155 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