def decrypt_remote_settings(kgk_mng, settings_mng):
    remote_kgk_manager = KgkManager()
    remote_kgk_manager.update_from_blob(master_password.encode('utf-8'), b64decode(data))
    if kgk_exists and remote_kgk_manager.has_kgk() and kgk_mng.has_kgk() and \
       kgk_mng.get_kgk() != remote_kgk_manager.get_kgk():
        print("Lokal und auf dem Server gibt es unterschiedliche KGKs. Das ist ein Problem!")
    else:
        if not kgk_exists:
            kgk_mng = remote_kgk_manager
            kgk_mng.set_preference_manager(preference_manager)
            kgk_mng.store_local_kgk_block()
        settings_mng.update_from_export_data(remote_kgk_manager, b64decode(data))
        print("Verbindung erfolgreich getestet.")
Beispiel #2
0
 def test_fresh_salt2(self):
     kgkm = KgkManager()
     kgkm.salt2 = b"\x3A" * 32
     self.assertEqual(b"\x3A" * 32, kgkm.get_salt2())
     kgkm.fresh_salt2()
     self.assertNotEqual(b"\x3A" * 32, kgkm.get_salt2())
     self.assertEqual(32, len(kgkm.get_salt2()))
Beispiel #3
0
 def test_fresh_iv2(self):
     kgkm = KgkManager()
     kgkm.iv2 = b"\x02" * 16
     self.assertEqual(b"\x02" * 16, kgkm.get_iv2())
     kgkm.fresh_iv2()
     self.assertNotEqual(b"\x02" * 16, kgkm.get_iv2())
     self.assertEqual(16, len(kgkm.get_iv2()))
 def test_store_local_settings(self):
     abc_setting = self.manager.get_setting('abc.de')
     abc_setting.set_template('xAxonaxxxx')
     self.manager.set_setting(abc_setting)
     new_setting = PasswordSetting('hugo.com')
     new_setting.set_template('xonxAxxaxxxx')
     self.manager.set_setting(new_setting)
     kgk_manager = KgkManager()
     kgk_manager.set_preference_manager(self.preference_manager)
     kgk_manager.create_new_kgk()
     salt = os.urandom(32)
     kgk_manager.create_and_save_new_kgk_block(
         Crypter(Crypter.createIvKey(b'xyz', salt, iterations=3)))
     self.manager.store_local_settings(kgk_manager)
     with open(os.path.expanduser('~/.ctSESAM_test.pws'), 'br') as f:
         data = f.read()
     settings_crypter = PasswordSettingsManager.get_settings_crypter(
         kgk_manager)
     decrypted_settings = settings_crypter.decrypt(data[144:])
     sync_settings_len = struct.unpack('!I', decrypted_settings[:4])[0]
     data = json.loads(
         Packer.decompress(
             decrypted_settings[4 + sync_settings_len:]).decode('utf8'))
     self.assertEqual('abc.de', data['settings']['abc.de']['domain'])
     self.assertEqual('xAxonaxxxx',
                      data['settings']['abc.de']['passwordTemplate'])
     self.assertEqual('hugo.com', data['settings']['hugo.com']['domain'])
     self.assertEqual('xonxAxxaxxxx',
                      data['settings']['hugo.com']['passwordTemplate'])
Beispiel #5
0
 def test_str(self):
     kgkm = KgkManager()
     self.assertEqual("<KGK: , salt: >", str(kgkm))
     kgkm.salt2 = b"\x01"*32
     kgkm.iv2 = b"\x02"*16
     self.assertEqual("<KGK: , salt: , iv2: 02020202020202020202020202020202, " +
                      "salt2: 0101010101010101010101010101010101010101010101010101010101010101>",
                      str(kgkm))
     kgkm.salt = b"\x03"*32
     kgkm.kgk = b"\x04"*64
     self.assertEqual("<KGK: 04040404040404040404040404040404040404040404040404040404040404040404040404040404040" +
                      "404040404040404040404040404040404040404040404, " +
                      "salt: 0303030303030303030303030303030303030303030303030303030303030303, " +
                      "iv2: 02020202020202020202020202020202, " +
                      "salt2: 0101010101010101010101010101010101010101010101010101010101010101>",
                      str(kgkm))
Beispiel #6
0
 def __init__(self):
     super(MainWindow, self).__init__()
     self.nam = QNetworkAccessManager()
     self.setWindowIcon(QIcon(os.path.join('icons', 'Logo_rendered_edited.png')))
     layout = QBoxLayout(QBoxLayout.TopToBottom)
     layout.setContentsMargins(0, 0, 0, 0)
     self.preference_manager = PreferenceManager()
     self.kgk_manager = KgkManager()
     self.kgk_manager.set_preference_manager(self.preference_manager)
     self.settings_manager = PasswordSettingsManager(self.preference_manager)
     self.setting_dirty = True
     # Header bar
     header_bar = QFrame()
     header_bar.setStyleSheet(
         "QWidget { background: rgb(40, 40, 40); } " +
         "QToolButton { background: rgb(40, 40, 40); }" +
         "QToolTip { color: rgb(255, 255, 255); background-color: rgb(20, 20, 20); " +
         "border: 1px solid white; }")
     header_bar.setAutoFillBackground(True)
     header_bar.setFixedHeight(45)
     header_bar_layout = QBoxLayout(QBoxLayout.LeftToRight)
     header_bar_layout.addStretch()
     header_bar.setLayout(header_bar_layout)
     layout.addWidget(header_bar)
     self.create_header_bar(header_bar_layout)
     # Widget area
     main_area = QFrame()
     main_layout = QBoxLayout(QBoxLayout.TopToBottom)
     main_area.setLayout(main_layout)
     layout.addWidget(main_area)
     self.create_main_area(main_layout)
     # Window layout
     layout.addStretch()
     main_layout.addStretch()
     self.setLayout(layout)
     settings = QSettings()
     size = settings.value("MainWindow/size")
     if not size:
         size = QSize(350, 450)
     self.resize(size)
     position = settings.value("MainWindow/pos")
     if not position:
         position = QPoint(0, 24)
     self.move(position)
     self.setWindowTitle("c't SESAM")
     self.master_password_edit.setFocus()
     self.show()
Beispiel #7
0
 def test_get_kgk_has_kgk(self):
     kgkm = KgkManager()
     self.assertEqual(b'', kgkm.get_kgk())
     self.assertFalse(kgkm.has_kgk())
     kgkm.kgk = b"\xE4" * 64
     kgkm.kgk_crypter = Crypter(
         Crypter.createIvKey(b'1234', b'pepper', iterations=3))
     self.assertEqual(b"\xE4" * 64, kgkm.get_kgk())
     self.assertTrue(kgkm.has_kgk())
Beispiel #8
0
 def test_fresh_salt2(self):
     kgkm = KgkManager()
     kgkm.salt2 = b"\x3A"*32
     self.assertEqual(b"\x3A"*32, kgkm.get_salt2())
     kgkm.fresh_salt2()
     self.assertNotEqual(b"\x3A"*32, kgkm.get_salt2())
     self.assertEqual(32, len(kgkm.get_salt2()))
Beispiel #9
0
 def test_fresh_iv2(self):
     kgkm = KgkManager()
     kgkm.iv2 = b"\x02"*16
     self.assertEqual(b"\x02"*16, kgkm.get_iv2())
     kgkm.fresh_iv2()
     self.assertNotEqual(b"\x02"*16, kgkm.get_iv2())
     self.assertEqual(16, len(kgkm.get_iv2()))
Beispiel #10
0
 def test_get_kgk_has_kgk(self):
     kgkm = KgkManager()
     self.assertEqual(b'', kgkm.get_kgk())
     self.assertFalse(kgkm.has_kgk())
     kgkm.kgk = b"\xE4"*64
     kgkm.kgk_crypter = Crypter(Crypter.createIvKey(b'1234', b'pepper', iterations=3))
     self.assertEqual(b"\xE4"*64, kgkm.get_kgk())
     self.assertTrue(kgkm.has_kgk())
Beispiel #11
0
 def sync_clicked(self):
     self.masterpassword_entered()
     if not self.settings_manager.sync_manager.has_settings():
         self.show_sync_settings()
     else:
         pull_successful, data = self.settings_manager.sync_manager.pull()
         if pull_successful and len(data) > 0:
             remote_kgk_manager = KgkManager()
             remote_kgk_manager.update_from_blob(self.master_password_edit.text().encode('utf-8'), b64decode(data))
             if len(self.preference_manager.get_kgk_block()) == 112 and \
                remote_kgk_manager.has_kgk() and self.kgk_manager.has_kgk() and \
                self.kgk_manager.get_kgk() != remote_kgk_manager.get_kgk():
                 if len(self.settings_manager.get_domain_list()) > 0:
                     print("Lokal und auf dem Server gibt es unterschiedliche KGKs. Das ist ein Problem!")
                 self.migrate_local_domains(remote_kgk_manager)
             else:
                 if len(self.preference_manager.get_kgk_block()) != 112:
                     self.kgk_manager = remote_kgk_manager
                     self.kgk_manager.set_preference_manager(self.preference_manager)
                     self.kgk_manager.store_local_kgk_block()
                 self.settings_manager.update_from_export_data(remote_kgk_manager, b64decode(data))
                 self.domain_edit.blockSignals(True)
                 current_domain = self.domain_edit.lineEdit().text()
                 for i in reversed(range(self.domain_edit.count())):
                     self.domain_edit.removeItem(i)
                 self.domain_edit.insertItems(0, self.settings_manager.get_domain_list())
                 self.domain_edit.blockSignals(False)
                 self.domain_edit.setEditText(current_domain)
         self.settings_manager.store_settings(self.kgk_manager)
    def load_settings(self, kgk_manager, password, no_sync=False):
        """
        Loads settings from local file and from a sync server if possible.

        :param kgk_manager: kgk manager
        :type kgk_manager: KgkManager
        :param password: the masterpassword
        :type password: str
        :param no_sync: skip the sync update?
        :type no_sync: bool
        """
        self.load_local_settings(kgk_manager)
        if not no_sync:
            if self.sync_manager.has_settings():
                pull_successful, data = self.sync_manager.pull()
                if pull_successful and len(data) > 0:
                    remote_kgk_manager = KgkManager()
                    remote_kgk_manager.update_from_blob(
                        password.encode('utf-8'), b64decode(data))
                    if remote_kgk_manager.has_kgk() and kgk_manager.get_kgk(
                    ) != remote_kgk_manager.get_kgk():
                        raise ValueError(
                            "KGK mismatch! This are not your settings!")
                    self.update_from_export_data(remote_kgk_manager,
                                                 b64decode(data))
                else:
                    print("Sync failed: No connection to the server.")
    def load_settings(self, kgk_manager, password, no_sync=False):
        """
        Loads settings from local file and from a sync server if possible.

        :param kgk_manager: kgk manager
        :type kgk_manager: KgkManager
        :param password: the masterpassword
        :type password: str
        :param no_sync: skip the sync update?
        :type no_sync: bool
        """
        self.load_local_settings(kgk_manager)
        if not no_sync:
            if self.sync_manager.has_settings():
                pull_successful, data = self.sync_manager.pull()
                if pull_successful and len(data) > 0:
                    remote_kgk_manager = KgkManager()
                    remote_kgk_manager.update_from_blob(password.encode('utf-8'), b64decode(data))
                    if remote_kgk_manager.has_kgk() and kgk_manager.get_kgk() != remote_kgk_manager.get_kgk():
                        raise ValueError("KGK mismatch! This are not your settings!")
                    self.update_from_export_data(remote_kgk_manager, b64decode(data))
                else:
                    print("Sync failed: No connection to the server.")
 def test_get_domain_list(self):
     settings = {
         'settings': {
             'unit.test': {
                 'domain': 'unit.test',
                 'extras': '#!"§$%&/()[]{}=-_+*<>;:.',
                 'passwordTemplate': 'xxxaoxxAxxn',
                 'iterations': 5000,
                 'notes': 'Nice note!',
                 'salt': 'cGVwcGVy',
                 'cDate': '2011-02-12T11:07:31',
                 'mDate': '2011-02-12T11:07:32'
             },
             'some.domain': {
                 'domain': 'some.domain',
                 'extras': '#!"§$%&/()[]{}=-_+*<>;:.',
                 'passwordTemplate': 'xxxo',
                 'iterations': 4096,
                 'salt': 'cGVwcGVy',
                 'cDate': '2013-06-17T04:03:41',
                 'mDate': '2014-08-02T10:37:12'
             }
         },
         'synced': []
     }
     salt = os.urandom(32)
     f = open(os.path.expanduser('~/.ctSESAM_test.pws'), 'bw')
     data = json.dumps(settings).encode('utf-8')
     kgk_manager = KgkManager()
     kgk_manager.set_preference_manager(self.preference_manager)
     kgk_manager.create_new_kgk()
     kgk_block = kgk_manager.create_and_save_new_kgk_block(
         Crypter(Crypter.createIvKey(b'xyz', salt, iterations=3)))
     crypter = PasswordSettingsManager.get_settings_crypter(kgk_manager)
     f.write(salt + kgk_block +
             crypter.encrypt(struct.pack('!I', 0) + Packer.compress(data)))
     f.close()
     self.preference_manager.read_file()
     self.manager.load_local_settings(kgk_manager)
     self.assertIn('settings', self.manager.get_settings_as_dict())
     self.assertIn('unit.test',
                   self.manager.get_settings_as_dict()['settings'])
     self.assertEqual(
         settings['settings']['unit.test'],
         self.manager.get_settings_as_dict()['settings']['unit.test'])
     self.assertIn('some.domain',
                   self.manager.get_settings_as_dict()['settings'])
     self.assertEqual(
         settings['settings']['some.domain'],
         self.manager.get_settings_as_dict()['settings']['some.domain'])
     self.assertEqual(settings, self.manager.get_settings_as_dict())
 def test_load_settings_from_file(self):
     settings = {
         'settings': {
             'unit.test': {
                 'domain': 'unit.test',
                 'passwordTemplate': 'xxxxxxxxxxo',
                 'extras': '#OWspx6;3gov0/1',
                 'iterations': 5000,
                 'notes': 'Nice note!',
                 'cDate': '2011-02-12T11:07:31',
                 'mDate': '2011-02-12T11:07:32'
             },
             'some.domain': {
                 'domain': 'some.domain',
                 'passwordTemplate': 'oxxx',
                 'extras': '6478593021',
                 'cDate': '2013-06-17T04:03:41',
                 'mDate': '2014-08-02T10:37:12'
             }
         },
         'synced': []
     }
     salt = os.urandom(32)
     data = json.dumps(settings).encode('utf-8')
     kgk_manager = KgkManager()
     kgk_manager.set_preference_manager(self.preference_manager)
     kgk_manager.create_new_kgk()
     kgk_block = kgk_manager.create_and_save_new_kgk_block(
         Crypter(Crypter.createIvKey(b'xyz', salt, iterations=3)))
     crypter = PasswordSettingsManager.get_settings_crypter(kgk_manager)
     f = open(os.path.expanduser('~/.ctSESAM_test.pws'), 'bw')
     f.write(salt + kgk_block +
             crypter.encrypt(struct.pack('!I', 0) + Packer.compress(data)))
     f.close()
     self.preference_manager.read_file()
     self.manager.load_local_settings(kgk_manager)
     self.assertIn('unit.test', self.manager.get_domain_list())
     self.assertIn('some.domain', self.manager.get_domain_list())
     self.assertEqual('xxxxxxxxxxo',
                      self.manager.get_setting('unit.test').get_template())
     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(
         'oxxx',
         self.manager.get_setting('some.domain').get_template())
     self.assertEqual(
         '6478593021',
         self.manager.get_setting('some.domain').get_character_set())
Beispiel #16
0
def decrypt_remote_settings(kgk_mng, settings_mng):
    remote_kgk_manager = KgkManager()
    remote_kgk_manager.update_from_blob(master_password.encode('utf-8'), b64decode(data))
    if kgk_exists and remote_kgk_manager.has_kgk() and kgk_mng.has_kgk() and \
       kgk_mng.get_kgk() != remote_kgk_manager.get_kgk():
        print("Lokal und auf dem Server gibt es unterschiedliche KGKs. Das ist ein Problem!")
    else:
        if not kgk_exists:
            kgk_mng = remote_kgk_manager
            kgk_mng.set_preference_manager(preference_manager)
            kgk_mng.store_local_kgk_block()
        settings_mng.update_from_export_data(remote_kgk_manager, b64decode(data))
        print("Verbindung erfolgreich getestet.")
Beispiel #17
0
 def test_str(self):
     kgkm = KgkManager()
     self.assertEqual("<KGK: , salt: >", str(kgkm))
     kgkm.salt2 = b"\x01" * 32
     kgkm.iv2 = b"\x02" * 16
     self.assertEqual(
         "<KGK: , salt: , iv2: 02020202020202020202020202020202, " +
         "salt2: 0101010101010101010101010101010101010101010101010101010101010101>",
         str(kgkm))
     kgkm.salt = b"\x03" * 32
     kgkm.kgk = b"\x04" * 64
     self.assertEqual(
         "<KGK: 04040404040404040404040404040404040404040404040404040404040404040404040404040404040"
         + "404040404040404040404040404040404040404040404, " +
         "salt: 0303030303030303030303030303030303030303030303030303030303030303, "
         + "iv2: 02020202020202020202020202020202, " +
         "salt2: 0101010101010101010101010101010101010101010101010101010101010101>",
         str(kgkm))
Beispiel #18
0
 def test_get_salt2(self):
     kgkm = KgkManager()
     kgkm.salt2 = b"\x3A"*32
     self.assertEqual(b"\x3A"*32, kgkm.get_salt2())
 def __init__(self, kgk):
     self.kgk_manager = KgkManager()
     self.kgk_manager.set_preference_manager(
         PreferenceManager(os.path.expanduser('~/.ctSESAM_test_extra.pws')))
     self.kgk_manager.kgk = kgk
class MockSyncManager(object):
    """
    We do not really want to sync.
    """
    def __init__(self, kgk):
        self.kgk_manager = KgkManager()
        self.kgk_manager.set_preference_manager(
            PreferenceManager(os.path.expanduser('~/.ctSESAM_test_extra.pws')))
        self.kgk_manager.kgk = kgk

    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)
        kgk_block = self.kgk_manager.create_and_save_new_kgk_block(
            self.kgk_manager.get_kgk_crypter(b'xyz', salt))
        settings_crypter = PasswordSettingsManager.get_settings_crypter(
            self.kgk_manager)
        return True, str(
            b64encode(b'\x01' + salt + kgk_block + settings_crypter.encrypt(
                Packer.compress(json.dumps(remote_data).encode('utf-8')))),
            encoding='utf-8')

    def get_binary_sync_settings(self):
        """
        :return:
        :rtype: bytes
        """
        return b''

    def has_settings(self):
        """
        :return:
        :rtype: bool
        """
        return True
Beispiel #21
0
 def test_get_iv2(self):
     kgkm = KgkManager()
     kgkm.iv2 = b"\x02" * 16
     self.assertEqual(b"\x02" * 16, kgkm.get_iv2())
Beispiel #22
0
 def test_get_salt2(self):
     kgkm = KgkManager()
     kgkm.salt2 = b"\x3A" * 32
     self.assertEqual(b"\x3A" * 32, kgkm.get_salt2())
                     help="If not specified it will be prompted.")
 parser.add_argument('-d',
                     '--domain',
                     help="If not specified it will be prompted.")
 parser.add_argument(
     '-q',
     '--quiet',
     action='store_const',
     const=True,
     help="Display only prompts (if necessary) and the plain password")
 args = parser.parse_args()
 if args.master_password:
     master_password = args.master_password
 else:
     master_password = getpass.getpass(prompt='Masterpasswort: ')
 kgk_manager = KgkManager()
 settings_manager, preference_manager = create_settings_manager(kgk_manager)
 try:
     settings_manager.load_settings(kgk_manager, master_password,
                                    args.no_sync)
     if not args.no_sync and (
             args.update_sync_settings
             or not settings_manager.sync_manager.has_settings()):
         settings_manager.sync_manager.ask_for_sync_settings()
         print("Teste die Verbindung...")
         pull_successful, data = settings_manager.sync_manager.pull()
         if pull_successful and len(data) > 0:
             kgk_manager, settings_manager = decrypt_remote_settings(
                 kgk_manager, settings_manager)
         else:
             print("Es konnte keine Verbindung aufgebaut werden.")
Beispiel #24
0
class MainWindow(QWidget, object):
    master_password_label = None
    master_password_edit = None
    domain_label = None
    domain_edit = None
    username_label = None
    username_edit = None
    strength_label = None
    strength_selector = None
    password_label = None
    password = None
    sync_button = None
    clipboard_button = None
    setting = None
    decrypt_kgk_task = None
    settings_window = None

    def __init__(self):
        super(MainWindow, self).__init__()
        self.nam = QNetworkAccessManager()
        self.setWindowIcon(QIcon(os.path.join('icons', 'Logo_rendered_edited.png')))
        layout = QBoxLayout(QBoxLayout.TopToBottom)
        layout.setContentsMargins(0, 0, 0, 0)
        self.preference_manager = PreferenceManager()
        self.kgk_manager = KgkManager()
        self.kgk_manager.set_preference_manager(self.preference_manager)
        self.settings_manager = PasswordSettingsManager(self.preference_manager)
        self.setting_dirty = True
        # Header bar
        header_bar = QFrame()
        header_bar.setStyleSheet(
            "QWidget { background: rgb(40, 40, 40); } " +
            "QToolButton { background: rgb(40, 40, 40); }" +
            "QToolTip { color: rgb(255, 255, 255); background-color: rgb(20, 20, 20); " +
            "border: 1px solid white; }")
        header_bar.setAutoFillBackground(True)
        header_bar.setFixedHeight(45)
        header_bar_layout = QBoxLayout(QBoxLayout.LeftToRight)
        header_bar_layout.addStretch()
        header_bar.setLayout(header_bar_layout)
        layout.addWidget(header_bar)
        self.create_header_bar(header_bar_layout)
        # Widget area
        main_area = QFrame()
        main_layout = QBoxLayout(QBoxLayout.TopToBottom)
        main_area.setLayout(main_layout)
        layout.addWidget(main_area)
        self.create_main_area(main_layout)
        # Window layout
        layout.addStretch()
        main_layout.addStretch()
        self.setLayout(layout)
        settings = QSettings()
        size = settings.value("MainWindow/size")
        if not size:
            size = QSize(350, 450)
        self.resize(size)
        position = settings.value("MainWindow/pos")
        if not position:
            position = QPoint(0, 24)
        self.move(position)
        self.setWindowTitle("c't SESAM")
        self.master_password_edit.setFocus()
        self.show()

    # noinspection PyUnresolvedReferences
    def create_header_bar(self, layout):
        self.sync_button = QToolButton()
        self.sync_button.setIconSize(QSize(30, 30))
        self.sync_button.setIcon(QIcon(os.path.join("icons", "ic_action_sync.png")))
        self.sync_button.setStyleSheet("border: 0px;")
        self.sync_button.setToolTip("Sync")
        self.sync_button.clicked.connect(self.sync_clicked)
        self.sync_button.setVisible(False)
        layout.addWidget(self.sync_button)
        self.clipboard_button = QToolButton()
        self.clipboard_button.setIconSize(QSize(30, 30))
        self.clipboard_button.setIcon(QIcon(os.path.join("icons", "ic_action_copy.png")))
        self.clipboard_button.setStyleSheet("border: 0px;")
        self.clipboard_button.setToolTip("in die Zwischenablage")
        self.clipboard_button.clicked.connect(self.copy_to_clipboard)
        self.clipboard_button.setVisible(False)
        layout.addWidget(self.clipboard_button)

    # noinspection PyUnresolvedReferences
    def create_main_area(self, layout):
        # Master password
        master_password_label = QLabel("&Master-Passwort:")
        self.master_password_edit = QLineEdit()
        self.master_password_edit.setEchoMode(QLineEdit.EchoMode.Password)
        self.master_password_edit.textChanged.connect(self.masterpassword_changed)
        self.master_password_edit.returnPressed.connect(self.move_focus)
        self.master_password_edit.editingFinished.connect(self.masterpassword_entered)
        self.master_password_edit.setMaximumHeight(28)
        master_password_label.setBuddy(self.master_password_edit)
        layout.addWidget(master_password_label)
        layout.addWidget(self.master_password_edit)
        # Domain
        domain_label = QLabel("&Domain:")
        self.domain_edit = QComboBox()
        self.domain_edit.setEditable(True)
        self.domain_edit.textChanged.connect(self.domain_changed)
        self.domain_edit.currentIndexChanged.connect(self.domain_changed)
        self.domain_edit.lineEdit().editingFinished.connect(self.domain_entered)
        self.domain_edit.lineEdit().returnPressed.connect(self.move_focus)
        self.domain_edit.setMaximumHeight(28)
        domain_label.setBuddy(self.domain_edit)
        layout.addWidget(domain_label)
        layout.addWidget(self.domain_edit)
        # Username
        self.username_label = QLabel("&Username:"******"&Passwortstärke:")
        self.strength_label.setVisible(False)
        self.strength_selector = PasswordStrengthSelector()
        self.strength_selector.set_min_length(4)
        self.strength_selector.set_max_length(36)
        self.strength_selector.setMinimumHeight(60)
        self.strength_selector.set_length(12)
        self.strength_selector.set_complexity(6)
        self.strength_selector.strength_changed.connect(self.strength_changed)
        self.strength_selector.setVisible(False)
        self.strength_label.setBuddy(self.strength_selector)
        layout.addWidget(self.strength_label)
        layout.addWidget(self.strength_selector)
        # Password
        self.password_label = QLabel("&Passwort:")
        self.password_label.setVisible(False)
        self.password = QLabel()
        self.password.setTextFormat(Qt.PlainText)
        self.password.setAlignment(Qt.AlignCenter)
        self.password.setFont(QFont("Helvetica", 18, QFont.Bold))
        self.password.setVisible(False)
        self.password_label.setBuddy(self.password)
        layout.addWidget(self.password_label)
        layout.addWidget(self.password)

    def set_masterpassword(self, masterpassword):
        self.master_password_edit.setText(masterpassword)

    def set_domain(self, domain):
        self.domain_edit.lineEdit().setText(domain)

    def closeEvent(self, *args, **kwargs):
        settings = QSettings()
        settings.setValue("MainWindow/size", self.size())
        settings.setValue("MainWindow/pos", self.pos())
        settings.sync()

    def masterpassword_changed(self):
        self.kgk_manager.reset()
        self.decrypt_kgk_task = None
        self.clipboard_button.setVisible(False)
        if len(self.master_password_edit.text()) > 0:
            self.sync_button.setVisible(True)
        else:
            self.sync_button.setVisible(False)

    def masterpassword_entered(self):
        if len(self.master_password_edit.text()) > 0 and not self.decrypt_kgk_task:
            self.kgk_manager.get_kgk_crypter_salt()
            self.decrypt_kgk_task = DecryptKgkTask(
                self.master_password_edit.text(),
                self.preference_manager,
                self.kgk_manager,
                self.settings_manager,
                self.domain_edit)

    def set_visibilities(self):
        if len(self.domain_edit.lineEdit().text()) > 0:
            self.username_label.setVisible(True)
            self.username_edit.setVisible(True)
            self.strength_label.setVisible(True)
            self.strength_selector.setVisible(True)
            self.password_label.setVisible(True)
            self.password.setVisible(True)
        else:
            self.username_label.setVisible(False)
            self.username_edit.setVisible(False)
            self.strength_label.setVisible(False)
            self.strength_selector.setVisible(False)
            self.password_label.setVisible(False)
            self.password.setVisible(False)
            self.clipboard_button.setVisible(False)

    def domain_changed(self):
        self.setting_dirty = True
        self.password.setText("")
        self.clipboard_button.setVisible(False)
        self.set_visibilities()
        if self.kgk_manager.has_kgk() and (not self.decrypt_kgk_task or not self.decrypt_kgk_task.is_running()) and \
           len(self.domain_edit.lineEdit().text()) > 0 and \
           self.domain_edit.lineEdit().text() in self.settings_manager.get_domain_list():
            self.domain_entered()

    def domain_entered(self):
        self.setting_dirty = self.domain_edit.lineEdit().text() not in self.settings_manager.get_domain_list()
        self.setting = self.settings_manager.get_setting(self.domain_edit.lineEdit().text())
        self.username_edit.blockSignals(True)
        self.username_edit.setText(self.setting.get_username())
        self.username_edit.blockSignals(False)
        self.strength_selector.blockSignals(True)
        self.strength_selector.set_length(self.setting.get_length())
        self.strength_selector.set_complexity(self.setting.get_complexity())
        self.strength_selector.set_extra_count(len(self.setting.get_extra_character_set()))
        self.strength_selector.blockSignals(False)
        self.generate_password()

    def move_focus(self):
        line_edits = [self.master_password_edit, self.domain_edit, self.username_edit]
        for i, edit in enumerate(line_edits):
            if edit.hasFocus() and i + 1 < len(line_edits):
                line_edits[i + 1].setFocus()
                return True
        self.generate_button.setFocus()

    def generate_password(self):
        if not self.kgk_manager.has_kgk():
            self.kgk_manager.create_new_kgk()
            self.kgk_manager.create_and_save_new_kgk_block()
        if not self.kgk_manager.kgk_crypter or not self.kgk_manager.salt:
            self.kgk_manager.get_kgk_crypter(self.master_password_edit.text().encode('utf-8'),
                                             self.kgk_manager.get_kgk_crypter_salt())
        if self.setting_dirty:
            self.setting.new_salt()
            self.setting.calculate_template()
        self.settings_manager.set_setting(self.setting)
        if not self.setting.get_legacy_password():
            generator = CtSesam(self.setting.get_domain(),
                                self.setting.get_username(),
                                self.kgk_manager.get_kgk(),
                                self.setting.get_salt(),
                                self.setting.get_iterations())
            password = generator.generate(self.setting)
        else:
            password = self.setting.get_legacy_password()
        self.password.setText(password)
        self.password.setTextInteractionFlags(Qt.TextSelectableByMouse | Qt.TextSelectableByKeyboard)
        self.clipboard_button.setVisible(True)
        self.settings_manager.store_local_settings(self.kgk_manager)
        self.setting_dirty = False

    def copy_to_clipboard(self):
        QApplication.clipboard().setText(self.password.text())

    def username_changed(self):
        if self.setting:
            if self.setting.get_username() != self.username_edit.text():
                self.setting.set_username(self.username_edit.text())
                self.setting_dirty = True
            self.generate_password()

    def strength_changed(self, complexity, length):
        if self.setting:
            if self.setting.get_length() != length:
                self.setting.set_length(length)
                self.setting_dirty = True
            if self.setting.get_complexity() != complexity:
                self.setting.set_complexity(complexity)
                self.setting_dirty = True
            self.generate_password()

    def migrate_local_domains(self, new_kgk_manager):
        for domain in self.settings_manager.get_domain_list():
            setting = self.settings_manager.get_setting(domain)
            generator = CtSesam(setting.get_domain(),
                                setting.get_username(),
                                self.kgk_manager.get_kgk(),
                                setting.get_salt(),
                                setting.get_iterations())
            setting.set_legacy_password(generator.generate(setting))
            self.settings_manager.set_setting(setting)
        self.kgk_manager = new_kgk_manager
        self.settings_manager.store_local_settings(self.kgk_manager)

    # noinspection PyUnresolvedReferences
    def sync_clicked(self):
        self.masterpassword_entered()
        if not self.settings_manager.sync_manager.has_settings():
            self.show_sync_settings()
        else:
            pull_successful, data = self.settings_manager.sync_manager.pull()
            if pull_successful and len(data) > 0:
                remote_kgk_manager = KgkManager()
                remote_kgk_manager.update_from_blob(self.master_password_edit.text().encode('utf-8'), b64decode(data))
                if len(self.preference_manager.get_kgk_block()) == 112 and \
                   remote_kgk_manager.has_kgk() and self.kgk_manager.has_kgk() and \
                   self.kgk_manager.get_kgk() != remote_kgk_manager.get_kgk():
                    if len(self.settings_manager.get_domain_list()) > 0:
                        print("Lokal und auf dem Server gibt es unterschiedliche KGKs. Das ist ein Problem!")
                    self.migrate_local_domains(remote_kgk_manager)
                else:
                    if len(self.preference_manager.get_kgk_block()) != 112:
                        self.kgk_manager = remote_kgk_manager
                        self.kgk_manager.set_preference_manager(self.preference_manager)
                        self.kgk_manager.store_local_kgk_block()
                    self.settings_manager.update_from_export_data(remote_kgk_manager, b64decode(data))
                    self.domain_edit.blockSignals(True)
                    current_domain = self.domain_edit.lineEdit().text()
                    for i in reversed(range(self.domain_edit.count())):
                        self.domain_edit.removeItem(i)
                    self.domain_edit.insertItems(0, self.settings_manager.get_domain_list())
                    self.domain_edit.blockSignals(False)
                    self.domain_edit.setEditText(current_domain)
            self.settings_manager.store_settings(self.kgk_manager)

    # noinspection PyUnresolvedReferences
    def show_sync_settings(self, url=None, username=None, password=None):
        self.settings_window = SettingsWindow(
            self.settings_manager.sync_manager,
            self.nam,
            url=self.settings_manager.sync_manager.server_address,
            username=self.settings_manager.sync_manager.username,
            password=self.settings_manager.sync_manager.password,
            certificate=self.settings_manager.sync_manager.certificate)
        self.settings_window.finished.connect(self.sync_clicked)
Beispiel #25
0
 def test_get_iv2(self):
     kgkm = KgkManager()
     kgkm.iv2 = b"\x02"*16
     self.assertEqual(b"\x02"*16, kgkm.get_iv2())
 def test_get_export_data(self):
     settings = {
         'settings': {
             'unit.test': {
                 'domain': 'unit.test',
                 'extras': '#!"§$%&/()[]{}=-_+*<>;:.',
                 'passwordTemplate': 'xnxoaAxxxx',
                 'iterations': 5000,
                 'notes': 'Nice note!',
                 'salt': 'cGVwcGVy',
                 'cDate': '2011-02-12T11:07:31',
                 'mDate': '2011-02-12T11:07:32'
             },
             'some.domain': {
                 'domain': 'some.domain',
                 'extras': '6478593021',
                 'passwordTemplate': 'xnxoaA',
                 'iterations': 4096,
                 'salt': 'cGVwcGVy',
                 'cDate': '2013-06-17T04:03:41',
                 'mDate': '2014-08-02T10:37:12'
             }
         },
         'synced': []
     }
     salt = os.urandom(32)
     kgk_manager = KgkManager()
     kgk_manager.set_preference_manager(self.preference_manager)
     kgk_manager.create_new_kgk()
     kgk_block = kgk_manager.create_and_save_new_kgk_block(
         Crypter(Crypter.createIvKey(b'xyz', salt, iterations=3)))
     crypter = PasswordSettingsManager.get_settings_crypter(kgk_manager)
     f = open(os.path.expanduser('~/.ctSESAM_test.pws'), 'bw')
     f.write(salt + kgk_block + crypter.encrypt(
         struct.pack('!I', 0) +
         Packer.compress(json.dumps(settings).encode('utf-8'))))
     f.close()
     self.preference_manager.read_file()
     self.manager.load_local_settings(kgk_manager)
     data = b64decode(self.manager.get_export_data(kgk_manager))
     self.assertEqual(b'\x01', data[:1])
     salt = data[1:33]
     kgk_crypter = Crypter(Crypter.createIvKey(b'xyz', salt, iterations=3))
     kgk_manager2 = KgkManager()
     kgk_manager2.set_preference_manager(self.preference_manager)
     kgk_manager2.decrypt_kgk(data[33:145], kgk_crypter)
     settings_crypter = PasswordSettingsManager.get_settings_crypter(
         kgk_manager2)
     self.assertEqual(
         settings['settings'],
         json.loads(
             str(Packer.decompress(settings_crypter.decrypt(data[145:])),
                 encoding='utf-8')))
 def test_update_from_sync(self):
     settings = {
         'settings': {
             'unit.test': {
                 'domain':
                 'unit.test',
                 'passwordTemplate':
                 'xxaAnoxxxxx',
                 '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',
                 'passwordTemplate': 'oanA',
                 'iterations': 4096,
                 'salt': 'cGVwcGVy',
                 'usedCharacters': '6478593021',
                 'cDate': '2013-06-17T04:03:41',
                 'mDate': '2014-08-02T10:37:12'
             }
         },
         'synced': []
     }
     salt = os.urandom(32)
     kgk_manager = KgkManager()
     kgk_manager.set_preference_manager(self.preference_manager)
     kgk_manager.create_new_kgk()
     kgk_block = kgk_manager.create_and_save_new_kgk_block(
         Crypter(Crypter.createIvKey('xyz'.encode('utf-8'), salt)))
     crypter = PasswordSettingsManager.get_settings_crypter(kgk_manager)
     f = open(os.path.expanduser('~/.ctSESAM_test.pws'), 'bw')
     f.write(salt + kgk_block + crypter.encrypt(
         struct.pack('!I', 0) +
         Packer.compress(json.dumps(settings).encode('utf-8'))))
     f.close()
     self.preference_manager.read_file()
     self.manager.sync_manager = MockSyncManager(kgk_manager.get_kgk())
     self.manager.load_settings(kgk_manager, '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())
     file = os.path.expanduser('~/.ctSESAM_test_extra.pws')
     if os.path.isfile(file):
         try:
             import win32con
             import win32api
             win32api.SetFileAttributes(file,
                                        win32con.FILE_ATTRIBUTE_NORMAL)
         except ImportError:
             pass
         os.remove(file)
                     action='store_const', const=True,
                     help="Do not synchronize with a server.")
 parser.add_argument('-u', '--update-sync-settings',
                     action='store_const', const=True,
                     help="Ask for server settings before synchronization.")
 parser.add_argument('--master-password', help="If not specified it will be prompted.")
 parser.add_argument('-d', '--domain', help="If not specified it will be prompted.")
 parser.add_argument('-q', '--quiet',
                     action='store_const', const=True,
                     help="Display only prompts (if necessary) and the plain password")
 args = parser.parse_args()
 if args.master_password:
     master_password = args.master_password
 else:
     master_password = getpass.getpass(prompt='Masterpasswort: ')
 kgk_manager = KgkManager()
 settings_manager, preference_manager = create_settings_manager(kgk_manager)
 kgk_exists = len(preference_manager.get_kgk_block()) == 112
 try:
     settings_manager.load_settings(kgk_manager, master_password, args.no_sync)
     if not args.no_sync and (args.update_sync_settings or not settings_manager.sync_manager.has_settings()):
         settings_manager.sync_manager.ask_for_sync_settings()
         print("Teste die Verbindung...")
         pull_successful, data = settings_manager.sync_manager.pull()
         if pull_successful and len(data) > 0:
             decrypt_remote_settings(kgk_manager, settings_manager)
         else:
             print("Es konnte keine Verbindung aufgebaut werden.")
 except ValueError:
     print("Falsches Masterpasswort. Es wurden keine Einstellungen geladen.")
     sys.exit(1)