Example #1
0
 def test_load_settings_from_file(self):
     settings = {
         'settings': {
             'unit.test': {
                 'domain': 'unit.test',
                 'length': 11,
                 'iterations': 5000,
                 'notes': 'Nice note!',
                 'cDate': '2011-02-12T11:07:31',
                 'mDate': '2011-02-12T11:07:32'
             },
             'some.domain': {
                 'domain': 'some.domain',
                 'length': 4,
                 'usedCharacters': '6478593021',
                 'cDate': '2013-06-17T04:03:41',
                 'mDate': '2014-08-02T10:37:12'
             }
         },
         'synced': []
     }
     salt = os.urandom(32)
     crypter = Crypter(salt, 'xyz')
     f = open(os.path.expanduser('~/.ctSESAM_test.pws'), 'bw')
     f.write(salt + struct.pack('!I', 0) + crypter.encrypt(Packer.compress(json.dumps(settings).encode('utf-8'))))
     f.close()
     self.manager.load_settings_from_file('xyz')
     self.assertIn('unit.test', self.manager.get_domain_list())
     self.assertIn('some.domain', self.manager.get_domain_list())
     self.assertEqual(11, self.manager.get_setting('unit.test').get_length())
     self.assertEqual(5000, self.manager.get_setting('unit.test').get_iterations())
     self.assertEqual('Nice note!', self.manager.get_setting('unit.test').get_notes())
     self.assertEqual(4, self.manager.get_setting('some.domain').get_length())
     self.assertEqual('6478593021', self.manager.get_setting('some.domain').get_character_set())
Example #2
0
    def load_settings_from_file(self, password):
        """
        This loads the saved settings. It is a good idea to call this method the minute you have a password.

        :param str password:
        """
        if os.path.isfile(self.settings_file):
            file = open(self.settings_file, 'br')
            data = file.read()
            crypter = Crypter(data[:32], password)
            saved_settings = json.loads(
                str(Packer.decompress(crypter.decrypt(data[32:])),
                    encoding='utf-8'))
            for domain_name in saved_settings['settings'].keys():
                data_set = saved_settings['settings'][domain_name]
                found = False
                i = 0
                while i < len(self.settings):
                    setting = self.settings[i]
                    if setting.get_domain() == domain_name:
                        found = True
                        if datetime.strptime(
                                data_set['mDate'],
                                "%Y-%m-%dT%H:%M:%S") > setting.get_m_date():
                            setting.load_from_dict(data_set)
                            setting.set_synced(setting.get_domain() in
                                               saved_settings['synced'])
                    i += 1
                if not found:
                    new_setting = PasswordSetting(domain_name)
                    new_setting.load_from_dict(data_set)
                    new_setting.set_synced(
                        new_setting.get_domain() in saved_settings['synced'])
                    self.settings.append(new_setting)
            file.close()
    def save_settings_to_file(self, password):
        """
        This actually saves the settings to a file on the disk. The file is encrypted so you need to supply the
        password.

        :param password: masterpassword
        :type password: str
        """
        salt = os.urandom(32)
        crypter = Crypter(salt, password)
        file = open(self.settings_file, 'bw')
        encrypted_sync_settings = crypter.encrypt(
            self.sync_manager.get_binary_sync_settings())
        file.write(
            salt + struct.pack('!I', len(encrypted_sync_settings)) +
            encrypted_sync_settings + crypter.encrypt(
                Packer.compress(json.dumps(self.get_settings_as_dict()))))
        file.close()
        try:
            import win32con
            import win32api
            win32api.SetFileAttributes(self.settings_file,
                                       win32con.FILE_ATTRIBUTE_HIDDEN)
        except ImportError:
            pass
    def get_export_data(self, password):
        """
        This gives you a base64 encoded string of encrypted settings data (the blob).

        :param str password:
        :return: encrypted settings blob
        :rtype: str
        """
        settings_list = self.get_settings_as_dict()['settings']
        if self.remote_data:
            for domain_name in self.remote_data.keys():
                data_set = self.remote_data[domain_name]
                if 'deleted' in data_set and data_set['deleted']:
                    for i, setting_dict in enumerate(settings_list):
                        if setting_dict['domain'] == setting_dict['domain'] and datetime.strptime(
                                data_set['mDate'], "%Y-%m-%dT%H:%M:%S") > datetime.strptime(
                                setting_dict['mDate'], "%Y-%m-%dT%H:%M:%S"):
                            settings_list[i] = data_set
                if domain_name not in settings_list.keys():
                    settings_list[domain_name] = {
                        'mDate': datetime.now(),
                        'deleted': True
                    }
        salt = os.urandom(32)
        crypter = Crypter(salt, password)
        return b64encode(b'\x00' + salt + crypter.encrypt(Packer.compress(json.dumps(settings_list))))
    def get_export_data(self, password, salt=None):
        """
        This gives you a base64 encoded string of encrypted settings data (the blob).

        :param password: masterpassword
        :type password: str
        :param salt: salt for the encryption: This is for testing only! Do not set it normally!
        :type salt: bytes
        :return: encrypted settings blob
        :rtype: str
        """
        settings_list = self.get_settings_as_dict()['settings']
        if self.remote_data:
            for domain_name in self.remote_data.keys():
                data_set = self.remote_data[domain_name]
                if 'deleted' in data_set and data_set['deleted']:
                    for i, setting_dict in enumerate(settings_list):
                        if setting_dict['domain'] == setting_dict[
                                'domain'] and datetime.strptime(
                                    data_set['mDate'],
                                    "%Y-%m-%dT%H:%M:%S") > datetime.strptime(
                                        setting_dict['mDate'],
                                        "%Y-%m-%dT%H:%M:%S"):
                            settings_list[i] = data_set
                if domain_name not in settings_list.keys():
                    settings_list[domain_name] = {
                        'mDate': datetime.now(),
                        'deleted': True
                    }
        if not salt:
            salt = os.urandom(32)
        crypter = Crypter(salt, password)
        return b64encode(
            b'\x00' + salt +
            crypter.encrypt(Packer.compress(json.dumps(settings_list))))
    def load_settings_from_file(self, password):
        """
        This loads the saved settings. It is a good idea to call this method the minute you have a password.

        :param str password:
        """
        if os.path.isfile(self.settings_file):
            file = open(self.settings_file, 'br')
            data = file.read()
            crypter = Crypter(data[:32], password)
            saved_settings = json.loads(str(Packer.decompress(crypter.decrypt(data[32:])), encoding='utf-8'))
            for domain_name in saved_settings['settings'].keys():
                data_set = saved_settings['settings'][domain_name]
                found = False
                i = 0
                while i < len(self.settings):
                    setting = self.settings[i]
                    if setting.get_domain() == domain_name:
                        found = True
                        if datetime.strptime(data_set['mDate'], "%Y-%m-%dT%H:%M:%S") > setting.get_m_date():
                            setting.load_from_dict(data_set)
                            setting.set_synced(setting.get_domain() in saved_settings['synced'])
                    i += 1
                if not found:
                    new_setting = PasswordSetting(domain_name)
                    new_setting.load_from_dict(data_set)
                    new_setting.set_synced(new_setting.get_domain() in saved_settings['synced'])
                    self.settings.append(new_setting)
            file.close()
 def test_get_export_data(self):
     settings = {
         'settings': {
             'unit.test': {
                 'domain': 'unit.test',
                 'length': 11,
                 'iterations': 5000,
                 'notes': 'Nice note!',
                 'salt': 'cGVwcGVy',
                 'usedCharacters': 'abcdefghijklmnopqrstuvwxyzABCDEFGHJKLMNPQRTUVWXYZ0123456789' +
                                   '#!"§$%&/()[]{}=-_+*<>;:.',
                 'cDate': '2011-02-12T11:07:31',
                 'mDate': '2011-02-12T11:07:32'
             },
             'some.domain': {
                 'domain': 'some.domain',
                 'length': 4,
                 'iterations': 4096,
                 'salt': 'cGVwcGVy',
                 'usedCharacters': '6478593021',
                 'cDate': '2013-06-17T04:03:41',
                 'mDate': '2014-08-02T10:37:12'
             }
         },
         'synced': []
     }
     crypter = Crypter('xyz')
     f = open(os.path.expanduser('~/.ctSESAM_test.pws'), 'bw')
     f.write(crypter.encrypt(Packer.compress(json.dumps(settings).encode('utf-8'))))
     f.close()
     self.manager.load_settings_from_file('xyz')
     self.assertEqual(
         b64encode(b'\x00' + crypter.encrypt(Packer.compress(json.dumps(settings['settings']).encode('utf-8')))),
         self.manager.get_export_data('xyz')
     )
    def update_from_sync(self, password):
        """
        Call this method to pull settings from the sync server.

        :param password: the masterpassword
        :type password: str
        """
        pull_successful, data = self.sync_manager.pull()
        if not pull_successful:
            print("Sync failed: No connection to the server.")
            return False
        if not len(data) > 0:
            return False
        binary_data = b64decode(data)
        data_version = binary_data[:1]
        if data_version == b'\x00':
            encryption_salt = binary_data[1:33]
            encrypted_data = binary_data[33:]
            crypter = Crypter(encryption_salt, password)
            self.remote_data = json.loads(
                str(Packer.decompress(crypter.decrypt(encrypted_data)), encoding='utf-8'))
            self.update_remote = False
            for domain_name in self.remote_data.keys():
                data_set = self.remote_data[domain_name]
                found = False
                i = 0
                while i < len(self.settings):
                    setting = self.settings[i]
                    if setting.get_domain() == domain_name:
                        found = True
                        if datetime.strptime(data_set['mDate'], "%Y-%m-%dT%H:%M:%S") > setting.get_m_date():
                            if 'deleted' in data_set and data_set['deleted']:
                                self.settings.pop(i)
                            else:
                                setting.load_from_dict(data_set)
                                setting.set_synced(True)
                                self.update_remote = True
                                i += 1
                        else:
                            i += 1
                    else:
                        i += 1
                if not found:
                    new_setting = PasswordSetting(domain_name)
                    new_setting.load_from_dict(data_set)
                    new_setting.set_synced(True)
                    self.settings.append(new_setting)
            for setting in self.settings:
                found = False
                for domain_name in self.remote_data.keys():
                    data_set = self.remote_data[domain_name]
                    if setting.get_domain() == domain_name:
                        found = True
                        if setting.get_m_date() >= datetime.strptime(data_set['mDate'], "%Y-%m-%dT%H:%M:%S"):
                            self.update_remote = True
                if not found:
                    self.update_remote = True
        else:
            print("Unknown data format version! Could not update.")
Example #9
0
    def update_from_export_data(self, password, data):
        """
        This takes a base64 encoded string of encrypted settings (a blob) and updates the internal list of settings.

        :param str password: the masterpassword
        :param str data: base64 encoded data
        """
        binary_data = b64decode(data)
        data_version = binary_data[:1]
        if data_version == b'\x00':
            encryption_salt = binary_data[1:33]
            encrypted_data = binary_data[:33]
            crypter = Crypter(encryption_salt, password)
            self.remote_data = json.loads(
                str(Packer.decompress(crypter.decrypt(encrypted_data)),
                    encoding='utf-8'))
            update_remote = False
            for domain_name in self.remote_data.keys():
                data_set = self.remote_data[domain_name]
                found = False
                i = 0
                while i < len(self.settings):
                    setting = self.settings[i]
                    if setting.get_domain() == domain_name:
                        found = True
                        if datetime.strptime(
                                data_set['mDate'],
                                "%Y-%m-%dT%H:%M:%S") > setting.get_m_date():
                            if 'deleted' in data_set and data_set['deleted']:
                                self.settings.pop(i)
                            else:
                                setting.load_from_dict(data_set)
                                setting.set_synced(True)
                                i += 1
                        else:
                            i += 1
                            update_remote = True
                    else:
                        i += 1
                if not found:
                    new_setting = PasswordSetting(domain_name)
                    new_setting.load_from_dict(data_set)
                    new_setting.set_synced(True)
                    self.settings.append(new_setting)
            for setting in self.settings:
                found = False
                for domain_name in self.remote_data.keys():
                    data_set = self.remote_data[domain_name]
                    if setting.get_domain() == domain_name:
                        found = True
                        if setting.get_m_date() >= datetime.strptime(
                                data_set['mDate'], "%Y-%m-%dT%H:%M:%S"):
                            update_remote = True
                if not found:
                    update_remote = True
            return update_remote
        else:
            print("Unknown data format version! Could not update.")
            return False
Example #10
0
def decrypt():
    # get the raw post data (it will be parsed in decrypt below)
    request.get_data()
    data = request.data

    # create the crypter object
    crypter = Crypter(Config.MASTER_SECRET)

    # decrypt and return the plaintext
    return crypter.decrypt(data)
Example #11
0
def encrypt():
    # get the raw post data
    request.get_data()
    data = request.data

    # create the crypter object
    crypter = Crypter(Config.MASTER_SECRET)

    # encrypt and return a string holding the ciphertext, iv and salt
    return crypter.encrypt(data)
    def update_from_export_data(self, password, data):
        """
        This takes a base64 encoded string of encrypted settings (a blob) and updates the internal list of settings.

        :param str password: the masterpassword
        :param str data: base64 encoded data
        """
        binary_data = b64decode(data)
        data_version = binary_data[:1]
        if data_version == b'\x00':
            encryption_salt = binary_data[1:33]
            encrypted_data = binary_data[:33]
            crypter = Crypter(encryption_salt, password)
            self.remote_data = json.loads(str(Packer.decompress(crypter.decrypt(encrypted_data)), encoding='utf-8'))
            update_remote = False
            for domain_name in self.remote_data.keys():
                data_set = self.remote_data[domain_name]
                found = False
                i = 0
                while i < len(self.settings):
                    setting = self.settings[i]
                    if setting.get_domain() == domain_name:
                        found = True
                        if datetime.strptime(data_set['mDate'], "%Y-%m-%dT%H:%M:%S") > setting.get_m_date():
                            if 'deleted' in data_set and data_set['deleted']:
                                self.settings.pop(i)
                            else:
                                setting.load_from_dict(data_set)
                                setting.set_synced(True)
                                i += 1
                        else:
                            i += 1
                            update_remote = True
                    else:
                        i += 1
                if not found:
                    new_setting = PasswordSetting(domain_name)
                    new_setting.load_from_dict(data_set)
                    new_setting.set_synced(True)
                    self.settings.append(new_setting)
            for setting in self.settings:
                found = False
                for domain_name in self.remote_data.keys():
                    data_set = self.remote_data[domain_name]
                    if setting.get_domain() == domain_name:
                        found = True
                        if setting.get_m_date() >= datetime.strptime(data_set['mDate'], "%Y-%m-%dT%H:%M:%S"):
                            update_remote = True
                if not found:
                    update_remote = True
            return update_remote
        else:
            print("Unknown data format version! Could not update.")
            return False
 def test_decrypt(self):
     ciphertext = b'1lsDkebMaZZeO+/DnvVAUYPmXrQOdCAFQ79C3sElpwamOLtX444tRMiecg4/a9394w51dbmKo89CYKpw19nOaKkbF8Dy' + \
         b'll9MQJSRUXZEoc3aoaBvgGBCy4rVM62hEQLfpOUdBcrJTPAU3l8zM8V+AN560z7Rj9gXoGkXsotIpEjNg0+hwdmcVRAw' + \
         b'JAiDnAbH7K1Q0olPdkM187tbF5A9OEzCU5M36qzUyr/68a1oGL65JCaMAGoHTpQa2i4DlTEkVF1xPkB40ZF167jo360lEQ=='
     self.assertEqual(0, len(b64decode(ciphertext)) % 16)
     password = "******"
     crypter = Crypter("pepper".encode('utf-8'), password)
     self.assertEqual(b'Important information with quite some length. ' +
                      b'This message is as long as this because otherwise only one cipher block would ' +
                      b'be encrypted. This long message insures that more than one block is needed.',
                      crypter.decrypt(b64decode(ciphertext)))
 def test_decrypt(self):
     cyphertext = "FRQFCWa38eSIrPnhELojAPrOb8oKzs2yoAbNqVONBEuac3OhUKY12mP+TNyZs1MRUbY9hnqvIG18" + \
                  "7MqTAVTzI0fCJhmR4stc/k4YpS+HptmzcTgEfXeli56davPUkmJ59yz2vvF3t/pCUOk0qWNQ2vv9" + \
                  "dU2sJhvOdQ7RVKzbw2DJAFtEM2BxJq8Oqa4mB4sBC/GpIP3xtNxANJPyN8xTSL2F4Ktt5hIcX3AV" + \
                  "UrnGYSjGeDHGua8iKNFohYtaPj3vvzaSVpGyzAfmlVEdN5/8zQ=="
     self.assertEqual(0, len(b64decode(cyphertext)) % 16)
     password = "******"
     crypter = Crypter(password)
     self.assertEqual(b'Important information with quite some length. ' +
                      b'This message is as long as this because otherwise only one cipher block would ' +
                      b'be encrypted. This long message insures that more than one block is needed.',
                      crypter.decrypt(b64decode(cyphertext)))
 def test_decrypt(self):
     ciphertext = b'1lsDkebMaZZeO+/DnvVAUYPmXrQOdCAFQ79C3sElpwamOLtX444tRMiecg4/a9394w51dbmKo89CYKpw19nOaKkbF8Dy' + \
         b'll9MQJSRUXZEoc3aoaBvgGBCy4rVM62hEQLfpOUdBcrJTPAU3l8zM8V+AN560z7Rj9gXoGkXsotIpEjNg0+hwdmcVRAw' + \
         b'JAiDnAbH7K1Q0olPdkM187tbF5A9OEzCU5M36qzUyr/68a1oGL65JCaMAGoHTpQa2i4DlTEkVF1xPkB40ZF167jo360lEQ=='
     self.assertEqual(0, len(b64decode(ciphertext)) % 16)
     password = "******"
     crypter = Crypter("pepper".encode('utf-8'), password)
     self.assertEqual(
         b'Important information with quite some length. ' +
         b'This message is as long as this because otherwise only one cipher block would '
         +
         b'be encrypted. This long message insures that more than one block is needed.',
         crypter.decrypt(b64decode(ciphertext)))
 def test_encrypt(self):
     message_string = "Important information with quite some length. " + \
                     "This message is as long as this because otherwise only one cipher block would " + \
                     "be encrypted. This long message insures that more than one block is needed."
     password = "******"
     message = message_string.encode('utf-8')
     crypter = Crypter(password)
     ciphertext = crypter.encrypt(message)
     self.assertEqual(
         b'FRQFCWa38eSIrPnhELojAPrOb8oKzs2yoAbNqVONBEuac3OhUKY12mP+TNyZs1MRUbY9hnqvIG18' +
         b'7MqTAVTzI0fCJhmR4stc/k4YpS+HptmzcTgEfXeli56davPUkmJ59yz2vvF3t/pCUOk0qWNQ2vv9' +
         b'dU2sJhvOdQ7RVKzbw2DJAFtEM2BxJq8Oqa4mB4sBC/GpIP3xtNxANJPyN8xTSL2F4Ktt5hIcX3AV' +
         b'UrnGYSjGeDHGua8iKNFohYtaPj3vvzaSVpGyzAfmlVEdN5/8zQ==',
         b64encode(ciphertext))
 def test_save_settings_to_file(self):
     self.manager.get_setting('abc.de')
     new_setting = PasswordSetting('hugo.com')
     new_setting.set_length(12)
     self.manager.save_setting(new_setting)
     self.manager.save_settings_to_file('xyz')
     f = open(os.path.expanduser('~/.ctSESAM_test.pws'), 'br')
     crypter = Crypter('xyz')
     data = json.loads(Packer.decompress(crypter.decrypt(f.read())).decode('utf8'))
     f.close()
     self.assertEqual('abc.de', data['settings']['abc.de']['domain'])
     self.assertEqual(10, data['settings']['abc.de']['length'])
     self.assertEqual('hugo.com', data['settings']['hugo.com']['domain'])
     self.assertEqual(12, data['settings']['hugo.com']['length'])
Example #18
0
 def test_decrypt(self):
     cyphertext = "FRQFCWa38eSIrPnhELojAPrOb8oKzs2yoAbNqVONBEuac3OhUKY12mP+TNyZs1MRUbY9hnqvIG18" + \
                  "7MqTAVTzI0fCJhmR4stc/k4YpS+HptmzcTgEfXeli56davPUkmJ59yz2vvF3t/pCUOk0qWNQ2vv9" + \
                  "dU2sJhvOdQ7RVKzbw2DJAFtEM2BxJq8Oqa4mB4sBC/GpIP3xtNxANJPyN8xTSL2F4Ktt5hIcX3AV" + \
                  "UrnGYSjGeDHGua8iKNFohYtaPj3vvzaSVpGyzAfmlVEdN5/8zQ=="
     self.assertEqual(0, len(b64decode(cyphertext)) % 16)
     password = "******"
     crypter = Crypter(password)
     self.assertEqual(
         b'Important information with quite some length. ' +
         b'This message is as long as this because otherwise only one cipher block would '
         +
         b'be encrypted. This long message insures that more than one block is needed.',
         crypter.decrypt(b64decode(cyphertext)))
Example #19
0
 def test_save_settings_to_file(self):
     self.manager.get_setting('abc.de')
     new_setting = PasswordSetting('hugo.com')
     new_setting.set_length(12)
     self.manager.save_setting(new_setting)
     self.manager.save_settings_to_file('xyz')
     f = open(os.path.expanduser('~/.ctSESAM_test.pws'), 'br')
     crypter = Crypter('xyz')
     data = json.loads(
         Packer.decompress(crypter.decrypt(f.read())).decode('utf8'))
     f.close()
     self.assertEqual('abc.de', data['settings']['abc.de']['domain'])
     self.assertEqual(10, data['settings']['abc.de']['length'])
     self.assertEqual('hugo.com', data['settings']['hugo.com']['domain'])
     self.assertEqual(12, data['settings']['hugo.com']['length'])
Example #20
0
 def test_save_settings_to_file(self):
     self.manager.get_setting('abc.de')
     new_setting = PasswordSetting('hugo.com')
     new_setting.set_length(12)
     self.manager.set_setting(new_setting)
     self.manager.save_settings_to_file('xyz')
     with open(os.path.expanduser('~/.ctSESAM_test.pws'), 'br') as f:
         data = f.read()
     crypter = Crypter(data[:32], 'xyz')
     sync_settings_len = struct.unpack('!I', data[32:36])[0]
     data = json.loads(Packer.decompress(crypter.decrypt(data[36+sync_settings_len:])).decode('utf8'))
     self.assertEqual('abc.de', data['settings']['abc.de']['domain'])
     self.assertEqual(10, data['settings']['abc.de']['length'])
     self.assertEqual('hugo.com', data['settings']['hugo.com']['domain'])
     self.assertEqual(12, data['settings']['hugo.com']['length'])
Example #21
0
 def test_get_domain_list(self):
     settings = {
         'settings': {
             'unit.test': {
                 'domain':
                 'unit.test',
                 'length':
                 11,
                 'iterations':
                 5000,
                 'notes':
                 'Nice note!',
                 'salt':
                 'cGVwcGVy',
                 'usedCharacters':
                 'abcdefghijklmnopqrstuvwxyzABCDEFGHJKLMNPQRTUVWXYZ0123456789'
                 + '#!"§$%&/()[]{}=-_+*<>;:.',
                 'cDate':
                 '2011-02-12T11:07:31',
                 'mDate':
                 '2011-02-12T11:07:32'
             },
             'some.domain': {
                 'domain': 'some.domain',
                 'length': 4,
                 'iterations': 4096,
                 'salt': 'cGVwcGVy',
                 'usedCharacters': '6478593021',
                 'cDate': '2013-06-17T04:03:41',
                 'mDate': '2014-08-02T10:37:12'
             }
         },
         'synced': []
     }
     crypter = Crypter('xyz')
     f = open(os.path.expanduser('~/.ctSESAM_test.pws'), 'bw')
     f.write(
         crypter.encrypt(
             Packer.compress(json.dumps(settings).encode('utf-8'))))
     f.close()
     self.manager.load_settings_from_file('xyz')
     self.assertEqual(
         settings['settings']['unit.test'],
         self.manager.get_settings_as_dict()['settings']['unit.test'])
     self.assertEqual(
         settings['settings']['some.domain'],
         self.manager.get_settings_as_dict()['settings']['some.domain'])
     self.assertEqual(settings, self.manager.get_settings_as_dict())
Example #22
0
 def test_encrypt(self):
     message_string = "Important information with quite some length. " + \
                     "This message is as long as this because otherwise only one cipher block would " + \
                     "be encrypted. This long message insures that more than one block is needed."
     password = "******"
     message = message_string.encode('utf-8')
     crypter = Crypter(password)
     ciphertext = crypter.encrypt(message)
     self.assertEqual(
         b'FRQFCWa38eSIrPnhELojAPrOb8oKzs2yoAbNqVONBEuac3OhUKY12mP+TNyZs1MRUbY9hnqvIG18'
         +
         b'7MqTAVTzI0fCJhmR4stc/k4YpS+HptmzcTgEfXeli56davPUkmJ59yz2vvF3t/pCUOk0qWNQ2vv9'
         +
         b'dU2sJhvOdQ7RVKzbw2DJAFtEM2BxJq8Oqa4mB4sBC/GpIP3xtNxANJPyN8xTSL2F4Ktt5hIcX3AV'
         + b'UrnGYSjGeDHGua8iKNFohYtaPj3vvzaSVpGyzAfmlVEdN5/8zQ==',
         b64encode(ciphertext))
    def load_settings_from_file(self,
                                password,
                                omit_sync_settings_questions=False):
        """
        This loads the saved settings. It is a good idea to call this method the minute you have a password.

        :param str password: masterpassword
        :param bool omit_sync_settings_questions: do not ask for questions? (Defalut: False)
        :type password: str
        """
        if os.path.isfile(self.settings_file):
            file = open(self.settings_file, 'br')
            data = file.read()
            crypter = Crypter(data[:32], password)
            sync_settings_len = struct.unpack('!I', data[32:36])[0]
            if sync_settings_len > 0:
                self.sync_manager.load_binary_sync_settings(
                    crypter.decrypt(data[36:36 + sync_settings_len]))
            saved_settings = json.loads(
                str(Packer.decompress(
                    crypter.decrypt(data[36 + sync_settings_len:])),
                    encoding='utf-8'))
            for domain_name in saved_settings['settings'].keys():
                data_set = saved_settings['settings'][domain_name]
                found = False
                i = 0
                while i < len(self.settings):
                    setting = self.settings[i]
                    if setting.get_domain() == domain_name:
                        found = True
                        if datetime.strptime(
                                data_set['mDate'],
                                "%Y-%m-%dT%H:%M:%S") > setting.get_m_date():
                            setting.load_from_dict(data_set)
                            setting.set_synced(setting.get_domain() in
                                               saved_settings['synced'])
                    i += 1
                if not found:
                    new_setting = PasswordSetting(domain_name)
                    new_setting.load_from_dict(data_set)
                    new_setting.set_synced(
                        new_setting.get_domain() in saved_settings['synced'])
                    self.settings.append(new_setting)
            file.close()
        else:
            if not omit_sync_settings_questions:
                self.sync_manager.ask_for_sync_settings()
    def save_settings_to_file(self, password):
        """
        This actually saves the settings to a file on the disk. The file is encrypted so you need to supply the
        password.

        :param str password:
        """
        salt = os.urandom(32)
        crypter = Crypter(salt, password)
        file = open(self.settings_file, 'bw')
        file.write(salt + crypter.encrypt(Packer.compress(json.dumps(self.get_settings_as_dict()))))
        file.close()
        try:
            import win32con
            import win32api
            win32api.SetFileAttributes(self.settings_file, win32con.FILE_ATTRIBUTE_HIDDEN)
        except ImportError:
            pass
Example #25
0
    def save_settings_to_file(self, password):
        """
        This actually saves the settings to a file on the disk. The file is encrypted so you need to supply the
        password.

        :param str password:
        """
        salt = os.urandom(32)
        crypter = Crypter(salt, password)
        file = open(self.settings_file, 'bw')
        file.write(salt + crypter.encrypt(
            Packer.compress(json.dumps(self.get_settings_as_dict()))))
        file.close()
        try:
            import win32con
            import win32api
            win32api.SetFileAttributes(self.settings_file,
                                       win32con.FILE_ATTRIBUTE_HIDDEN)
        except ImportError:
            pass
Example #26
0
 def test_update_from_sync(self):
     settings = {
         'settings': {
             'unit.test': {
                 'domain': 'unit.test',
                 'length': 11,
                 'iterations': 5000,
                 'notes': 'Nice note!',
                 'salt': 'cGVwcGVy',
                 'usedCharacters': 'abcdefghijklmnopqrstuvwxyzABCDEFGHJKLMNPQRTUVWXYZ0123456789' +
                                   '#!"§$%&/()[]{}=-_+*<>;:.',
                 'cDate': '2011-02-12T11:07:31',
                 'mDate': '2011-02-12T11:07:32'
             },
             'some.domain': {
                 'domain': 'some.domain',
                 'length': 4,
                 'iterations': 4096,
                 'salt': 'cGVwcGVy',
                 'usedCharacters': '6478593021',
                 'cDate': '2013-06-17T04:03:41',
                 'mDate': '2014-08-02T10:37:12'
             }
         },
         'synced': []
     }
     salt = os.urandom(32)
     crypter = Crypter(salt, 'xyz')
     f = open(os.path.expanduser('~/.ctSESAM_test.pws'), 'bw')
     f.write(salt + struct.pack('!I', 0) + crypter.encrypt(
         Packer.compress(json.dumps(settings).encode('utf-8'))))
     f.close()
     self.manager.load_settings_from_file('xyz')
     self.manager.sync_manager = MockSyncManager()
     self.manager.update_from_sync('xyz')
     self.assertIn('unit.test', self.manager.get_domain_list())
     self.assertIn('some.domain', self.manager.get_domain_list())
     self.assertIn('third.domain', self.manager.get_domain_list())
     self.assertEqual(5001, self.manager.get_setting('unit.test').get_iterations())
     self.assertEqual(4096, self.manager.get_setting('some.domain').get_iterations())
     self.assertEqual(4098, self.manager.get_setting('third.domain').get_iterations())
Example #27
0
    def pull(self):
        """
        Returns some mock data tor the sync test.

        :return: base64 mock data blob
        :rtype: (bool, str)
        """
        remote_data = {
            'unit.test': {
                'domain': 'unit.test',
                'length': 12,
                'iterations': 5001,
                'notes': 'another note!',
                'salt': 'cGVwcGVy',
                'usedCharacters': 'abcdefghijklmnopqrstuvwxyzABCDEFGHJKLMNPQRTUVWXYZ0123456789',
                'cDate': '2011-02-12T11:07:31',
                'mDate': '2013-07-12T14:46:11'
            },
            'some.domain': {
                'domain': 'some.domain',
                'length': 4,
                'iterations': 4097,
                'salt': 'cGVwcGVy',
                'usedCharacters': '6478593021',
                'cDate': '2013-06-17T04:03:41',
                'mDate': '2014-08-02T10:37:11'
            },
            'third.domain': {
                'domain': 'third.domain',
                'length': 10,
                'iterations': 4098,
                'salt': 'cGVwcGVy',
                'usedCharacters': 'aeiou',
                'cDate': '2013-06-17T04:03:41',
                'mDate': '2014-08-02T10:37:11'
            }
        }
        salt = os.urandom(32)
        crypter = Crypter(salt, 'xyz')
        return True, str(b64encode(b'\x00' + salt + crypter.encrypt(
            Packer.compress(json.dumps(remote_data).encode('utf-8')))), encoding='utf-8')
    def save_settings_to_file(self, password):
        """
        This actually saves the settings to a file on the disk. The file is encrypted so you need to supply the
        password.

        :param password: masterpassword
        :type password: str
        """
        salt = os.urandom(32)
        crypter = Crypter(salt, password)
        file = open(self.settings_file, 'bw')
        encrypted_sync_settings = crypter.encrypt(self.sync_manager.get_binary_sync_settings())
        file.write(salt + struct.pack('!I', len(encrypted_sync_settings)) + encrypted_sync_settings +
                   crypter.encrypt(Packer.compress(json.dumps(self.get_settings_as_dict()))))
        file.close()
        try:
            import win32con
            import win32api
            win32api.SetFileAttributes(self.settings_file, win32con.FILE_ATTRIBUTE_HIDDEN)
        except ImportError:
            pass
    def load_settings_from_file(self, password, omit_sync_settings_questions=False):
        """
        This loads the saved settings. It is a good idea to call this method the minute you have a password.

        :param str password: masterpassword
        :param bool omit_sync_settings_questions: do not ask for questions? (Defalut: False)
        :type password: str
        """
        if os.path.isfile(self.settings_file):
            file = open(self.settings_file, 'br')
            data = file.read()
            crypter = Crypter(data[:32], password)
            sync_settings_len = struct.unpack('!I', data[32:36])[0]
            if sync_settings_len > 0:
                self.sync_manager.load_binary_sync_settings(crypter.decrypt(data[36:36+sync_settings_len]))
            saved_settings = json.loads(str(Packer.decompress(crypter.decrypt(data[36+sync_settings_len:])),
                                            encoding='utf-8'))
            for domain_name in saved_settings['settings'].keys():
                data_set = saved_settings['settings'][domain_name]
                found = False
                i = 0
                while i < len(self.settings):
                    setting = self.settings[i]
                    if setting.get_domain() == domain_name:
                        found = True
                        if datetime.strptime(data_set['mDate'], "%Y-%m-%dT%H:%M:%S") > setting.get_m_date():
                            setting.load_from_dict(data_set)
                            setting.set_synced(setting.get_domain() in saved_settings['synced'])
                    i += 1
                if not found:
                    new_setting = PasswordSetting(domain_name)
                    new_setting.load_from_dict(data_set)
                    new_setting.set_synced(new_setting.get_domain() in saved_settings['synced'])
                    self.settings.append(new_setting)
            file.close()
        else:
            if not omit_sync_settings_questions:
                self.sync_manager.ask_for_sync_settings()
Example #30
0
 def __init__(self,domain):
     self.domain = domain
     self.url = None
     self.username = None
     self.legacyPassword = None
     self.notes = None
     self.iterations = 4096
     self.salt = Crypter.createSalt()
     self.creationDate = datetime.now()
     self.modificationDate = self.creationDate
     self.extraCharacters = DEFAULT_CHARACTER_SET_EXTRA
     self.template = 'x' * 10
     self.calculate_template(True, True, True, True)
     self.synced = False
Example #31
0
 def test_get_export_data(self):
     settings = {
         'settings': {
             'unit.test': {
                 'domain': 'unit.test',
                 'length': 11,
                 'iterations': 5000,
                 'notes': 'Nice note!',
                 'salt': 'cGVwcGVy',
                 'usedCharacters': 'abcdefghijklmnopqrstuvwxyzABCDEFGHJKLMNPQRTUVWXYZ0123456789' +
                                   '#!"§$%&/()[]{}=-_+*<>;:.',
                 'cDate': '2011-02-12T11:07:31',
                 'mDate': '2011-02-12T11:07:32'
             },
             'some.domain': {
                 'domain': 'some.domain',
                 'length': 4,
                 'iterations': 4096,
                 'salt': 'cGVwcGVy',
                 'usedCharacters': '6478593021',
                 'cDate': '2013-06-17T04:03:41',
                 'mDate': '2014-08-02T10:37:12'
             }
         },
         'synced': []
     }
     salt = os.urandom(32)
     crypter = Crypter(salt, 'xyz')
     f = open(os.path.expanduser('~/.ctSESAM_test.pws'), 'bw')
     f.write(salt + struct.pack('!I', 0) + crypter.encrypt(
         Packer.compress(json.dumps(settings).encode('utf-8'))))
     f.close()
     self.manager.load_settings_from_file('xyz')
     data = b64decode(self.manager.get_export_data('xyz'))
     salt = data[1:33]
     crypter = Crypter(salt, 'xyz')
     self.assertEqual(
         settings['settings'],
         json.loads(str(Packer.decompress(crypter.decrypt(data[33:])), encoding='utf-8')))
Example #32
0
 def test_update_from_export_data(self):
     remote_data = {
         'unit.test': {
             'domain': 'unit.test',
             'length': 12,
             'iterations': 5001,
             'notes': 'another note!',
             'salt': 'cGVwcGVy',
             'usedCharacters':
             'abcdefghijklmnopqrstuvwxyzABCDEFGHJKLMNPQRTUVWXYZ0123456789',
             'cDate': '2011-02-12T11:07:31',
             'mDate': '2013-07-12T14:46:11'
         },
         'some.domain': {
             'domain': 'some.domain',
             'length': 4,
             'iterations': 4097,
             'salt': 'cGVwcGVy',
             'usedCharacters': '6478593021',
             'cDate': '2013-06-17T04:03:41',
             'mDate': '2014-08-02T10:37:11'
         },
         'third.domain': {
             'domain': 'third.domain',
             'length': 10,
             'iterations': 4098,
             'salt': 'cGVwcGVy',
             'usedCharacters': 'aeiou',
             'cDate': '2013-06-17T04:03:41',
             'mDate': '2014-08-02T10:37:11'
         }
     }
     settings = {
         'settings': {
             'unit.test': {
                 'domain':
                 'unit.test',
                 'length':
                 11,
                 'iterations':
                 5000,
                 'notes':
                 'Nice note!',
                 'salt':
                 'cGVwcGVy',
                 'usedCharacters':
                 'abcdefghijklmnopqrstuvwxyzABCDEFGHJKLMNPQRTUVWXYZ0123456789'
                 + '#!"§$%&/()[]{}=-_+*<>;:.',
                 'cDate':
                 '2011-02-12T11:07:31',
                 'mDate':
                 '2011-02-12T11:07:32'
             },
             'some.domain': {
                 'domain': 'some.domain',
                 'length': 4,
                 'iterations': 4096,
                 'salt': 'cGVwcGVy',
                 'usedCharacters': '6478593021',
                 'cDate': '2013-06-17T04:03:41',
                 'mDate': '2014-08-02T10:37:12'
             }
         },
         'synced': []
     }
     crypter = Crypter('xyz')
     f = open(os.path.expanduser('~/.ctSESAM_test.pws'), 'bw')
     f.write(
         crypter.encrypt(
             Packer.compress(json.dumps(settings).encode('utf-8'))))
     f.close()
     self.manager.load_settings_from_file('xyz')
     self.assertTrue(
         self.manager.update_from_export_data(
             'xyz',
             b64encode(b'\x00' + crypter.encrypt(
                 Packer.compress(json.dumps(remote_data).encode('utf-8')))))
     )
     self.assertEqual(['unit.test', 'some.domain', 'third.domain'],
                      self.manager.get_domain_list())
     self.assertEqual(
         5001,
         self.manager.get_setting('unit.test').get_iterations())
     self.assertEqual(
         4096,
         self.manager.get_setting('some.domain').get_iterations())
     self.assertEqual(
         4098,
         self.manager.get_setting('third.domain').get_iterations())
Example #33
0
    '''

    app = wx.App()
    error_dialog = wx.MessageDialog(None, str(message), "Error",
                                    wx.OK | wx.ICON_ERROR)
    error_dialog.ShowModal()
    app.MainLoop()


# GO
if __name__ == "__main__":

    ## START
    try:
        mutex = Mutex()
        go = Crypter()
    # Could not acquire mutex
    except MutexAlreadyAcquired as maa:
        showErrorDialog("The file is corrupt and cannot be opened")
        sys.exit()
    # Exception
    except Exception as ex:
        if "--debug" in sys.argv:
            exc_type, exc_obj, exc_tb = sys.exc_info()
            msg = "Exception encountered!\n\n"
            msg += "Exception: %s\n" % ex
            msg += "Type: %s\n" % exc_type.__name__
            msg += "Traceback: %s" % "".join(traceback.format_tb(exc_tb))
            showErrorDialog(msg)
            sys.exit()
    def update_from_sync(self, password):
        """
        Call this method to pull settings from the sync server.

        :param password: the masterpassword
        :type password: str
        """
        pull_successful, data = self.sync_manager.pull()
        if not pull_successful:
            print("Sync failed: No connection to the server.")
            return False
        if not len(data) > 0:
            return False
        binary_data = b64decode(data)
        data_version = binary_data[:1]
        if data_version == b'\x00':
            encryption_salt = binary_data[1:33]
            encrypted_data = binary_data[33:]
            crypter = Crypter(encryption_salt, password)
            self.remote_data = json.loads(
                str(Packer.decompress(crypter.decrypt(encrypted_data)),
                    encoding='utf-8'))
            self.update_remote = False
            for domain_name in self.remote_data.keys():
                data_set = self.remote_data[domain_name]
                found = False
                i = 0
                while i < len(self.settings):
                    setting = self.settings[i]
                    if setting.get_domain() == domain_name:
                        found = True
                        if datetime.strptime(
                                data_set['mDate'],
                                "%Y-%m-%dT%H:%M:%S") > setting.get_m_date():
                            if 'deleted' in data_set and data_set['deleted']:
                                self.settings.pop(i)
                            else:
                                setting.load_from_dict(data_set)
                                setting.set_synced(True)
                                self.update_remote = True
                                i += 1
                        else:
                            i += 1
                    else:
                        i += 1
                if not found:
                    new_setting = PasswordSetting(domain_name)
                    new_setting.load_from_dict(data_set)
                    new_setting.set_synced(True)
                    self.settings.append(new_setting)
            for setting in self.settings:
                found = False
                for domain_name in self.remote_data.keys():
                    data_set = self.remote_data[domain_name]
                    if setting.get_domain() == domain_name:
                        found = True
                        if setting.get_m_date() >= datetime.strptime(
                                data_set['mDate'], "%Y-%m-%dT%H:%M:%S"):
                            self.update_remote = True
                if not found:
                    self.update_remote = True
        else:
            print("Unknown data format version! Could not update.")