/gdata/Crypto/Util/test.py
Python | 453 lines | 383 code | 46 blank | 24 comment | 126 complexity | f69e446cf4498387aaf8c0f10a919d89 MD5 | raw file
- #
- # test.py : Functions used for testing the modules
- #
- # Part of the Python Cryptography Toolkit
- #
- # Distribute and use freely; there are no restrictions on further
- # dissemination and usage except those imposed by the laws of your
- # country of residence. This software is provided "as is" without
- # warranty of fitness for use or suitability for any purpose, express
- # or implied. Use at your own risk or not at all.
- #
- __revision__ = "$Id: test.py,v 1.16 2004/08/13 22:24:18 akuchling Exp $"
- import binascii
- import string
- import testdata
- from Crypto.Cipher import *
- def die(string):
- import sys
- print '***ERROR: ', string
- # sys.exit(0) # Will default to continuing onward...
- def print_timing (size, delta, verbose):
- if verbose:
- if delta == 0:
- print 'Unable to measure time -- elapsed time too small'
- else:
- print '%.2f K/sec' % (size/delta)
-
- def exerciseBlockCipher(cipher, verbose):
- import string, time
- try:
- ciph = eval(cipher)
- except NameError:
- print cipher, 'module not available'
- return None
- print cipher+ ':'
- str='1' # Build 128K of test data
- for i in xrange(0, 17):
- str=str+str
- if ciph.key_size==0: ciph.key_size=16
- password = 'password12345678Extra text for password'[0:ciph.key_size]
- IV = 'Test IV Test IV Test IV Test'[0:ciph.block_size]
- if verbose: print ' ECB mode:',
- obj=ciph.new(password, ciph.MODE_ECB)
- if obj.block_size != ciph.block_size:
- die("Module and cipher object block_size don't match")
- text='1234567812345678'[0:ciph.block_size]
- c=obj.encrypt(text)
- if (obj.decrypt(c)!=text): die('Error encrypting "'+text+'"')
- text='KuchlingKuchling'[0:ciph.block_size]
- c=obj.encrypt(text)
- if (obj.decrypt(c)!=text): die('Error encrypting "'+text+'"')
- text='NotTodayNotEver!'[0:ciph.block_size]
- c=obj.encrypt(text)
- if (obj.decrypt(c)!=text): die('Error encrypting "'+text+'"')
- start=time.time()
- s=obj.encrypt(str)
- s2=obj.decrypt(s)
- end=time.time()
- if (str!=s2):
- die('Error in resulting plaintext from ECB mode')
- print_timing(256, end-start, verbose)
- del obj
- if verbose: print ' CFB mode:',
- obj1=ciph.new(password, ciph.MODE_CFB, IV)
- obj2=ciph.new(password, ciph.MODE_CFB, IV)
- start=time.time()
- ciphertext=obj1.encrypt(str[0:65536])
- plaintext=obj2.decrypt(ciphertext)
- end=time.time()
- if (plaintext!=str[0:65536]):
- die('Error in resulting plaintext from CFB mode')
- print_timing(64, end-start, verbose)
- del obj1, obj2
- if verbose: print ' CBC mode:',
- obj1=ciph.new(password, ciph.MODE_CBC, IV)
- obj2=ciph.new(password, ciph.MODE_CBC, IV)
- start=time.time()
- ciphertext=obj1.encrypt(str)
- plaintext=obj2.decrypt(ciphertext)
- end=time.time()
- if (plaintext!=str):
- die('Error in resulting plaintext from CBC mode')
- print_timing(256, end-start, verbose)
- del obj1, obj2
- if verbose: print ' PGP mode:',
- obj1=ciph.new(password, ciph.MODE_PGP, IV)
- obj2=ciph.new(password, ciph.MODE_PGP, IV)
- start=time.time()
- ciphertext=obj1.encrypt(str)
- plaintext=obj2.decrypt(ciphertext)
- end=time.time()
- if (plaintext!=str):
- die('Error in resulting plaintext from PGP mode')
- print_timing(256, end-start, verbose)
- del obj1, obj2
- if verbose: print ' OFB mode:',
- obj1=ciph.new(password, ciph.MODE_OFB, IV)
- obj2=ciph.new(password, ciph.MODE_OFB, IV)
- start=time.time()
- ciphertext=obj1.encrypt(str)
- plaintext=obj2.decrypt(ciphertext)
- end=time.time()
- if (plaintext!=str):
- die('Error in resulting plaintext from OFB mode')
- print_timing(256, end-start, verbose)
- del obj1, obj2
- def counter(length=ciph.block_size):
- return length * 'a'
- if verbose: print ' CTR mode:',
- obj1=ciph.new(password, ciph.MODE_CTR, counter=counter)
- obj2=ciph.new(password, ciph.MODE_CTR, counter=counter)
- start=time.time()
- ciphertext=obj1.encrypt(str)
- plaintext=obj2.decrypt(ciphertext)
- end=time.time()
- if (plaintext!=str):
- die('Error in resulting plaintext from CTR mode')
- print_timing(256, end-start, verbose)
- del obj1, obj2
- # Test the IV handling
- if verbose: print ' Testing IV handling'
- obj1=ciph.new(password, ciph.MODE_CBC, IV)
- plaintext='Test'*(ciph.block_size/4)*3
- ciphertext1=obj1.encrypt(plaintext)
- obj1.IV=IV
- ciphertext2=obj1.encrypt(plaintext)
- if ciphertext1!=ciphertext2:
- die('Error in setting IV')
- # Test keyword arguments
- obj1=ciph.new(key=password)
- obj1=ciph.new(password, mode=ciph.MODE_CBC)
- obj1=ciph.new(mode=ciph.MODE_CBC, key=password)
- obj1=ciph.new(IV=IV, mode=ciph.MODE_CBC, key=password)
- return ciph
- def exerciseStreamCipher(cipher, verbose):
- import string, time
- try:
- ciph = eval(cipher)
- except (NameError):
- print cipher, 'module not available'
- return None
- print cipher + ':',
- str='1' # Build 128K of test data
- for i in xrange(0, 17):
- str=str+str
- key_size = ciph.key_size or 16
- password = 'password12345678Extra text for password'[0:key_size]
- obj1=ciph.new(password)
- obj2=ciph.new(password)
- if obj1.block_size != ciph.block_size:
- die("Module and cipher object block_size don't match")
- if obj1.key_size != ciph.key_size:
- die("Module and cipher object key_size don't match")
- text='1234567812345678Python'
- c=obj1.encrypt(text)
- if (obj2.decrypt(c)!=text): die('Error encrypting "'+text+'"')
- text='B1FF I2 A R3A11Y |<00L D00D!!!!!'
- c=obj1.encrypt(text)
- if (obj2.decrypt(c)!=text): die('Error encrypting "'+text+'"')
- text='SpamSpamSpamSpamSpamSpamSpamSpamSpam'
- c=obj1.encrypt(text)
- if (obj2.decrypt(c)!=text): die('Error encrypting "'+text+'"')
- start=time.time()
- s=obj1.encrypt(str)
- str=obj2.decrypt(s)
- end=time.time()
- print_timing(256, end-start, verbose)
- del obj1, obj2
- return ciph
- def TestStreamModules(args=['arc4', 'XOR'], verbose=1):
- import sys, string
- args=map(string.lower, args)
- if 'arc4' in args:
- # Test ARC4 stream cipher
- arc4=exerciseStreamCipher('ARC4', verbose)
- if (arc4!=None):
- for entry in testdata.arc4:
- key,plain,cipher=entry
- key=binascii.a2b_hex(key)
- plain=binascii.a2b_hex(plain)
- cipher=binascii.a2b_hex(cipher)
- obj=arc4.new(key)
- ciphertext=obj.encrypt(plain)
- if (ciphertext!=cipher):
- die('ARC4 failed on entry '+`entry`)
- if 'xor' in args:
- # Test XOR stream cipher
- XOR=exerciseStreamCipher('XOR', verbose)
- if (XOR!=None):
- for entry in testdata.xor:
- key,plain,cipher=entry
- key=binascii.a2b_hex(key)
- plain=binascii.a2b_hex(plain)
- cipher=binascii.a2b_hex(cipher)
- obj=XOR.new(key)
- ciphertext=obj.encrypt(plain)
- if (ciphertext!=cipher):
- die('XOR failed on entry '+`entry`)
- def TestBlockModules(args=['aes', 'arc2', 'des', 'blowfish', 'cast', 'des3',
- 'idea', 'rc5'],
- verbose=1):
- import string
- args=map(string.lower, args)
- if 'aes' in args:
- ciph=exerciseBlockCipher('AES', verbose) # AES
- if (ciph!=None):
- if verbose: print ' Verifying against test suite...'
- for entry in testdata.aes:
- key,plain,cipher=entry
- key=binascii.a2b_hex(key)
- plain=binascii.a2b_hex(plain)
- cipher=binascii.a2b_hex(cipher)
- obj=ciph.new(key, ciph.MODE_ECB)
- ciphertext=obj.encrypt(plain)
- if (ciphertext!=cipher):
- die('AES failed on entry '+`entry`)
- for i in ciphertext:
- if verbose: print hex(ord(i)),
- if verbose: print
- for entry in testdata.aes_modes:
- mode, key, plain, cipher, kw = entry
- key=binascii.a2b_hex(key)
- plain=binascii.a2b_hex(plain)
- cipher=binascii.a2b_hex(cipher)
- obj=ciph.new(key, mode, **kw)
- obj2=ciph.new(key, mode, **kw)
- ciphertext=obj.encrypt(plain)
- if (ciphertext!=cipher):
- die('AES encrypt failed on entry '+`entry`)
- for i in ciphertext:
- if verbose: print hex(ord(i)),
- if verbose: print
- plain2=obj2.decrypt(ciphertext)
- if plain2!=plain:
- die('AES decrypt failed on entry '+`entry`)
- for i in plain2:
- if verbose: print hex(ord(i)),
- if verbose: print
- if 'arc2' in args:
- ciph=exerciseBlockCipher('ARC2', verbose) # Alleged RC2
- if (ciph!=None):
- if verbose: print ' Verifying against test suite...'
- for entry in testdata.arc2:
- key,plain,cipher=entry
- key=binascii.a2b_hex(key)
- plain=binascii.a2b_hex(plain)
- cipher=binascii.a2b_hex(cipher)
- obj=ciph.new(key, ciph.MODE_ECB)
- ciphertext=obj.encrypt(plain)
- if (ciphertext!=cipher):
- die('ARC2 failed on entry '+`entry`)
- for i in ciphertext:
- if verbose: print hex(ord(i)),
- print
- if 'blowfish' in args:
- ciph=exerciseBlockCipher('Blowfish',verbose)# Bruce Schneier's Blowfish cipher
- if (ciph!=None):
- if verbose: print ' Verifying against test suite...'
- for entry in testdata.blowfish:
- key,plain,cipher=entry
- key=binascii.a2b_hex(key)
- plain=binascii.a2b_hex(plain)
- cipher=binascii.a2b_hex(cipher)
- obj=ciph.new(key, ciph.MODE_ECB)
- ciphertext=obj.encrypt(plain)
- if (ciphertext!=cipher):
- die('Blowfish failed on entry '+`entry`)
- for i in ciphertext:
- if verbose: print hex(ord(i)),
- if verbose: print
- if 'cast' in args:
- ciph=exerciseBlockCipher('CAST', verbose) # CAST-128
- if (ciph!=None):
- if verbose: print ' Verifying against test suite...'
- for entry in testdata.cast:
- key,plain,cipher=entry
- key=binascii.a2b_hex(key)
- plain=binascii.a2b_hex(plain)
- cipher=binascii.a2b_hex(cipher)
- obj=ciph.new(key, ciph.MODE_ECB)
- ciphertext=obj.encrypt(plain)
- if (ciphertext!=cipher):
- die('CAST failed on entry '+`entry`)
- for i in ciphertext:
- if verbose: print hex(ord(i)),
- if verbose: print
- if 0:
- # The full-maintenance test; it requires 4 million encryptions,
- # and correspondingly is quite time-consuming. I've disabled
- # it; it's faster to compile block/cast.c with -DTEST and run
- # the resulting program.
- a = b = '\x01\x23\x45\x67\x12\x34\x56\x78\x23\x45\x67\x89\x34\x56\x78\x9A'
- for i in range(0, 1000000):
- obj = cast.new(b, cast.MODE_ECB)
- a = obj.encrypt(a[:8]) + obj.encrypt(a[-8:])
- obj = cast.new(a, cast.MODE_ECB)
- b = obj.encrypt(b[:8]) + obj.encrypt(b[-8:])
- if a!="\xEE\xA9\xD0\xA2\x49\xFD\x3B\xA6\xB3\x43\x6F\xB8\x9D\x6D\xCA\x92":
- if verbose: print 'CAST test failed: value of "a" doesn\'t match'
- if b!="\xB2\xC9\x5E\xB0\x0C\x31\xAD\x71\x80\xAC\x05\xB8\xE8\x3D\x69\x6E":
- if verbose: print 'CAST test failed: value of "b" doesn\'t match'
- if 'des' in args:
- # Test/benchmark DES block cipher
- des=exerciseBlockCipher('DES', verbose)
- if (des!=None):
- # Various tests taken from the DES library packaged with Kerberos V4
- obj=des.new(binascii.a2b_hex('0123456789abcdef'), des.MODE_ECB)
- s=obj.encrypt('Now is t')
- if (s!=binascii.a2b_hex('3fa40e8a984d4815')):
- die('DES fails test 1')
- obj=des.new(binascii.a2b_hex('08192a3b4c5d6e7f'), des.MODE_ECB)
- s=obj.encrypt('\000\000\000\000\000\000\000\000')
- if (s!=binascii.a2b_hex('25ddac3e96176467')):
- die('DES fails test 2')
- obj=des.new(binascii.a2b_hex('0123456789abcdef'), des.MODE_CBC,
- binascii.a2b_hex('1234567890abcdef'))
- s=obj.encrypt("Now is the time for all ")
- if (s!=binascii.a2b_hex('e5c7cdde872bf27c43e934008c389c0f683788499a7c05f6')):
- die('DES fails test 3')
- obj=des.new(binascii.a2b_hex('0123456789abcdef'), des.MODE_CBC,
- binascii.a2b_hex('fedcba9876543210'))
- s=obj.encrypt("7654321 Now is the time for \000\000\000\000")
- if (s!=binascii.a2b_hex("ccd173ffab2039f4acd8aefddfd8a1eb468e91157888ba681d269397f7fe62b4")):
- die('DES fails test 4')
- del obj,s
- # R. Rivest's test: see http://theory.lcs.mit.edu/~rivest/destest.txt
- x=binascii.a2b_hex('9474B8E8C73BCA7D')
- for i in range(0, 16):
- obj=des.new(x, des.MODE_ECB)
- if (i & 1): x=obj.decrypt(x)
- else: x=obj.encrypt(x)
- if x!=binascii.a2b_hex('1B1A2DDB4C642438'):
- die("DES fails Rivest's test")
- if verbose: print ' Verifying against test suite...'
- for entry in testdata.des:
- key,plain,cipher=entry
- key=binascii.a2b_hex(key)
- plain=binascii.a2b_hex(plain)
- cipher=binascii.a2b_hex(cipher)
- obj=des.new(key, des.MODE_ECB)
- ciphertext=obj.encrypt(plain)
- if (ciphertext!=cipher):
- die('DES failed on entry '+`entry`)
- for entry in testdata.des_cbc:
- key, iv, plain, cipher=entry
- key, iv, cipher=binascii.a2b_hex(key),binascii.a2b_hex(iv),binascii.a2b_hex(cipher)
- obj1=des.new(key, des.MODE_CBC, iv)
- obj2=des.new(key, des.MODE_CBC, iv)
- ciphertext=obj1.encrypt(plain)
- if (ciphertext!=cipher):
- die('DES CBC mode failed on entry '+`entry`)
- if 'des3' in args:
- ciph=exerciseBlockCipher('DES3', verbose) # Triple DES
- if (ciph!=None):
- if verbose: print ' Verifying against test suite...'
- for entry in testdata.des3:
- key,plain,cipher=entry
- key=binascii.a2b_hex(key)
- plain=binascii.a2b_hex(plain)
- cipher=binascii.a2b_hex(cipher)
- obj=ciph.new(key, ciph.MODE_ECB)
- ciphertext=obj.encrypt(plain)
- if (ciphertext!=cipher):
- die('DES3 failed on entry '+`entry`)
- for i in ciphertext:
- if verbose: print hex(ord(i)),
- if verbose: print
- for entry in testdata.des3_cbc:
- key, iv, plain, cipher=entry
- key, iv, cipher=binascii.a2b_hex(key),binascii.a2b_hex(iv),binascii.a2b_hex(cipher)
- obj1=ciph.new(key, ciph.MODE_CBC, iv)
- obj2=ciph.new(key, ciph.MODE_CBC, iv)
- ciphertext=obj1.encrypt(plain)
- if (ciphertext!=cipher):
- die('DES3 CBC mode failed on entry '+`entry`)
- if 'idea' in args:
- ciph=exerciseBlockCipher('IDEA', verbose) # IDEA block cipher
- if (ciph!=None):
- if verbose: print ' Verifying against test suite...'
- for entry in testdata.idea:
- key,plain,cipher=entry
- key=binascii.a2b_hex(key)
- plain=binascii.a2b_hex(plain)
- cipher=binascii.a2b_hex(cipher)
- obj=ciph.new(key, ciph.MODE_ECB)
- ciphertext=obj.encrypt(plain)
- if (ciphertext!=cipher):
- die('IDEA failed on entry '+`entry`)
- if 'rc5' in args:
- # Ronald Rivest's RC5 algorithm
- ciph=exerciseBlockCipher('RC5', verbose)
- if (ciph!=None):
- if verbose: print ' Verifying against test suite...'
- for entry in testdata.rc5:
- key,plain,cipher=entry
- key=binascii.a2b_hex(key)
- plain=binascii.a2b_hex(plain)
- cipher=binascii.a2b_hex(cipher)
- obj=ciph.new(key[4:], ciph.MODE_ECB,
- version =ord(key[0]),
- word_size=ord(key[1]),
- rounds =ord(key[2]) )
- ciphertext=obj.encrypt(plain)
- if (ciphertext!=cipher):
- die('RC5 failed on entry '+`entry`)
- for i in ciphertext:
- if verbose: print hex(ord(i)),
- if verbose: print