<s> __revision__ = "<STR_LIT>" <EOL> import sys <EOL> if sys . version_info [ <NUM_LIT:0> ] is <NUM_LIT:2> and sys . version_info [ <NUM_LIT:1> ] is <NUM_LIT:1> : <EOL> from Crypto . Util . py21compat import * <EOL> from Crypto . Util . py3compat import * <EOL> import struct <EOL> from Crypto . Util . number import ceil_shift , exact_log2 , exact_div <EOL> from Crypto . Util import Counter <EOL> from Crypto . Cipher import AES <EOL> import SHAd256 <EOL> class AESGenerator ( object ) : <EOL> """<STR_LIT>""" <EOL> block_size = AES . block_size <EOL> key_size = <NUM_LIT:32> <EOL> max_blocks_per_request = <NUM_LIT:2> ** <NUM_LIT:16> <EOL> _four_kiblocks_of_zeros = b ( "<STR_LIT>" ) * block_size * <NUM_LIT> <EOL> def __init__ ( self ) : <EOL> self . counter = Counter . new ( nbits = self . block_size * <NUM_LIT:8> , initial_value = <NUM_LIT:0> , little_endian = True ) <EOL> self . key = None <EOL> self . block_size_shift = exact_log2 ( self . block_size ) <EOL> assert ( <NUM_LIT:1> << self . block_size_shift ) == self . block_size <EOL> self . blocks_per_key = exact_div ( self . key_size , self . block_size ) <EOL> assert self . key_size == self . blocks_per_key * self . block_size <EOL> self . max_bytes_per_request = self . max_blocks_per_request * self . block_size <EOL> def reseed ( self , seed ) : <EOL> if self . key is None : <EOL> self . key = b ( "<STR_LIT>" ) * self . key_size <EOL> self . _set_key ( SHAd256 . new ( self . key + seed ) . digest ( ) ) <EOL> self . counter ( ) <EOL> assert len ( self . key ) == self . key_size <EOL> def pseudo_random_data ( self , bytes ) : <EOL> assert bytes >= <NUM_LIT:0> <EOL> num_full_blocks = bytes >> <NUM_LIT:20> <EOL> remainder = bytes & ( ( <NUM_LIT:1> << <NUM_LIT:20> ) - <NUM_LIT:1> ) <EOL> retval = [ ] <EOL> for i in xrange ( num_full_blocks ) : <EOL> retval . append ( self . _pseudo_random_data ( <NUM_LIT:1> << <NUM_LIT:20> ) ) <EOL> retval . append ( self . _pseudo_random_data ( remainder ) ) <EOL> return b ( "<STR_LIT>" ) . join ( retval ) <EOL> def _set_key ( self , key ) : <EOL> self . key = key <EOL> self . _cipher = AES . new ( key , AES . MODE_CTR , counter = self . counter ) <EOL> def _pseudo_random_data ( self , bytes ) : <EOL> if not ( <NUM_LIT:0> <= bytes <= self . max_bytes_per_request ) : <EOL> raise AssertionError ( "<STR_LIT>" ) <EOL> num_blocks = ceil_shift ( bytes , self . block_size_shift ) <EOL> retval = self . _generate_blocks ( num_blocks ) [ : bytes ] <EOL> self . _set_key ( self . _generate_blocks ( self . blocks_per_key ) ) <EOL> assert len ( retval ) == bytes <EOL> assert len ( self . key ) == self . key_size <EOL> return retval <EOL> def _generate_blocks ( self , num_blocks ) : <EOL> if self . key is None : <EOL> raise AssertionError ( "<STR_LIT>" ) <EOL> assert <NUM_LIT:0> <= num_blocks <= self . max_blocks_per_request <EOL> retval = [ ] <EOL> for i in xrange ( num_blocks >> <NUM_LIT:12> ) : <EOL> retval . append ( self . _cipher . encrypt ( self . _four_kiblocks_of_zeros ) ) <EOL> remaining_bytes = ( num_blocks & <NUM_LIT> ) << self . block_size_shift <EOL> retval . append ( self . _cipher . encrypt ( self . _four_kiblocks_of_zeros [ : remaining_bytes ] ) ) <EOL> return b ( "<STR_LIT>" ) . join ( retval ) </s>
