[2] | 1 | import os, os.path, logging |
---|
| 2 | |
---|
| 3 | import pkg_resources |
---|
| 4 | pkg_resources.require( "pycrypto" ) |
---|
| 5 | |
---|
| 6 | from Crypto.Cipher import Blowfish |
---|
| 7 | from Crypto.Util.randpool import RandomPool |
---|
| 8 | from Crypto.Util import number |
---|
| 9 | |
---|
| 10 | log = logging.getLogger( __name__ ) |
---|
| 11 | |
---|
| 12 | if os.path.exists( "/dev/urandom" ): |
---|
| 13 | # We have urandom, use it as the source of random data |
---|
| 14 | random_fd = os.open( "/dev/urandom", os.O_RDONLY ) |
---|
| 15 | def get_random_bytes( nbytes ): |
---|
| 16 | value = os.read( random_fd, nbytes ) |
---|
| 17 | # Normally we should get as much as we need |
---|
| 18 | if len( value ) == nbytes: |
---|
| 19 | return value.encode( "hex" ) |
---|
| 20 | # If we don't, keep reading (this is slow and should never happen) |
---|
| 21 | while len( value ) < nbytes: |
---|
| 22 | value += os.read( random_fd, nbytes - len( value ) ) |
---|
| 23 | return value.encode( "hex" ) |
---|
| 24 | else: |
---|
| 25 | def get_random_bytes( nbytes ): |
---|
| 26 | nbits = nbytes * 8 |
---|
| 27 | random_pool = RandomPool( 1064 ) |
---|
| 28 | while random_pool.entropy < nbits: |
---|
| 29 | random_pool.add_event() |
---|
| 30 | random_pool.stir() |
---|
| 31 | return str( number.getRandomNumber( nbits, random_pool.get_bytes ) ) |
---|
| 32 | |
---|
| 33 | class SecurityHelper( object ): |
---|
| 34 | def __init__( self, **config ): |
---|
| 35 | self.id_secret = config['id_secret'] |
---|
| 36 | self.id_cipher = Blowfish.new( self.id_secret ) |
---|
| 37 | def encode_id( self, obj_id ): |
---|
| 38 | # Convert to string |
---|
| 39 | s = str( obj_id ) |
---|
| 40 | # Pad to a multiple of 8 with leading "!" |
---|
| 41 | s = ( "!" * ( 8 - len(s) % 8 ) ) + s |
---|
| 42 | # Encrypt |
---|
| 43 | return self.id_cipher.encrypt( s ).encode( 'hex' ) |
---|
| 44 | def decode_id( self, obj_id ): |
---|
| 45 | return int( self.id_cipher.decrypt( obj_id.decode( 'hex' ) ).lstrip( "!" ) ) |
---|
| 46 | def decode_string_id( self, obj_id ): |
---|
| 47 | return self.id_cipher.decrypt( obj_id.decode( 'hex' ) ).lstrip( "!" ) |
---|
| 48 | def encode_guid( self, session_key ): |
---|
| 49 | # Session keys are strings |
---|
| 50 | # Pad to a multiple of 8 with leading "!" |
---|
| 51 | s = ( "!" * ( 8 - len( session_key ) % 8 ) ) + session_key |
---|
| 52 | # Encrypt |
---|
| 53 | return self.id_cipher.encrypt( s ).encode( 'hex' ) |
---|
| 54 | def decode_guid( self, session_key ): |
---|
| 55 | # Session keys are strings |
---|
| 56 | return self.id_cipher.decrypt( session_key.decode( 'hex' ) ).lstrip( "!" ) |
---|
| 57 | def get_new_guid( self ): |
---|
| 58 | # Generate a unique, high entropy 128 bit random number |
---|
| 59 | return get_random_bytes( 16 ) |
---|
| 60 | |
---|