def decrypt(path_to_privkey: str, crypt_s: str, choice_privkey: str = None, result_check_choice_privkey: str = None) -> str: """ Decrypts the string with the private key and returns it. :param crypt_s: Input crypto string :param path_to_privkey: Path to privkey.pem file :param choice_privkey: Privkey.pem file if available :param result_check_choice_privkey: Result of checking privkey.pem :return: Output decrypt string or 'error' """ if result_check_choice_privkey == 'ok': privkey = choice_privkey else: with open(path_to_privkey, 'rb') as privfile: keydata_priv = privfile.read() privfile.close() privkey = rsa.PrivateKey.load_pkcs1(keydata_priv, 'PEM') password_bin = crypt_s.encode() password_dec = base64.b64decode(password_bin) try: decrypto = rsa.decrypt(password_dec, privkey) result = decrypto.decode() return result except rsa.pkcs1.DecryptionError as error: show_msg(title='Ошибка', top_text='Ошибка расшифровки закрытого ключа', bottom_text=str(error), window_type='critical', buttons='ok') return 'error'
def show_main_window(self): if self.comboBox_2.currentIndex() == -1: show_msg(title='Ошибка', top_text='Не выбрана база данных', window_type='critical', buttons='ok') else: pwd = self.lineEdit_2.text() wrong_db_info = self.comboBox_2.currentData() wrong_db_info_new = '' for _item_db_info in range(len(wrong_db_info[0])): if wrong_db_info[0][_item_db_info] == '\\': wrong_db_info_new += '/' else: wrong_db_info_new += wrong_db_info[0][_item_db_info] db_info = [wrong_db_info_new, wrong_db_info[1]] conn_start_window = sqlite3.connect(db_info[0]) cur_start_window = conn_start_window.cursor() cur_start_window.execute("PRAGMA key = '{}'".format(pwd)) try: cur_start_window.execute( "SELECT count(*) FROM account_information") result = True cur_start_window.close() except sqlite3.DatabaseError: result = False cur_start_window.close() conn_start_window.close() if result: self._update_new_rsa_bit() conn_start_window, check_result = check_database( conn_start_window, pwd, self.new_rsa_bit) conn_start_window.close() if check_result: conn, cur, rsa_length = database.connect_sql( db_info[0], pwd) self.main_window = main_menu.MainMenu( version=self.version, db_dir=db_info[0], db_name=db_info[1], pwd=pwd, connect=conn, cursor=cur, rsa_length=rsa_length) del pwd self.main_window.show() self.close() else: show_msg(title='Ошибка', top_text='Неправильный пароль', window_type='critical', buttons='ok') self.lineEdit_2.clear()
def start_sync(self): self.label_5.setPixmap(QtGui.QPixmap(":/resource/image/question.ico")) self.label_6.setPixmap(QtGui.QPixmap(":/resource/image/question.ico")) self.label_7.setPixmap(QtGui.QPixmap(":/resource/image/question.ico")) path = self.comboBox.currentData()[0] pwd = self.lineEdit.text() conn_sync = create_and_check_connection(path, pwd) if conn_sync is not None: self.label_5.setPixmap( QtGui.QPixmap(":/resource/image/checkmark.ico")) check_empty = "SELECT * from account_information" rows = execute_read_query(conn_sync, check_empty) if len(rows) != 0: self.label_6.setPixmap( QtGui.QPixmap(":/resource/image/checkmark.ico")) decrypt_result = decrypt(self.path_to_privkey, rows[0][4], self.choice_privkey, self.result_check_choice_privkey) if decrypt_result == 'error': self.label_7.setPixmap( QtGui.QPixmap(":/resource/image/cross.ico")) else: self.label_7.setPixmap( QtGui.QPixmap(":/resource/image/checkmark.ico")) path_to_privkey, path_to_pubkey = \ self.path_to_privkey, self.path_to_pubkey self.sync_db_thread = SyncDBThread(path, pwd, path_to_privkey, path_to_pubkey, self.db_dir) self.sync_db_thread.started.connect(self.spinner_started) self.sync_db_thread.response.connect(self.response_slot) self.acc_count = 0 self.sync_db_thread.finished.connect( lambda: self.spinner_finished(self.acc_count)) self.sync_db_thread.start() else: self.label_6.setPixmap( QtGui.QPixmap(":/resource/image/cross.ico")) show_msg(title='Ошибка', top_text='База данных пустая', window_type='critical', buttons='ok') conn_sync.close() else: self.label_5.setPixmap(QtGui.QPixmap(":/resource/image/cross.ico")) self.lineEdit.clear()
def show_main_window(self): pwd = self.lineEdit.text() wrong_db_info = self.comboBox.currentData() wrong_db_info_new = '' db_info = list() for item_db_info in range(len(wrong_db_info[0])): if wrong_db_info[0][item_db_info] == '\\': wrong_db_info_new += '/' else: wrong_db_info_new += wrong_db_info[0][item_db_info] db_info.append(wrong_db_info_new) db_info.append(wrong_db_info[1]) conn_load = sqlite3.connect(db_info[0]) cur_load = conn_load.cursor() cur_load.execute("PRAGMA key = '{}'".format(pwd)) try: cur_load.execute("SELECT count(*) FROM account_information") cur_load.close() conn_load.close() result = bool(1) except sqlite3.DatabaseError: cur_load.close() conn_load.close() result = bool(0) if result: self._conn, self._cur, self._rsa_length = \ database.connect_sql(db_info[0], pwd) self._db_dir = db_info[0] self._db_name = db_info[1] self._pwd = pwd del pwd self._update_data_loading_db() self._update_sql_connection() self.done(1) else: show_msg(title='Ошибка', top_text='Неправильный пароль', window_type='critical', buttons='ok') self.lineEdit.clear()
def spinner_finished(self): self.spinner.stop() self.label_6.hide() show_msg(title='Успех', top_text='База данных успешно создана' + (' ' * 500), bottom_text='Более подробно по нажатию ' 'кнопки "Show Details..."', detailed_text='- База данных: \n' + os.getcwd() + '\\data\\' + self.lineEdit.text() + '.db' + '\n\n' '- Открытый ключ: \n' + os.getcwd() + '\\data\\' + self.lineEdit.text() + '_pubkey.pem' + '\n\n' '- Закрытый ключ: \n' + os.getcwd() + '\\data\\' + self.lineEdit.text() + '_privkey.pem', window_type='information', buttons='ok') self.lineEdit.clear() self.lineEdit_2.clear() self.lineEdit_3.clear() self.lineEdit.setStyleSheet("border: 1px solid gray") self.lineEdit_2.setStyleSheet("border: 1px solid gray") self.lineEdit_3.setStyleSheet("border: 1px solid gray") self.close()
def execute_read_query(conn_sync: sqlite3.Connection, query: str) -> list: """ Executes the passed sql database query and returns the result. :param conn_sync: sqlite3.Connection object :param query: sql query string :return: list """ result = [] cur_sync = conn_sync.cursor() try: cur_sync.execute(query) result = cur_sync.fetchall() cur_sync.close() return result except Error as e: show_msg(title='Ошибка', top_text=f'Ошибка выполнения запроса: ({e})', window_type='critical', buttons='ok') cur_sync.close() return result
def create_and_check_connection(path: str, pwd: str) \ -> sqlite3.Connection or None: """ Connects to the database and verifies the password. Returns None or a connection object. :param path: path to database file :param pwd: input password for database :return: sqlite3.Connection object / None """ try: conn_sync = sqlite3.connect(path) cur_sync = conn_sync.cursor() cur_sync.execute("PRAGMA key = '{}'".format(pwd)) cur_sync.execute("SELECT name from account_information WHERE id=1") cur_sync.close() return conn_sync except Error: show_msg(title='Ошибка', top_text='Неправильный пароль', window_type='critical', buttons='ok') conn_sync = None return conn_sync
def check_database(connect: sqlite3.Connection, pwd: str, new_rsa_bit: int) \ -> tuple: """ Validates the database and returns a tuple. :param connect: sqlite3.Connection object :param pwd: pragma key password :param new_rsa_bit: rsa key length when creating a new base :return: tuple(sqlite3.Connection, bool) """ cur_check_db = connect.cursor() cur_check_db.execute(f"PRAGMA key = '{pwd}'") try: account_information = cur_check_db.execute(""" SELECT name FROM sqlite_master WHERE type='table' AND name='account_information'""").fetchall() data_change_time = cur_check_db.execute(""" SELECT name FROM sqlite_master WHERE type='table' AND name='data_change_time'""").fetchall() db_information = cur_check_db.execute(""" SELECT name FROM sqlite_master WHERE type='table' AND name='db_information'""").fetchall() if len(data_change_time) == 0: cur_check_db.execute(""" CREATE TABLE IF NOT EXISTS data_change_time( "id" INTEGER NOT NULL UNIQUE REFERENCES account_information (id) ON DELETE CASCADE ON UPDATE CASCADE, "create_account" TEXT NOT NULL, "update_account" TEXT DEFAULT 'NULL', "change_section" TEXT DEFAULT 'NULL', "change_login" TEXT DEFAULT 'NULL', "change_pass" TEXT DEFAULT 'NULL', "change_email" TEXT DEFAULT 'NULL', "change_secret_word" TEXT DEFAULT 'NULL', "change_url" TEXT DEFAULT 'NULL')""") if len(account_information) == 1: id_account_information = cur_check_db.execute(""" SELECT id FROM account_information""").fetchall() now_time = datetime.datetime.now().strftime( '%Y-%m-%d %H:%M:%S') for id_ in id_account_information: cur_check_db.execute( """ INSERT INTO data_change_time (id, create_account) VALUES (?,?)""", (id_[0], now_time)) if len(account_information) == 0: cur_check_db.execute(""" CREATE TABLE IF NOT EXISTS account_information( "id" INTEGER NOT NULL UNIQUE PRIMARY KEY AUTOINCREMENT, "section" TEXT NOT NULL, "name" TEXT NOT NULL, "login" TEXT NOT NULL, "pass" TEXT NOT NULL, "email" TEXT DEFAULT 'NULL', "secret_word" TEXT DEFAULT 'NULL', "url" TEXT DEFAULT 'NULL')""") if len(db_information) == 0: cur_check_db.execute(""" CREATE TABLE IF NOT EXISTS db_information( "name" TEXT NOT NULL, "value" INTEGER NOT NULL)""") cur_check_db.execute( """ INSERT INTO db_information (name, value) VALUES (?, ?)""", ('rsa_bit', new_rsa_bit)) except sqlite3.DatabaseError as error: show_msg(title='Ошибка', top_text='Ошибка проверки базы данных', bottom_text=str(error), window_type='critical', buttons='ok') cur_check_db.close() return connect, False cur_check_db.close() connect.commit() return connect, True
from PyQt5 import QtWidgets, QtCore import py.start_window as start_window from py.show_msg import show_msg class Interface(start_window.StartWindow): def __init__(self): super().__init__() if __name__ == "__main__": lock_file = None try: app = QtWidgets.QApplication(sys.argv) lock_file = QtCore.QLockFile("password_saver.lock") if lock_file.tryLock(): window = Interface() window.show() sys.exit(app.exec_()) else: show_msg(title='Ошибка', top_text='Программа уже запущена', window_type='warning', buttons='ok') finally: lock_file.unlock()
def create_database(self): data_files = os.listdir(path="data") name_db = self.lineEdit.text() pwd = self.lineEdit_2.text() pwd_re = self.lineEdit_3.text() if name_db == '': show_msg(title='Ошибка', top_text='Введите название БД', window_type='critical', buttons='ok') self.lineEdit.setStyleSheet("border: 1px solid red") else: result = False new_name_db = [] for name_db_ in data_files: type_file = name_db_[name_db_.find("."):] if type_file == '.db': new_name_db.append(name_db_[:-3]) for item_db in new_name_db: if name_db == item_db: result = True break if result: show_msg(title='Ошибка', top_text='Такая база данных уже существует', window_type='critical', buttons='ok') self.lineEdit.setStyleSheet("border: 1px solid red") elif pwd == '' and pwd_re == '': show_msg(title='Ошибка', top_text='Заполните поля ввода паролей', window_type='critical', buttons='ok') self.lineEdit_2.setStyleSheet("border: 1px solid red") self.lineEdit_3.setStyleSheet("border: 1px solid red") elif pwd == '': show_msg(title='Ошибка', top_text='Поле введите пароль пустое', window_type='critical', buttons='ok') self.lineEdit_2.setStyleSheet("border: 1px solid red") elif self.validate_password is None or not self.validate_password: show_msg(title='Ошибка', top_text='Неправильный пароль', bottom_text='- 8 символов или больше\n' '- Верхний и нижний регистр\n' '- Минимум 1 цифра\n' '- Не может быть русскими буквами', window_type='critical', buttons='ok') self.lineEdit_2.setStyleSheet("border: 1px solid red") self.lineEdit_3.setStyleSheet("border: 1px solid red") elif pwd_re == '': show_msg(title='Ошибка', top_text='Поле подтвердите пароль пустое', window_type='critical', buttons='ok') self.lineEdit_3.setStyleSheet("border: 1px solid red") elif pwd != pwd_re: show_msg(title='Ошибка', top_text='Пароли не совпадают', window_type='critical', buttons='ok') self.lineEdit_3.setStyleSheet("border: 1px solid red") elif pwd == pwd_re: self._new_rsa_bit = self.comboBox.currentData() conn_db_creation = sqlite3.connect(r'data/' + name_db + '.db') cur_db_creation = conn_db_creation.cursor() cur_db_creation.execute("PRAGMA key = '{}'".format(pwd)) cur_db_creation.execute("PRAGMA foreign_keys = ON") cur_db_creation.execute(""" CREATE TABLE IF NOT EXISTS account_information( "id" INTEGER NOT NULL UNIQUE PRIMARY KEY AUTOINCREMENT, "section" TEXT NOT NULL, "name" TEXT NOT NULL, "login" TEXT NOT NULL, "pass" TEXT NOT NULL, "email" TEXT DEFAULT 'NULL', "secret_word" TEXT DEFAULT 'NULL', "url" TEXT DEFAULT 'NULL')""") cur_db_creation.execute(""" CREATE TABLE IF NOT EXISTS db_information( "name" TEXT NOT NULL, "value" INTEGER NOT NULL)""") cur_db_creation.execute(""" CREATE TABLE IF NOT EXISTS data_change_time( "id" INTEGER NOT NULL UNIQUE REFERENCES account_information (id) ON DELETE CASCADE ON UPDATE CASCADE, "create_account" TEXT NOT NULL, "update_account" TEXT DEFAULT 'NULL', "change_section" TEXT DEFAULT 'NULL', "change_login" TEXT DEFAULT 'NULL', "change_pass" TEXT DEFAULT 'NULL', "change_email" TEXT DEFAULT 'NULL', "change_secret_word" TEXT DEFAULT 'NULL', "change_url" TEXT DEFAULT 'NULL')""") cur_db_creation.execute(""" INSERT INTO db_information (name, value) VALUES ('rsa_bit', {})""".format(self._new_rsa_bit)) conn_db_creation.commit() cur_db_creation.close() conn_db_creation.close() self.create_keys = ThreadCreateKeys( name_db=self.lineEdit.text(), new_rsa_bit=self._new_rsa_bit) self.create_keys.started.connect(self.spinner_started) self.create_keys.finished.connect(self.spinner_finished) self.create_keys.start() else: show_msg(title='Ошибка', top_text='Неизвестная ошибка', bottom_text='Обратитесь к разработчику', window_type='critical', buttons='ok') self.lineEdit_3.setStyleSheet("border: 1px solid red")
def add_data(self): section = None if self.lineEdit_7.isVisible(): section = self.lineEdit_7.text() elif self.comboBox.isVisible(): section = self.comboBox.currentText() name = self.lineEdit.text() login = self.lineEdit_2.text() entered_password = self.lineEdit_3.text() password_bin = entered_password.encode() if self.choice_pubkey is not None: pubkey = self.choice_pubkey else: with open('{}_pubkey.pem'.format(self.db_dir[:-3]), 'rb') \ as pubfile: keydata_pub = pubfile.read() pubfile.close() pubkey = rsa.PublicKey.load_pkcs1(keydata_pub, 'PEM') crypto_password = rsa.encrypt(password_bin, pubkey) password = (base64.b64encode(crypto_password)).decode() email = self.lineEdit_4.text() entered_secret_word = self.lineEdit_5.text() if entered_secret_word == '': entered_secret_word = 'None' secret_word_bin = entered_secret_word.encode() crypto_secret = rsa.encrypt(secret_word_bin, pubkey) secret_word = (base64.b64encode(crypto_secret)).decode() url = self.lineEdit_6.text() if section == '': show_msg(title='Ошибка', top_text='Введите раздел', window_type='critical', buttons='ok') self.lineEdit_7.setStyleSheet("border: 1px solid red;") elif name == '': show_msg(title='Ошибка', top_text='Введите название', window_type='critical', buttons='ok') self.lineEdit.setStyleSheet("border: 1px solid red;") elif login == '': show_msg(title='Ошибка', top_text='Введите логин', window_type='critical', buttons='ok') self.lineEdit_2.setStyleSheet("border: 1px solid red;") elif entered_password == '': show_msg(title='Ошибка', top_text='Введите пароль', window_type='critical', buttons='ok') self.lineEdit_3.setStyleSheet("border: 1px solid red;") else: if email == '': email = 'None' if entered_secret_word == '': secret_word = 'None' if url == '': url = 'None' if self.lines == 0: new_id = 1 self.cur.execute( """ INSERT INTO account_information (ID, section, name, login, pass, email, secret_word, url) VALUES (?, ?, ?, ?, ?, ?, ?, ?)""", (new_id, section, name, login, password, email, secret_word, url)) self.cur.execute( """ INSERT INTO data_change_time (id, create_account) VALUES (?, ?)""", (new_id, datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'))) if self.checkBox.isChecked(): self._buffer = QtWidgets.QApplication.clipboard() self._buffer.setText(entered_password) self.checkbox_copy_buffer = 1 self.close() else: self.cur.execute(""" SELECT ID FROM account_information WHERE name='{}' and login='******' """.format(name, login)) exist_account = self.cur.fetchone() if exist_account is not None: show_msg(title='Ошибка', top_text='Такой аккаунт уже существует', window_type='critical', buttons='ok') else: [max_id], = self.cur.execute(""" SELECT ID FROM account_information ORDER BY ID DESC LIMIT 1""") new_id = max_id + 1 self.cur.execute( """ INSERT INTO account_information (id, section, name, login, pass, email, secret_word, url) VALUES (?, ?, ?, ?, ?, ?, ?, ?)""", (new_id, section, name, login, password, email, secret_word, url)) self.cur.execute( """ INSERT INTO data_change_time (id, create_account) VALUES (?, ?)""", (new_id, datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S') )) if self.checkBox.isChecked(): self._buffer = QtWidgets.QApplication.clipboard() self._buffer.setText(entered_password) self.checkbox_copy_buffer = 1 self.close()