|  | @@ -45,7 +45,7 @@ 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 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
 | 
	
	
		
			
				|  | @@ -60,6 +60,7 @@ import time
 | 
	
		
			
				|  |  |  import sys
 | 
	
		
			
				|  |  |  import ctypes
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  def zerome(string):
 | 
	
		
			
				|  |  |      """
 | 
	
		
			
				|  |  |      securely erase strings ...
 | 
	
	
		
			
				|  | @@ -77,33 +78,40 @@ _INSTANCE = None
 | 
	
		
			
				|  |  |  # Use this to tell if crypto is successful or not
 | 
	
		
			
				|  |  |  _TAG = "PWMANCRYPTO"
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  class CryptoException(Exception):
 | 
	
		
			
				|  |  |      """Generic Crypto Exception."""
 | 
	
		
			
				|  |  |      def __init__(self, message):
 | 
	
		
			
				|  |  |          self.message = message
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |      def __str__(self):
 | 
	
		
			
				|  |  |          return "CryptoException: " + self.message
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  class CryptoUnsupportedException(CryptoException):
 | 
	
		
			
				|  |  |      """Unsupported feature requested."""
 | 
	
		
			
				|  |  |      def __str__(self):
 | 
	
		
			
				|  |  | -        return "CryptoUnsupportedException: " +self.message
 | 
	
		
			
				|  |  | +        return "CryptoUnsupportedException: " + self.message
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  class CryptoBadKeyException(CryptoException):
 | 
	
		
			
				|  |  |      """Encryption key is incorrect."""
 | 
	
		
			
				|  |  |      def __str__(self):
 | 
	
		
			
				|  |  |          return "CryptoBadKeyException: " + self.message
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  class CryptoNoKeyException(CryptoException):
 | 
	
		
			
				|  |  |      """No key has been initalised."""
 | 
	
		
			
				|  |  |      def __str__(self):
 | 
	
		
			
				|  |  |          return "CryptoNoKeyException: " + self.message
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  class CryptoNoCallbackException(CryptoException):
 | 
	
		
			
				|  |  |      """No Callback has been set."""
 | 
	
		
			
				|  |  |      def __str__(self):
 | 
	
		
			
				|  |  |          return "CryptoNoCallbackException: " + self.message
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  class CryptoPasswordMismatchException(CryptoException):
 | 
	
		
			
				|  |  |      """Entered passwords do not match."""
 | 
	
		
			
				|  |  |      def __str__(self):
 | 
	
	
		
			
				|  | @@ -123,14 +131,14 @@ class CryptoEngine:
 | 
	
		
			
				|  |  |          Return an instance of CryptoEngine.
 | 
	
		
			
				|  |  |          If no instance is found, a CryptoException is raised.
 | 
	
		
			
				|  |  |          """
 | 
	
		
			
				|  |  | -        if (CryptoEngine._instance == None):
 | 
	
		
			
				|  |  | +        if CryptoEngine._instance is None:
 | 
	
		
			
				|  |  |              algo = config.get_value("Encryption", "algorithm")
 | 
	
		
			
				|  |  |              if algo == "Dummy":
 | 
	
		
			
				|  |  |                  CryptoEngine._instance = DummyCryptoEngine()
 | 
	
		
			
				|  |  |              else:
 | 
	
		
			
				|  |  |                  CryptoEngine._instance = CryptoEngine()
 | 
	
		
			
				|  |  |          return CryptoEngine._instance
 | 
	
		
			
				|  |  | -    #get = classmethod(get)
 | 
	
		
			
				|  |  | +    # get = classmethod(get)
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      def __init__(self):
 | 
	
		
			
				|  |  |          """Initialise the Cryptographic Engine
 | 
	
	
		
			
				|  | @@ -220,10 +228,10 @@ class CryptoEngine:
 | 
	
		
			
				|  |  |          password that the user provides. This makes it easy to change the
 | 
	
		
			
				|  |  |          password for the database.
 | 
	
		
			
				|  |  |          If oldKeyCrypted is none, then a new password is generated."""
 | 
	
		
			
				|  |  | -        if (self._callback == None):
 | 
	
		
			
				|  |  | +        if self._callback is None:
 | 
	
		
			
				|  |  |              raise CryptoNoCallbackException("No call back class has been \
 | 
	
		
			
				|  |  |  specified")
 | 
	
		
			
				|  |  | -        if (self._keycrypted == None):
 | 
	
		
			
				|  |  | +        if self._keycrypted is None:
 | 
	
		
			
				|  |  |              # Generate a new key, 32 bits in length, if that's
 | 
	
		
			
				|  |  |              # too long for the Cipher, _getCipherReal will sort it out
 | 
	
		
			
				|  |  |              random = OSRNG.new()
 | 
	
	
		
			
				|  | @@ -234,23 +242,32 @@ password")
 | 
	
		
			
				|  |  |              cipher = self._getcipher_real(password, self._algo)
 | 
	
		
			
				|  |  |              plainkey = cipher.decrypt(str(self._keycrypted).decode('base64'))
 | 
	
		
			
				|  |  |              key = self._retrievedata(plainkey)
 | 
	
		
			
				|  |  | -        
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |          newpassword1 = self._callback.getsecret("Please enter your new \
 | 
	
		
			
				|  |  |  password")
 | 
	
		
			
				|  |  |          newpassword2 = self._callback.getsecret("Please enter your new \
 | 
	
		
			
				|  |  |  password again")
 | 
	
		
			
				|  |  | -        if (newpassword1 != newpassword2):
 | 
	
		
			
				|  |  | -            raise CryptoPasswordMismatchException("Passwords do not match")
 | 
	
		
			
				|  |  | +        while newpassword1 != newpassword2:
 | 
	
		
			
				|  |  | +            print "Passwords do not match!"
 | 
	
		
			
				|  |  | +            newpassword1 = self._callback.getsecret("Please enter your new \
 | 
	
		
			
				|  |  | +password")
 | 
	
		
			
				|  |  | +            newpassword2 = self._callback.getsecret("Please enter your new \
 | 
	
		
			
				|  |  | +password again")
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        # if (newpassword1 != newpassword2):
 | 
	
		
			
				|  |  | +        #   raise CryptoPasswordMismatchException("Passwords do not match")
 | 
	
		
			
				|  |  |          newcipher = self._getcipher_real(newpassword1, self._algo)
 | 
	
		
			
				|  |  | -        self._keycrypted = str(newcipher.encrypt(self._preparedata(key,
 | 
	
		
			
				|  |  | -                           newcipher.block_size))).encode('base64')
 | 
	
		
			
				|  |  | -        # newpassword1, newpassword2 are not needed any more so we erase 
 | 
	
		
			
				|  |  | +        self._keycrypted = str(newcipher.encrypt(
 | 
	
		
			
				|  |  | +                               self._preparedata(key,
 | 
	
		
			
				|  |  | +                                                 newcipher.block_size)
 | 
	
		
			
				|  |  | +                               )).encode('base64')
 | 
	
		
			
				|  |  | +        # newpassword1, newpassword2 are not needed any more so we erase
 | 
	
		
			
				|  |  |          # them
 | 
	
		
			
				|  |  |          zerome(newpassword1)
 | 
	
		
			
				|  |  |          zerome(newpassword2)
 | 
	
		
			
				|  |  |          # we also want to create the cipher if there isn't one already
 | 
	
		
			
				|  |  |          # so this CryptoEngine can be used from now on
 | 
	
		
			
				|  |  | -        if (self._cipher == None):
 | 
	
		
			
				|  |  | +        if self._cipher is None:
 | 
	
		
			
				|  |  |              self._cipher = self._getcipher_real(str(key).decode('base64'),
 | 
	
		
			
				|  |  |                                                  self._algo)
 | 
	
		
			
				|  |  |              CryptoEngine._timeoutcount = time.time()
 | 
	
	
		
			
				|  | @@ -261,7 +278,7 @@ password again")
 | 
	
		
			
				|  |  |          """
 | 
	
		
			
				|  |  |          check if we have cipher
 | 
	
		
			
				|  |  |          """
 | 
	
		
			
				|  |  | -        if (self._cipher != None):
 | 
	
		
			
				|  |  | +        if self._cipher is not None:
 | 
	
		
			
				|  |  |              return True
 | 
	
		
			
				|  |  |          else:
 | 
	
		
			
				|  |  |              return False
 | 
	
	
		
			
				|  | @@ -276,13 +293,14 @@ password again")
 | 
	
		
			
				|  |  |          """
 | 
	
		
			
				|  |  |          get cypher from user, to decrypt DB
 | 
	
		
			
				|  |  |          """
 | 
	
		
			
				|  |  | -        if (self._cipher != None
 | 
	
		
			
				|  |  | +        if (self._cipher is not None
 | 
	
		
			
				|  |  |              and (self._timeout == -1
 | 
	
		
			
				|  |  | -            or (time.time() - CryptoEngine._timeoutcount) < self._timeout)):
 | 
	
		
			
				|  |  | +                 or (time.time() -
 | 
	
		
			
				|  |  | +                     CryptoEngine._timeoutcount) < self._timeout)):
 | 
	
		
			
				|  |  |              return self._cipher
 | 
	
		
			
				|  |  | -        if (self._callback == None):
 | 
	
		
			
				|  |  | +        if self._callback is None:
 | 
	
		
			
				|  |  |              raise CryptoNoCallbackException("No Callback exception")
 | 
	
		
			
				|  |  | -        if (self._keycrypted == None):
 | 
	
		
			
				|  |  | +        if self._keycrypted is None:
 | 
	
		
			
				|  |  |              raise CryptoNoKeyException("Encryption key has not been generated")
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          max_tries = 5
 | 
	
	
		
			
				|  | @@ -304,16 +322,15 @@ password")
 | 
	
		
			
				|  |  |                  tries += 1
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          if not key:
 | 
	
		
			
				|  |  | -            raise Exception("Wrong password entered %s times; giving up" \
 | 
	
		
			
				|  |  | -                    % max_tries)
 | 
	
		
			
				|  |  | +            raise Exception("Wrong password entered %s times; giving up"
 | 
	
		
			
				|  |  | +                            % max_tries)
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          self._cipher = self._getcipher_real(str(key).decode('base64'),
 | 
	
		
			
				|  |  | -                self._algo)
 | 
	
		
			
				|  |  | +                                            self._algo)
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          CryptoEngine._timeoutcount = time.time()
 | 
	
		
			
				|  |  |          return self._cipher
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |      def _getcipher_real(self, key, algo):
 | 
	
		
			
				|  |  |          """
 | 
	
		
			
				|  |  |          do the real job of decrypting using functions
 | 
	
	
		
			
				|  | @@ -335,7 +352,7 @@ password")
 | 
	
		
			
				|  |  |              cipher = cDES.new(key, cDES.MODE_ECB)
 | 
	
		
			
				|  |  |          elif (algo == 'DES3'):
 | 
	
		
			
				|  |  |              key = self._padkey(key, [16, 24])
 | 
	
		
			
				|  |  | -            cipher =  cDES3.new(key, cDES3.MODE_ECB)
 | 
	
		
			
				|  |  | +            cipher = cDES3.new(key, cDES3.MODE_ECB)
 | 
	
		
			
				|  |  |          elif (algo == 'XOR'):
 | 
	
		
			
				|  |  |              raise CryptoUnsupportedException("XOR is currently unsupported")
 | 
	
		
			
				|  |  |          else:
 |