|  | @@ -45,7 +45,6 @@ plaintext = cyypto.decrypt(ciphertext)
 | 
	
		
			
				|  |  |  from Crypto.Cipher import Blowfish as cBlowfish
 | 
	
		
			
				|  |  |  from Crypto.Cipher import AES as cAES
 | 
	
		
			
				|  |  |  from Crypto.Cipher import ARC2 as cARC2
 | 
	
		
			
				|  |  | -from Crypto.Cipher import ARC4 as cARC4
 | 
	
		
			
				|  |  |  from Crypto.Cipher import CAST as cCAST
 | 
	
		
			
				|  |  |  from Crypto.Cipher import DES as cDES
 | 
	
		
			
				|  |  |  from Crypto.Cipher import DES3 as cDES3
 | 
	
	
		
			
				|  | @@ -115,13 +114,25 @@ class CryptoPasswordMismatchException(CryptoException):
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  class CryptoEngine(object):
 | 
	
		
			
				|  |  | -    """Cryptographic Engine"""
 | 
	
		
			
				|  |  | +    """
 | 
	
		
			
				|  |  | +    Cryptographic Engine, overrides CryptoEngineOld.
 | 
	
		
			
				|  |  | +    The main change is that _getcipher_real is now hashing the key
 | 
	
		
			
				|  |  | +    before encrypting it.
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    This method can eventually remove the call to _retrievedata,
 | 
	
		
			
				|  |  | +    which used to strip the _TAG from the plain text string or return
 | 
	
		
			
				|  |  | +    the cPickle object as string.
 | 
	
		
			
				|  |  | +    Since we don't use cPickle to serialize object anymore, we can
 | 
	
		
			
				|  |  | +    safely aim towards removing this method. Thus, removing also
 | 
	
		
			
				|  |  | +    the _TAG in the beginning of each string as per recommendation of
 | 
	
		
			
				|  |  | +    Ralf Herzog.
 | 
	
		
			
				|  |  | +    """
 | 
	
		
			
				|  |  |      _timeoutcount = 0
 | 
	
		
			
				|  |  |      _instance = None
 | 
	
		
			
				|  |  |      _callback = None
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      @classmethod
 | 
	
		
			
				|  |  | -    def get(cls):
 | 
	
		
			
				|  |  | +    def get(cls, dbver=None):
 | 
	
		
			
				|  |  |          """
 | 
	
		
			
				|  |  |          CryptoEngine.get() -> CryptoEngine
 | 
	
		
			
				|  |  |          Return an instance of CryptoEngine.
 | 
	
	
		
			
				|  | @@ -131,8 +142,11 @@ class CryptoEngine(object):
 | 
	
		
			
				|  |  |              algo = config.get_value("Encryption", "algorithm")
 | 
	
		
			
				|  |  |              if algo == "Dummy":
 | 
	
		
			
				|  |  |                  CryptoEngine._instance = DummyCryptoEngine()
 | 
	
		
			
				|  |  | -            else:
 | 
	
		
			
				|  |  | +            elif dbver < 0.5:
 | 
	
		
			
				|  |  | +                CryptoEngine._instance = CryptoEngineOld()
 | 
	
		
			
				|  |  | +            elif dbver == 0.5:
 | 
	
		
			
				|  |  |                  CryptoEngine._instance = CryptoEngine()
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |          return CryptoEngine._instance
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      def __init__(self):
 | 
	
	
		
			
				|  | @@ -180,7 +194,6 @@ class CryptoEngine(object):
 | 
	
		
			
				|  |  |          key = str(key).decode('base64')
 | 
	
		
			
				|  |  |          self._cipher = self._getcipher_real(key, self._algo)
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |      def encrypt(self, obj):
 | 
	
		
			
				|  |  |          """
 | 
	
		
			
				|  |  |          encrypt(obj) -> ciphertext
 | 
	
	
		
			
				|  | @@ -375,7 +388,7 @@ password again")
 | 
	
		
			
				|  |  |          """
 | 
	
		
			
				|  |  |          prepare data before encrypting
 | 
	
		
			
				|  |  |          """
 | 
	
		
			
				|  |  | -        #plaintext = cPickle.dumps(obj)
 | 
	
		
			
				|  |  | +        # plaintext = cPickle.dumps(obj)
 | 
	
		
			
				|  |  |          plaintext = _TAG + obj
 | 
	
		
			
				|  |  |          numblocks = (len(plaintext)/blocksize) + 1
 | 
	
		
			
				|  |  |          newdatasize = blocksize*numblocks
 | 
	
	
		
			
				|  | @@ -419,3 +432,51 @@ class DummyCryptoEngine(CryptoEngine):
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      def changepassword(self):
 | 
	
		
			
				|  |  |          return ''
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +class CryptoEngineOld(CryptoEngine):
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    def _getcipher_real(self, key, algo):
 | 
	
		
			
				|  |  | +        """
 | 
	
		
			
				|  |  | +        do the real job of decrypting using functions
 | 
	
		
			
				|  |  | +        form PyCrypto
 | 
	
		
			
				|  |  | +        """
 | 
	
		
			
				|  |  | +        if (algo == "AES"):
 | 
	
		
			
				|  |  | +            key = self._padkey(key, [16, 24, 32])
 | 
	
		
			
				|  |  | +            cipher = cAES.new(key, cAES.MODE_ECB)
 | 
	
		
			
				|  |  | +        elif (algo == 'ARC2'):
 | 
	
		
			
				|  |  | +            cipher = cARC2.new(key, cARC2.MODE_ECB)
 | 
	
		
			
				|  |  | +        elif (algo == 'ARC4'):
 | 
	
		
			
				|  |  | +            raise CryptoUnsupportedException("ARC4 is currently unsupported")
 | 
	
		
			
				|  |  | +        elif (algo == 'Blowfish'):
 | 
	
		
			
				|  |  | +            cipher = cBlowfish.new(key, cBlowfish.MODE_ECB)
 | 
	
		
			
				|  |  | +        elif (algo == 'CAST'):
 | 
	
		
			
				|  |  | +            cipher = cCAST.new(key, cCAST.MODE_ECB)
 | 
	
		
			
				|  |  | +        elif (algo == 'DES'):
 | 
	
		
			
				|  |  | +            self._padkey(key, [8])
 | 
	
		
			
				|  |  | +            cipher = cDES.new(key, cDES.MODE_ECB)
 | 
	
		
			
				|  |  | +        elif (algo == 'DES3'):
 | 
	
		
			
				|  |  | +            key = self._padkey(key, [16, 24])
 | 
	
		
			
				|  |  | +            cipher = cDES3.new(key, cDES3.MODE_ECB)
 | 
	
		
			
				|  |  | +        elif (algo == 'XOR'):
 | 
	
		
			
				|  |  | +            raise CryptoUnsupportedException("XOR is currently unsupported")
 | 
	
		
			
				|  |  | +        else:
 | 
	
		
			
				|  |  | +            raise CryptoException("Invalid algorithm specified")
 | 
	
		
			
				|  |  | +        return cipher
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    def _padkey(self, key, acceptable_lengths):
 | 
	
		
			
				|  |  | +        """
 | 
	
		
			
				|  |  | +        pad key with extra string
 | 
	
		
			
				|  |  | +        """
 | 
	
		
			
				|  |  | +        maxlen = max(acceptable_lengths)
 | 
	
		
			
				|  |  | +        keylen = len(key)
 | 
	
		
			
				|  |  | +        if (keylen > maxlen):
 | 
	
		
			
				|  |  | +            return key[0:maxlen]
 | 
	
		
			
				|  |  | +        acceptable_lengths.sort()
 | 
	
		
			
				|  |  | +        acceptable_lengths.reverse()
 | 
	
		
			
				|  |  | +        newkeylen = None
 | 
	
		
			
				|  |  | +        for i in acceptable_lengths:
 | 
	
		
			
				|  |  | +            if (i < keylen):
 | 
	
		
			
				|  |  | +                break
 | 
	
		
			
				|  |  | +            newkeylen = i
 | 
	
		
			
				|  |  | +        return key.ljust(newkeylen)
 |