|  | @@ -183,7 +183,7 @@ class CryptoEngine(object):  # pagma: no cover
 | 
											
												
													
														|  |              return CryptoEngine._instance_new
 |  |              return CryptoEngine._instance_new
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |      def __init__(self, salt=None, digest=None, algorithm='AES',
 |  |      def __init__(self, salt=None, digest=None, algorithm='AES',
 | 
											
												
													
														|  | -                 timeout=-1, reader=raw_input):
 |  | 
 | 
											
												
													
														|  | 
 |  | +                 timeout=-1, reader=None):
 | 
											
												
													
														|  |          """
 |  |          """
 | 
											
												
													
														|  |          Initialise the Cryptographic Engine
 |  |          Initialise the Cryptographic Engine
 | 
											
												
													
														|  |          """
 |  |          """
 | 
											
										
											
												
													
														|  | @@ -193,6 +193,7 @@ class CryptoEngine(object):  # pagma: no cover
 | 
											
												
													
														|  |          self._timeout = timeout
 |  |          self._timeout = timeout
 | 
											
												
													
														|  |          self._cipher = None
 |  |          self._cipher = None
 | 
											
												
													
														|  |          self._reader = reader
 |  |          self._reader = reader
 | 
											
												
													
														|  | 
 |  | +        self._callback = None
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |      def authenticate(self, password):
 |  |      def authenticate(self, password):
 | 
											
												
													
														|  |          """
 |  |          """
 | 
											
										
											
												
													
														|  | @@ -205,9 +206,28 @@ class CryptoEngine(object):  # pagma: no cover
 | 
											
												
													
														|  |              return True
 |  |              return True
 | 
											
												
													
														|  |          return False
 |  |          return False
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | 
 |  | +    def _auth(self):
 | 
											
												
													
														|  | 
 |  | +        """
 | 
											
												
													
														|  | 
 |  | +        Read password from the user, if the password is correct,
 | 
											
												
													
														|  | 
 |  | +        finish the execution an return the password and salt which
 | 
											
												
													
														|  | 
 |  | +        are read from the file.
 | 
											
												
													
														|  | 
 |  | +        """
 | 
											
												
													
														|  | 
 |  | +        salt, digest = get_digest_from_file('passwords.txt')
 | 
											
												
													
														|  | 
 |  | +        tries = 0
 | 
											
												
													
														|  | 
 |  | +        while tries < 5:
 | 
											
												
													
														|  | 
 |  | +            password = self._getsecret("Please type in your master password:"
 | 
											
												
													
														|  | 
 |  | +                                       ).encode('utf-8')
 | 
											
												
													
														|  | 
 |  | +            if authenticate(password, salt, digest):
 | 
											
												
													
														|  | 
 |  | +                return password, salt
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +            print("You entered a wrong password...")
 | 
											
												
													
														|  | 
 |  | +            tries += 1
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +        raise CryptoException("You entered wrong password 5 times..")
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  |      def encrypt(self, text):
 |  |      def encrypt(self, text):
 | 
											
												
													
														|  |          if not self._is_authenticated():
 |  |          if not self._is_authenticated():
 | 
											
												
													
														|  | -            p, s = cli_auth(self._reader)
 |  | 
 | 
											
												
													
														|  | 
 |  | +            p, s = self._auth()
 | 
											
												
													
														|  |              cipher = get_cipher(p, s)
 |  |              cipher = get_cipher(p, s)
 | 
											
												
													
														|  |              del(p)
 |  |              del(p)
 | 
											
												
													
														|  |              return EncodeAES(cipher, prepare_data(text, AES.block_size))
 |  |              return EncodeAES(cipher, prepare_data(text, AES.block_size))
 | 
											
										
											
												
													
														|  | @@ -224,6 +244,12 @@ class CryptoEngine(object):  # pagma: no cover
 | 
											
												
													
														|  |          return DecodeAES(self._cipher, prepare_data(cipher_text,
 |  |          return DecodeAES(self._cipher, prepare_data(cipher_text,
 | 
											
												
													
														|  |                                                      AES.block_size))
 |  |                                                      AES.block_size))
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | 
 |  | +    def forget(self):
 | 
											
												
													
														|  | 
 |  | +        """
 | 
											
												
													
														|  | 
 |  | +        discard cipher
 | 
											
												
													
														|  | 
 |  | +        """
 | 
											
												
													
														|  | 
 |  | +        self._cipher = None
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  |      def _is_authenticated(self):
 |  |      def _is_authenticated(self):
 | 
											
												
													
														|  |          if not self._is_timedout() and self._cipher is not None:
 |  |          if not self._is_timedout() and self._cipher is not None:
 | 
											
												
													
														|  |              return True
 |  |              return True
 | 
											
										
											
												
													
														|  | @@ -237,7 +263,10 @@ class CryptoEngine(object):  # pagma: no cover
 | 
											
												
													
														|  |          return False
 |  |          return False
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |      def changepassword(self, reader=raw_input):
 |  |      def changepassword(self, reader=raw_input):
 | 
											
												
													
														|  | -        self._keycrypted = self._create_password(reader=reader)
 |  | 
 | 
											
												
													
														|  | 
 |  | +        if self._callback is None:
 | 
											
												
													
														|  | 
 |  | +            raise CryptoException("No callback class has been "
 | 
											
												
													
														|  | 
 |  | +                                  "specified")
 | 
											
												
													
														|  | 
 |  | +        self._keycrypted = self._create_password()
 | 
											
												
													
														|  |          return self._keycrypted
 |  |          return self._keycrypted
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |      @property
 |  |      @property
 | 
											
										
											
												
													
														|  | @@ -256,13 +285,13 @@ class CryptoEngine(object):  # pagma: no cover
 | 
											
												
													
														|  |          else:
 |  |          else:
 | 
											
												
													
														|  |              raise Exception("callback must be an instance of Callback!")
 |  |              raise Exception("callback must be an instance of Callback!")
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | -    def _create_password(self, reader=raw_input):
 |  | 
 | 
											
												
													
														|  | 
 |  | +    def _create_password(self):
 | 
											
												
													
														|  |          """
 |  |          """
 | 
											
												
													
														|  |          Create a secret password as a hash and the salt used for this hash.
 |  |          Create a secret password as a hash and the salt used for this hash.
 | 
											
												
													
														|  |          Change reader to manipulate how input is given.
 |  |          Change reader to manipulate how input is given.
 | 
											
												
													
														|  |          """
 |  |          """
 | 
											
												
													
														|  |          salt = base64.b64encode(os.urandom(32))
 |  |          salt = base64.b64encode(os.urandom(32))
 | 
											
												
													
														|  | -        passwd = reader("Please type in the secret key:")
 |  | 
 | 
											
												
													
														|  | 
 |  | +        passwd = self._getsecret("Please type in the secret key:")
 | 
											
												
													
														|  |          key = self._get_digest(passwd, salt)
 |  |          key = self._get_digest(passwd, salt)
 | 
											
												
													
														|  |          hpk = salt+'$6$'.encode('utf8')+binascii.hexlify(key)
 |  |          hpk = salt+'$6$'.encode('utf8')+binascii.hexlify(key)
 | 
											
												
													
														|  |          return hpk.decode('utf-8')
 |  |          return hpk.decode('utf-8')
 | 
											
										
											
												
													
														|  | @@ -274,6 +303,18 @@ class CryptoEngine(object):  # pagma: no cover
 | 
											
												
													
														|  |          iterations = 5000
 |  |          iterations = 5000
 | 
											
												
													
														|  |          return PBKDF2(password, salt, dkLen=32, count=iterations)
 |  |          return PBKDF2(password, salt, dkLen=32, count=iterations)
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | 
 |  | +    def set_cryptedkey(self, key):
 | 
											
												
													
														|  | 
 |  | +        # TODO: rename this method!
 | 
											
												
													
														|  | 
 |  | +        salt, digest = key.split('$6$')
 | 
											
												
													
														|  | 
 |  | +        self._digest = digest.encode('utf-8')
 | 
											
												
													
														|  | 
 |  | +        self._salt = salt.encode('utf-8'),
 | 
											
												
													
														|  | 
 |  | +    def get_cryptedkey(self):
 | 
											
												
													
														|  | 
 |  | +        # TODO: rename this method!
 | 
											
												
													
														|  | 
 |  | +        """
 | 
											
												
													
														|  | 
 |  | +        return _keycrypted
 | 
											
												
													
														|  | 
 |  | +        """
 | 
											
												
													
														|  | 
 |  | +        return self._keycrypted
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |  if __name__ == '__main__':  # pragma: no cover
 |  |  if __name__ == '__main__':  # pragma: no cover
 | 
											
												
													
														|  |      if '-i' in sys.argv:
 |  |      if '-i' in sys.argv:
 |