diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..8ab7b28460ad110d0adae15737934ee31c8c3ce0 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,7 @@ +cryptography==41.0.1 +customtkinter==5.1.2 +ecdsa==0.18.0 +Pillow==9.5.0 +Pillow==9.5.0 +psycopg2_binary==2.9.5 +yadisk==1.3.3 diff --git a/src/base_api.py b/src/base_api.py new file mode 100644 index 0000000000000000000000000000000000000000..328de599559fa7237ab130b2bbbda3e9781afd91 --- /dev/null +++ b/src/base_api.py @@ -0,0 +1,100 @@ +import psycopg2 + +#Параметры +host_ = "localhost" +port_ = 5432 +user_ = "postgres" +password_ = "" +database_="postgres" + +def create_database(): + try: + connection = psycopg2.connect( + host=host_, + port=port_, + user=user_, + password=password_, + database=database_ + ) + except (Exception, psycopg2.Error) as error: + print("Can't connect to DB: ", error) + return + + with connection.cursor() as cursor: + cursor.execute(""" + CREATE TABLE IF NOT EXISTS my_users( + nick_name VARCHAR(255) NOT NULL PRIMARY KEY, + first_name VARCHAR(255) NOT NULL, + last_name VARCHAR(255) NOT NULL, + password_user VARCHAR(255) NOT NULL + ); + """) + connection.commit() + print('[SERVER] table created!') + connection.close() + + +def insert_into_users(nick_name, first_name, last_name, password_user): + try: + connection = psycopg2.connect( + host=host_, + port=port_, + user=user_, + password=password_, + database=database_ + ) + except (Exception, psycopg2.Error) as error: + print("Can't connect to DB: ", error) + + with connection.cursor() as cursor: + cursor.execute(""" + INSERT INTO my_users + VALUES (%s, %s, %s, %s); """, + (nick_name, first_name, last_name, password_user)) + connection.commit() + connection.close() + +def checking_uniqueness(nick_name): + try: + connection = psycopg2.connect( + host="195.19.32.74", + port=port_, + user=user_, + password=password_, + database=database_ + ) + except (Exception, psycopg2.Error) as error: + print("Can't connect to DB: ", error) + with connection.cursor() as cursor: + cursor.execute(f""" + SELECT 1 FROM my_users WHERE nick_name = '{nick_name}' """) + + res_= cursor.fetchone() + connection.close() + return res_ + + +def user_verification(nick_name, password_user): + print(nick_name, password_user) + try: + connection = psycopg2.connect( + host="195.19.32.74", + port=port_, + user=user_, + password=password_, + database=database_ + ) + except (Exception, psycopg2.Error) as error: + print("Can't connect to DB: ", error) + with connection.cursor() as cursor: + try: + cursor.execute(f""" + SELECT 1 FROM my_users WHERE nick_name = '{nick_name}' AND password_user = '{password_user}' """ + ) + res_ = cursor.fetchone() + connection.close() + return res_ + except (Exception, psycopg2.Error) as error: + print("Can't select from database:", error) + + diff --git a/src/client.py b/src/client.py new file mode 100644 index 0000000000000000000000000000000000000000..e65e44ce699ffc088e0ebfa0f8bb781ac1a2f134 --- /dev/null +++ b/src/client.py @@ -0,0 +1,103 @@ +import socket +from encoding import useKey +from time import sleep +import customtkinter as ctk +from os.path import basename + +buff_size = 1024 + + + +def sendFile(client, file_name): + try: + file = open(file_name, 'rb') + except: + print(f"[CLIENT] Can't open sended file: {file_name}") + data = file.read(buff_size) + while data: + client.send((data)) + data = file.read(buff_size) + + client.send(b'') + print('[CLIENT] msg shared!') + +def recieveFile(client, file_name): + file = open(file_name, 'wb') + data = client.recv(buff_size) + while data[-5:] != b'': + file.write(data) + data = client.recv(buff_size) + + if(len(data) > 5): + file.write(data[0:-5]) + + + print("[CLIENT] transfered succesfully") + + file.close() + + +def ServerMeet(socket_, command : str): + print(f'[CLIENT] {command}') + + cmd_ = command[0:command.find(' ')] + if cmd_ == 'send_file': + socket_.send( (cmd_+ ' ' + basename(command[command.find(' ')+1:])).encode() ) + file_name = command[command.find(' ')+1:] + sendFile(socket_, file_name) + elif cmd_ == 'use_key': + socket_.send(command.encode()) + with open(command[command.find(' ')+1:], 'rb') as f: + data = f.read(1024) + socket_.send(data) + elif cmd_ == 'use_key_pub': + socket_.send(command.encode()) + with open(command[command.find(' ')+1:], 'rb') as f: + data = f.read(1024) + socket_.send(data) + elif cmd_ == 'encode_file': + socket_.send(command.encode()) + recieveFile(socket_, command[command.find(' ')+1:]+'.sig') + + pub_k = socket_.recv(buff_size) + with open(command[command.find(' ')+1:]+'.pem', 'wb') as f: + f.write(pub_k) + elif cmd_ == 'verify_sign': + socket_.send(command.encode()) + return socket_.recv(buff_size).decode() + elif cmd_ == 'send_encode_file': #send_encode_file + socket_.send(command.encode()) + file_name = command[command.find(' ')+1:] + sendFile(socket_, file_name) + recieveFile(socket_, command[command.find(' ')+1:]+'.sig') + + elif cmd_ == 'rec_file_cloud': + socket_.send(command.encode()) + file_name = command[command.find(' ')+1:] + recieveFile(socket_, file_name) + + elif cmd_ == 'upload_file': + socket_.send((cmd_+ ' ' + basename(command[command.find(' ')+1:])).encode()) + file_name = command[command.find(' ')+1:] + sendFile(socket_, file_name) + elif cmd_ == 'reg': + socket_.send(command.encode()) + return socket_.recv(buff_size).decode() + elif cmd_ == 'login': + socket_.send(command.encode()) + return socket_.recv(buff_size).decode() + elif cmd_ == 'log_unique': + socket_.send(command.encode()) + return socket_.recv(buff_size).decode() + elif command == 'dwnld_files': + socket_.send(command.encode()) + s = socket_.recv(buff_size).decode().split('|') + return s + elif command == 'exit': + try: + socket_.send(command.encode()) + socket_.close() + except: + pass + return None + \ No newline at end of file diff --git a/src/encoding.py b/src/encoding.py new file mode 100644 index 0000000000000000000000000000000000000000..f5cae76007d49398b9dc65f7c9f4574446a5772b --- /dev/null +++ b/src/encoding.py @@ -0,0 +1,84 @@ +from ecdsa import SigningKey, NIST256p, VerifyingKey +from ecdsa import BadSignatureError +from ecdsa.util import sigdecode_der, sigencode_der +from zlib import crc32 +from hashlib import sha256 + +def useKey(path): + try: + with open(path, 'rb') as f: + return SigningKey.from_pem(f.read()) + except: + print(f"Failed can't use key in {path}") + return None + +def UsePub(path): + try: + with open(path, 'rb') as f: + return VerifyingKey.from_pem(f.read()) + except: + print(f"Failed can't use key in {path}") + return None + +def encrypt_str(s: bytes, key): + res = "" + for c in s: + #print(c) + #1114111 - max value + res += chr((c + key) % 1114111) + + return res.encode() + +def decrypt_str(s:bytes, key): + res = "" + for c in s: + res += chr(((c - key) % 1114111 + 1114111) % 1114111) + + return res.encode() + + + +def EncodeFile(path, private_key): + if private_key == None: + print("Can't make sig, choose private_key") + return None + + #чтение файла + try: + with open(path, 'rb') as file: + data = sha256(file.read()).hexdigest().encode() + # data = b'\n\x00\x00\x00\x00' + except: + print(f'[SERVER] Cant open file {path}') + try: + + sig = private_key.sign_deterministic(data, sigencode=sigencode_der, hashfunc=sha256) + #запись подписи в файл + with open(path+'.sig', 'wb') as siq_file: + siq_file.write(sig) + print(f'[CLIENT] File: {path} signigied') + except: + print("Can't make sig") + +def VerifyFile(path_sig, path_source, public_key): + if public_key == None: + print("Can't verify sig without public_key") + return None + try: + with open(path_sig, 'rb') as f: + sig = f.read() + except: + print("Can't open sig file") + try: + with open(path_source, 'rb') as file: + data = sha256(file.read()).hexdigest().encode() + except: + print("Can't open source file") + try: + res = public_key.verify(sig, data, hashfunc=sha256, sigdecode=sigdecode_der) + return res + assert res + print('[CLIENT] Valid sign') + except BadSignatureError: + print('[CLIENT] Invalid sign') + diff --git a/src/gui_auth.py b/src/gui_auth.py new file mode 100644 index 0000000000000000000000000000000000000000..e32af8cd6d25b1895fd172c95c5db919854e27df --- /dev/null +++ b/src/gui_auth.py @@ -0,0 +1,188 @@ +import tkinter + +from tkinter import messagebox +import customtkinter +from PIL import Image +from encoding import useKey, EncodeFile, VerifyFile, UsePub +from os import getcwd +from os.path import basename +import socket +from client import sendFile, recieveFile, ServerMeet +from hashlib import sha256 +#параметры +host = 'localhost' +port = 1234 +buff_size = 1024 + + +class Regist(customtkinter.CTk): + def __init__(self): + super().__init__() + self.salt = 'salt' + self.logd = 0 + self.con = 0 + self.cur_dir = getcwd() + self.resizable(1, 1) + + self.client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + self.try_connect() + + self.geometry('450x400+700+200') + self.title('Login page') + + self.frame1 = customtkinter.CTkFrame(self, width=600) + self.frame1.grid(row=0, column=0, padx=20, pady=20) + + self.l1 = customtkinter.CTkLabel(master=self.frame1, text="Начнём работу!", font=('Century Gothic', 15)) + self.l1.grid(row=0, column=0, padx=10) + + self.login = customtkinter.CTkEntry(master=self.frame1, + placeholder_text="Логин", + width=120, + height=25, + border_width=2, + corner_radius=10, ) + self.login.grid(row=1, column=0) + + self.password = customtkinter.CTkEntry(master=self.frame1, + placeholder_text="Пароль", + width=120, + height=25, + border_width=2, + corner_radius=10, show = '*') + self.password.grid(row=2, column=0, pady=10) + + self.button1 = customtkinter.CTkButton(master=self.frame1, text='Войти', fg_color='#C57A44', cursor='hand2', width = 20, command=self.login_button) + self.button1.grid(row=3, column=0, pady=10) + + self.button2 = customtkinter.CTkButton(master=self.frame1, fg_color='#C57A44', text='Зарегистрироваться', cursor='hand2', + command=self.register_page) + self.button2.grid(row=4, column=0, padx=10, pady=10) + + self.columnconfigure(0, weight=1) + self.rowconfigure(0, weight=1) + + self.frame1.rowconfigure(0, weight=1) + self.frame1.columnconfigure(0, weight=1) + + + + def login_button(self): + global login, pas + salted_pas = sha256((self.password.get() + self.salt).encode()).hexdigest() + if self.con == 0: + self.try_connect() + if self.con == 0: + messagebox.showerror('Ошибка', 'Нет подключения!') + #print(f"Can't connect to: {host, port}") + return + + res = (ServerMeet(self.client, f'login {self.login.get()} {salted_pas}')) + if self.login.get() == '' or self.password.get() == '': + messagebox.showerror('Ошибка', 'Не все поля заполнены') + elif res == 'None': + messagebox.showerror('Ошибка', 'Неверный логин или пароль') + else: + messagebox.showinfo('Добро пожаловать', 'Выполняется вход') + self.logd = 1 + self.destroy() + ServerMeet(self.client, f'exit') + def __del__(self): + try: + ServerMeet(self.client, f'exit') + self.destroy() + except: + pass + + + def register_page(self): + self.frame1.grid_remove() + self.frame2 = customtkinter.CTkFrame(self, corner_radius=10) + self.frame2.grid(row=0, column=0, padx=20, pady=20) + + self.l1 = customtkinter.CTkLabel(master=self.frame2, text="Регистрация в системе ", font=('Century Gothic', 15)) + self.l1.grid(row=0, column=0, sticky='e', padx=20, pady=10) + + self.first_name2 = customtkinter.CTkEntry(master=self.frame2, + placeholder_text="Имя", + width=120, + height=25, + border_width=2, + corner_radius=10, ) + self.first_name2.grid(row=1, column=0, padx=5, pady=10) + self.last_name2 = customtkinter.CTkEntry(master=self.frame2, + placeholder_text="Фамилия", + width=120, + height=25, + border_width=2, + corner_radius=10, ) + self.last_name2.grid(row=2, column=0, padx=5, pady=10) + + self.login2 = customtkinter.CTkEntry(master=self.frame2, + placeholder_text="Логин", + width=120, + height=25, + border_width=2, + corner_radius=10, ) + self.login2.grid(row=3, column=0, padx=5, pady=10) + + self.password2 = customtkinter.CTkEntry(master=self.frame2, + placeholder_text="Пароль", + width=120, + height=25, + border_width=2, + corner_radius=10, show = '*') + self.password2.grid(row=4, column=0, padx=5, pady=10) + + self.button5 = customtkinter.CTkButton(master=self.frame2, text='Зарегистрироваться', fg_color='#C57A44', cursor='hand2', + command=self.register_button) + self.button5.grid(row=5, column=0, pady=10) + + self.arleadyaccount = customtkinter.CTkLabel(master=self.frame2, text='Уже есть аккаунт?') + self.arleadyaccount.grid(row=6, column=0) + + self.loginButton = customtkinter.CTkButton(master=self.frame2, text='Войти', fg_color='#C57A44', command=self.login_page) + self.loginButton.grid(row=7, column=0, pady=10) + + self.columnconfigure(0, weight=1) + self.rowconfigure(0, weight=1) + + self.frame2.rowconfigure(0, weight=1) + self.frame2.columnconfigure(0, weight=1) + def login_page(self): + self.frame2.grid_remove() + self.frame1.grid(row=0, column=0, padx=20, pady=20) + def register_button(self): + if self.con == 0: + self.try_connect() + if self.con == 0: + messagebox.showerror('Ошибка', 'Нет подключения!') + return + + if self.login2.get() == '' or self.password2.get() == '': + messagebox.showerror('Ошибка', 'Не все поля заполнены') + + elif ServerMeet(self.client, f'log_unique {self.login2.get()}') != 'None': + messagebox.showerror('Ошибка', 'Такой логин уже существует') + else: + salted_pas = sha256((self.password2.get() + self.salt).encode()).hexdigest() + res = ServerMeet(self.client, f'reg {self.login2.get()} {self.first_name2.get()} {self.last_name2.get()} {salted_pas}') + if res == 'ex_1': + messagebox.showerror('Ошибка', 'Повторите попытку') + else: + messagebox.showinfo('Успех', 'Регистрация прошла успешно') + + self.frame2.grid_remove() + self.frame1.grid(row=0, column=0, padx=20, pady=20) + def try_connect(self): + try: + self.client.connect((host, port)) + self.con = 1 + except: + pass + + + +# if __name__ == '__main__': +# app = Regist() +# app.mainloop() diff --git a/src/images/armadillo (1).png b/src/images/armadillo (1).png new file mode 100644 index 0000000000000000000000000000000000000000..6a6c51776d6b8c258ba6077ef6b5b7d55e74df75 Binary files /dev/null and b/src/images/armadillo (1).png differ diff --git a/src/images/check.png b/src/images/check.png new file mode 100644 index 0000000000000000000000000000000000000000..840eabf613c2ff526ee2f7d00c14a09a20dd09da Binary files /dev/null and b/src/images/check.png differ diff --git a/src/images/cloud.png b/src/images/cloud.png new file mode 100644 index 0000000000000000000000000000000000000000..bddc8b3af2ff7f9b01b64eade11c093ee32b7c9f Binary files /dev/null and b/src/images/cloud.png differ diff --git a/src/images/cross.png b/src/images/cross.png new file mode 100644 index 0000000000000000000000000000000000000000..8a40e0437571f1e44c70e5dcdca9e73b41838940 Binary files /dev/null and b/src/images/cross.png differ diff --git a/src/images/download.png b/src/images/download.png new file mode 100644 index 0000000000000000000000000000000000000000..89f0bad4ebbc8fa4b3f02507b564c9460bd7f1f2 Binary files /dev/null and b/src/images/download.png differ diff --git a/src/images/key.png b/src/images/key.png new file mode 100644 index 0000000000000000000000000000000000000000..5762e591c7e1edd02a835b925936344c7e2b04c4 Binary files /dev/null and b/src/images/key.png differ diff --git a/src/images/key2.png b/src/images/key2.png new file mode 100644 index 0000000000000000000000000000000000000000..56e31ef7b4fd9171da033b45d1f84d4c61fd4466 Binary files /dev/null and b/src/images/key2.png differ diff --git a/src/images/table.png b/src/images/table.png new file mode 100644 index 0000000000000000000000000000000000000000..a97818c95eee69896355452dfad21d96995432b9 Binary files /dev/null and b/src/images/table.png differ diff --git a/src/images/verify.png b/src/images/verify.png new file mode 100644 index 0000000000000000000000000000000000000000..f60f53ff7c7f055eb0248383577a8adac2a130ba Binary files /dev/null and b/src/images/verify.png differ diff --git a/src/key_gen.py b/src/key_gen.py new file mode 100644 index 0000000000000000000000000000000000000000..05cb82e97b03a638e318f997942d1d6cf9b1c1d6 --- /dev/null +++ b/src/key_gen.py @@ -0,0 +1,7 @@ +from ecdsa import SigningKey, NIST256p + +key = SigningKey.generate(curve=NIST256p) + +s = input('key name:') +with open(s+".pem", "wb") as f: + f.write(key.to_pem(format="pkcs8")) \ No newline at end of file diff --git a/src/server.py b/src/server.py new file mode 100644 index 0000000000000000000000000000000000000000..5d5248c24d20c864c5669cc35319b133acda9291 --- /dev/null +++ b/src/server.py @@ -0,0 +1,218 @@ +import socket +import threading +from time import sleep +from encoding import EncodeFile, VerifyFile, encrypt_str, decrypt_str +from ecdsa import SigningKey, VerifyingKey +from os import getcwd, mkdir +from os.path import join +import yadisk +from base_api import * +from random import randint + +#Параметры +host = 'localhost'# +port = 1234 +#Токен yandex диска +y = yadisk.YaDisk(token='') +storage_dir = getcwd() + +buff_size = 1024 +private_key, public_key = None, None +name = None +users_now = 0 + +def recieveFile(client, file_name): + try: + file = open(join(storage_dir, name, file_name), 'wb') + except: + #print(f'[SERVER] can"t open {join(storage_dir, login,file_name)}') + return + data = client.recv(buff_size) + while data[-5:] != b'': + file.write(data) + data = client.recv(buff_size) + + if(len(data) > 5): + file.write(data[0:-5]) + + + print("[SERVER] transfered succesfully") + + file.close() + + +def sendFile(socket_, file_name): + #socket_.send(file_name.encode()) + #print(file_name) + try: + file = open(file_name, 'rb') + except: + print(f'Cant open: {file_name}') + data = file.read(buff_size) + while data: + socket_.send((data)) + data = file.read(buff_size) + socket_.send(b'') + print('[SERVER] msg shared!') + +def sendFile_(socket_, file_name): + file = open(file_name, 'rb') + data = file.read() + while data: + socket_.send((data)) + data = file.read(buff_size) + socket_.send(b'') + print('[SERVER] msg shared!') + +# +def uploadDisk(file_name): + y.upload(join(storage_dir, name, file_name), f'test/{name}/{file_name}') + + + +def recieveData(client): + global name, private_key, public_key, users_now, union_key + while True: + try: + command = client.recv(buff_size).decode() + cmd_ = command[0:command.find(' ')] + print(f'[SERVER] rec command from [{name}]: {command}') + if cmd_ == 'send_file': # file: client -> server + recieveFile(client, command[command.find(' ')+1:]) + elif cmd_ == 'use_key': #use_file + f = client.recv(buff_size) + private_key = SigningKey.from_pem(f) + elif cmd_ == 'use_key_pub': + f = client.recv(buff_size) + #print(f) + public_key = VerifyingKey.from_pem(f) + elif cmd_ == 'encode_file':#encode_file + EncodeFile(join(storage_dir, name, command[command.find(' ')+1:]).replace('\\', '/'), private_key) + print(join(storage_dir, name, command[command.find(' ')+1:]).replace('\\', '/')) + sendFile_(client, join(storage_dir, name, command[command.find(' ')+1:]+'.sig').replace('\\', '/')) + pub_ = private_key.verifying_key + #print(pub_.to_pem()) + sleep(1) + client.send(pub_.to_pem()) + + elif cmd_ == 'verify_sign':#verify_sign + args = command[command.find(' ')+1:] + res = (VerifyFile(join(storage_dir, name, args[0:args.find('.sig ')+4]), join(storage_dir, name, args[args.find('.sig ')+5:]), public_key)) + print(str(res)) + client.send(str(res).encode()) + elif cmd_ == 'send_encode_file': + recieveFile(client, command[command.find(' ')+1:]) + EncodeFile(command[command.find(' ')+1:], private_key) + + elif cmd_ == 'send_encode_file_with_key': + recieveFile(client, command[command.find(' ')+1:]) + f = client.recv(buff_size) + private_key = SigningKey.from_pem(f) + verify_key = private_key.verifying_key + print('Here') + EncodeFile(command[command.find(' ')+1:], private_key) + client.send((command[command.find(' ')+1:]+".sig").encode()) + sendFile(client, command[command.find(' ')+1:]+'.sig') + print(f'[SERVER] file {command[command.find(" ")+1:]} signed and sended back') + + elif cmd_ == 'rec_file_cloud': + file_name = command[command.find(' ')+1:] + y.download(f'/test/{name}/{file_name}', join(storage_dir, name, file_name)) + sendFile(client, join(storage_dir, name, file_name)) + elif cmd_ == 'reg': + try: + s = command.split(' ') + try: + insert_into_users(s[1], s[2], s[3], s[4]) + client.send((str('norm')).encode()) + except: + client.send((str('ex_1')).encode()) + continue + name = s[1] + mkdir(join(storage_dir, s[1])) + y.mkdir(f'/test/{name}') + print(f"[SERVER] Reg'd user: {s[1]}") + except: + print(f"[SERVER] User already exist: {s[1]}") + elif cmd_ == 'login': + s = command.split(' ') + name = s[1] + print(f'[SERVER] Entered in app: {name}') + res = user_verification(s[1],s[2]) + client.send((str(res)).encode()) + + elif cmd_ == 'log_unique': + s = command.split(' ') + res = checking_uniqueness(s[1]) + client.send((str(res)).encode()) + #print(name) + elif cmd_ == 'upload_file': + recieveFile(client, command[command.find(' ')+1:]) + uploadDisk(command[command.find(' ')+1:]) + + elif command == 'dwnld_files': + files = '|'.join([(x['name']+' '+ '%.2f' % (x['size']/1024)) for x in (y.listdir(f'/test/{name}')) ]) + + print(files) + if files == '': + files = ' ' + client.send(files.encode()) + print(f'[SERVER] files in disk shared for {name}') + elif command == 'exit': + print(f'[SERVER] client [ {name} ] disconnected') + users_now -=1 + client.close() + break + else: + print('[SERVER] Unknown command') + except: + pass + + + + + + +socket_ = socket.socket(socket.AF_INET, socket.SOCK_STREAM) +socket_.bind((host, port)) +socket_.listen(16) +print(f"[Server listening...]") +#print(getcwd()) + +def recieve(): + global users_now + while True: + try: + conn, addr = socket_.accept() + users_now += 1 + #регает новые подключения + print(f"[New connection]: {addr}") + print(f'[SERVER] active users {users_now}') + #print(f'Current connections: {connections}') + #sendFile(socket_, '1.png') + thread = threading.Thread(target=recieveData, args=(conn,)) + thread.start() + except: + print("Can't connect") + ''' + file_name = conn.recv(buff_size).decode() + print(file_name) + + file = open(file_name, 'wb') + + data = conn.recv(buff_size) + while data: + file.write(data) + data = conn.recv(buff_size) + + print("[SERVER] transfered succesfully") + ''' + + + + + conn.close() + + +recieve() +socket_.close() \ No newline at end of file diff --git a/src/signify.py b/src/signify.py new file mode 100644 index 0000000000000000000000000000000000000000..d80be91fb2ea4aaeb881b09a846ba31a655d7475 --- /dev/null +++ b/src/signify.py @@ -0,0 +1,307 @@ +import tkinter as tk +import customtkinter as ctk +from PIL import Image +from encoding import useKey, EncodeFile, VerifyFile, UsePub +from os import getcwd +from os.path import basename, getsize +import socket +from client import sendFile, recieveFile, ServerMeet +from gui_auth import * +from time import sleep +from random import randint +from tkinter import messagebox + +#Параметры +host = 'localhost' +port = 1234 +buff_size = 1024 + + +class App(ctk.CTk): + def __init__(self): + super().__init__() + + + + self.cur_dir = getcwd() + + self.resizable(1,1) + + self.private_key = None + self.public_key = None + + self.encode_file_path = None + + self.verify_file_path = None + self.source_file_path = None + + self.client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + try: + self.client.connect((host, port)) + except: + print(f"Can't connect to: {host, port}") + # recieveFile(self.client, 'ar.png') + + #self.client.send('login ilya'.encode()) + self.geometry('900x600+290+115') + self.title('signify') + self.list_dwnld_files = (ServerMeet(self.client, 'dwnld_files')) + + + #set grid 1 row, 2 columns + self.grid_rowconfigure(0, weight=1) + self.grid_columnconfigure(1, weight=1) + #self.grid_columnconfigure(2, weight=1) + self.columnconfigure(0, minsize=230) + self.columnconfigure(1, weight=1, minsize=700) + #self.rowconfigure(0, minsize=600) + + #load images + logo_image = ctk.CTkImage(Image.open('images/armadillo (1).png'), size = (60, 60)) + add_image = ctk.CTkImage(Image.open('images/cloud.png'), size = (30, 30)) + #folder_image = ctk.CTkImage(Image.open('folder.png'), size = (30, 30)) + encode_image = ctk.CTkImage(Image.open('images/key.png'), size = (30, 30)) + verify_image = ctk.CTkImage(Image.open('images/verify.png'), size = (30, 30)) + download_image = ctk.CTkImage(Image.open('images/download.png'), size = (30, 30)) + self.lablekey_image = ctk.CTkImage(Image.open('images/key2.png'), size = (400, 400)) + self.lablecloud_image = ctk.CTkImage(Image.open('images/cloud.png'), size = (400, 400)) + self.lableverify_image1 = ctk.CTkImage(Image.open('images/cross.png'), size = (400, 400)) + self.lableverify_image2 = ctk.CTkImage(Image.open('images/verify.png'), size = (400, 400)) + self.table_image = ctk.CTkImage(Image.open('images/table.png'), size = (512, 512)) + self.micro_load = ctk.CTkImage(Image.open('images/download.png'), size = (20, 20)) + + #frame + self.navigation_frame = ctk.CTkFrame(self, corner_radius=0, width=400) + self.navigation_frame.grid(row=0, column=0, sticky='nsew', padx=10, pady=10) + # self.navigation_frame.grid_rowconfigure(2, weight=1) + + #lable + self.lable_logo = ctk.CTkLabel(self.navigation_frame, corner_radius=0, image=logo_image, font=ctk.CTkFont(size=20, weight="bold"), compound='left', text='signify ') + self.lable_logo.grid(row=0, column = 0, padx = 20, pady = 15) + + + #buttons + self.add_button = ctk.CTkButton(self.navigation_frame, text=' Загрузить', image=add_image, compound='top', height=40, fg_color='#C57A44', command=self.upload_cloud, font=('Century Gothic', 15)) + self.add_button.grid(row=1, column = 0, sticky = 'nsew', padx=10, pady=5) + + self.download_button = ctk.CTkButton(self.navigation_frame, text=' Скачать', image=download_image, compound='top', height=40, fg_color='#C57A44', command=self.download_cloud, font=('Century Gothic', 15)) + self.download_button.grid(row=2, column = 0, sticky = 'nsew', padx=10, pady=5) + + self.verify = ctk.CTkButton(self.navigation_frame, text=' Проверка подписи', image=verify_image, compound='top', height=40, fg_color='#C57A44', command=self.verify_main, font=('Century Gothic', 15)) + self.verify.grid(row=3, column = 0, sticky = 'ew', padx=10, pady=5) + + self.encode = ctk.CTkButton(self.navigation_frame, text=' Подписать', image=encode_image, compound='top', height=40, command=self.encode_main, fg_color='#C57A44', font=('Century Gothic', 15)) + self.encode.grid(row=4, column = 0, sticky = 'ew',padx=10, pady=5) + + + #main frame + self.main_frame = ctk.CTkFrame(self, corner_radius=0) + # self.main_frame.grid_columnconfigure(0, weight=1) + self.main_frame.grid(row=0, column=1, padx=10, pady = 10, sticky = 'nsew') + + self.main_frame.rowconfigure(0, weight=1) + self.main_frame.rowconfigure(1, weight=1) + self.main_frame.rowconfigure(2, weight=1) + self.main_frame.rowconfigure(3, weight=1) + self.main_frame.rowconfigure(4, weight=1) + self.main_frame.columnconfigure(1, weight=1) + + + self.label = ctk.CTkLabel(self.main_frame, corner_radius=0, image=self.table_image, font=ctk.CTkFont(size=20, weight="bold"), compound='left', text='') + self.label.grid(row=0,column=1, padx=25, pady = 25) + + + #buttons for verify page + # self.button_verify = ctk.CTkButton(self.main_frame, ) + def __del__(self): + ServerMeet(self.client, 'exit') + + def encode_main(self): + for widget in self.main_frame.winfo_children(): + widget.destroy() + + + #Label + self.label = ctk.CTkLabel(self.main_frame, corner_radius=0, text='Выберите файл и ключ для шифрования:', + image=self.lablekey_image, compound='top', anchor=ctk.CENTER,font=ctk.CTkFont(size=18, weight="bold")) + self.label.grid(row=0, column=1) + + + + #buttons for encode page + self.button_file = ctk.CTkButton(self.main_frame, corner_radius=5, text = 'Закрытый ключ', fg_color='#C57A44', + command=lambda: self.pick_file(('Pem Files', '*.pem'), 'private_key')) + self.privateKey_file = ctk.CTkButton(self.main_frame, corner_radius=5, text = 'Файл для подписи', fg_color='#C57A44', + command=lambda: self.pick_file(('All files', '*.*'), 'encode_file_path')) + + #self.sign_file = ctk.CTkButton(self.main_frame, corner_radius=5, text = 'Make sign', fg_color='#C57A44', command=lambda : EncodeFile(self.encode_file_path, self.private_key)) + self.sign_file = ctk.CTkButton(self.main_frame, corner_radius=5, text = 'Сделать подпись', fg_color='#C57A44', + command=lambda : self.ServerMeet_(self.client, f'encode_file')) + + + self.button_file.grid(row=1, column = 1, sticky = 'nsew', padx=10, pady=5) + self.privateKey_file.grid(row=2, column = 1, sticky = 'nsew', padx=10, pady=5) + self.sign_file.grid(row=3, column=1, sticky = 'nsew', padx=10, pady=5) + + + # def pick_and_send(self, name): + # if (name == "private_key"): + + def ServerMeet_(self, client, s): + # if self.encode_file_path != None and self.private_key != None: + if self.encode_file_path != None and self.private_key != None: + ServerMeet(self.client, f'encode_file {basename(self.encode_file_path)}') + messagebox.showinfo('signify', 'Файл успешно подписан!') + else: + messagebox.showerror('signify', 'Выберите закрытый ключ и файл подписи!') + + #else: + # messagebox.showerror('Ошибка', 'Выберите файл и закрытый ключ для подписи') + + + def verify_main(self): + for widget in self.main_frame.winfo_children(): + widget.destroy() + + self.label = ctk.CTkLabel(self.main_frame, corner_radius=0, text='Выберите подписанный файл, исходный файл и открытый ключ:', + image=self.lablekey_image, compound='top', anchor=ctk.CENTER,font=ctk.CTkFont(size=18, weight="bold")) + self.label.grid(row=0, column=1) + + + self.label.columnconfigure(1, weight=1) + + + self.publicKey_file = ctk.CTkButton(self.main_frame, corner_radius=5, text = 'Открытый ключ', fg_color='#C57A44', + command=lambda: self.pick_file(('Pem Files', '*.pem'), 'public_key')) + self.signed_file = ctk.CTkButton(self.main_frame, corner_radius=5, text = 'Подписанный файл', fg_color='#C57A44', + command=lambda: self.pick_file(('All files', '*.*'), 'signed_file')) + self.source_file = ctk.CTkButton(self.main_frame, corner_radius=5, text = 'Исходный файл', fg_color='#C57A44', + command=lambda: self.pick_file(('All files', '*.*'), 'source_file')) + self.verify_file = ctk.CTkButton(self.main_frame, corner_radius=5, text = 'Проверка подписи', fg_color='#C57A44', + command=lambda : + self.VerifyFile_(path_sig = self.verify_file_path, path_source=self.source_file_path)) + + + self.publicKey_file.grid(row=1, column = 1, sticky = 'nsew', padx=10, pady=5) + self.signed_file.grid(row=2, column = 1, sticky = 'nsew', padx=10, pady=5) + self.source_file.grid(row=3, column = 1, sticky = 'nsew', padx=10, pady=5) + self.verify_file.grid(row=4, column=1, sticky = 'nsew', padx=10, pady=5) + + + def VerifyFile_(self, path_sig, path_source): + print('sig:',path_sig, 'source:',path_source) + if path_sig == None and path_source == None: + messagebox.showerror('signify', 'Выберите необходимые параметры') + return + res = ServerMeet(self.client, f"verify_sign {basename(path_sig)} {basename(path_source)}") + #print(res, res == True) + if res == 'True': + self.label.configure(image = self.lableverify_image2) + messagebox.showinfo('signify', 'Подпись документа достоверна') + else: + self.label.configure(image = self.lableverify_image1) + messagebox.showinfo('signify', 'Подпись документа неверна') + + def upload_cloud(self): + for widget in self.main_frame.winfo_children(): + widget.destroy() + + self.label = ctk.CTkLabel(self.main_frame, corner_radius=0, text='Выберите файл, чтобы загрузить его в облако:', + image=self.lablecloud_image, compound='top', anchor=ctk.CENTER,font=ctk.CTkFont(size=20, weight="bold")) + self.label.grid(row=0, column=1) + self.label.grid_rowconfigure(0, weight=1) + self.label.grid_columnconfigure(1, weight=1) + self.source_file2 = ctk.CTkButton(self.main_frame, corner_radius=5, text = 'Исходный файл', fg_color='#C57A44', + command=lambda: self.pick_file(('All files', '*.*'), 'upload_file')) + self.source_file2.grid(row=1, column=1, sticky = 'nsew', padx=10, pady=5) + + + + def add_item(self, name, t): + + name_ = name[:name.find('')-1] + size = name[name.find('')+6:]+' KB' + if len(name_) > 35: + name_ = name_[0:34]+'...' + name_ = name_ + ', '+size + label_left = ctk.CTkLabel(master=self.scroll_files, text = name_, anchor = 'w') + button_right = ctk.CTkButton(master=self.scroll_files, corner_radius=5, text = 'скачать', image = self.micro_load, fg_color='#C57A44', compound = 'left', + anchor='w', command=lambda: self.dwnload_file(name[:name.find('')-1])) + + label_left.grid(row=t, column=0, sticky='w') + button_right.grid(row=t, column=2, padx = 10, pady=5, sticky = 'nsew') + + def download_cloud(self): + for widget in self.main_frame.winfo_children(): + widget.destroy() + self.scroll_files = ctk.CTkScrollableFrame(master = self.main_frame, width=550, height=700) + + self.scroll_files.grid(row=0, column=1) + self.scroll_files.grid_columnconfigure(1, weight=1) + self.scroll_files.grid_columnconfigure(2, weight=1, minsize = 100) + + #self.scroll_files.grid_columnconfigure(1, weight=1) + #self.scroll_files.grid_rowconfigure(0, weight=1) + #self.scroll_files.grid_rowconfigure(1, weight=1) + + t = 0 + for item in self.list_dwnld_files: + if item != ' ': + self.add_item(item, t) + t+= 1 + + def dwnload_file(self, item): + #print('Pressed button with item: ', item) + ServerMeet(self.client, f'rec_file_cloud {item}') + + + + def pick_file(self, format, name): + filepath = ctk.filedialog.askopenfilename(filetypes=[format]) + if filepath != '': + if name == 'private_key': + self.private_key = useKey(filepath) + #self.client.send('use_key ') + ServerMeet(self.client, f'use_key {(filepath)}') + #self.public_key = self.private_key.verifying_key + if self.private_key != None: + print('Readed key') + elif name == 'public_key': + self.public_key = UsePub(filepath) + ServerMeet(self.client, f'use_key_pub {(filepath)}') + + elif name == 'encode_file_path': + self.encode_file_path = filepath + ServerMeet(self.client, f'send_file {filepath}') + #self.SendFile_() + + elif name == 'signed_file': + self.verify_file_path = filepath + ServerMeet(self.client, f'send_file {filepath}') + + elif name == 'source_file': + self.source_file_path = filepath + ServerMeet(self.client, f'send_file {filepath}') + elif name == 'upload_file': + self.source_file = filepath + size = getsize(filepath) + + self.list_dwnld_files.append(basename(filepath)+' '+'%.2f' % (size/1024) ) + ServerMeet(self.client, f'upload_file {filepath}') + messagebox.showinfo('signify', 'Файл успешно доставлен') + + + print(filepath) + +if __name__ == '__main__': + log = Regist() + log.mainloop() + ServerMeet(log.client, 'exit') + if log.logd == 1: + app = App() + app.mainloop() + ServerMeet(app.client, 'exit') + + + + diff --git a/test/check.png b/test/check.png new file mode 100644 index 0000000000000000000000000000000000000000..840eabf613c2ff526ee2f7d00c14a09a20dd09da Binary files /dev/null and b/test/check.png differ diff --git a/test/check.png.pem b/test/check.png.pem new file mode 100644 index 0000000000000000000000000000000000000000..f3cc272b656abeb9eec9965a957890071a65cd31 --- /dev/null +++ b/test/check.png.pem @@ -0,0 +1,4 @@ +-----BEGIN PUBLIC KEY----- +MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEEedidbizMAQW8hwS7JQhK5AL2gZB +bJWusPfYqKSnenOr22+6rxoXTuTsGwvwslOi2xDF3FIMEyW5aYFPpvketw== +-----END PUBLIC KEY----- diff --git a/test/check.png.sig b/test/check.png.sig new file mode 100644 index 0000000000000000000000000000000000000000..e137d2b46e8547da9be539aa02a7af25684786ef Binary files /dev/null and b/test/check.png.sig differ diff --git a/test/key_test.pem b/test/key_test.pem new file mode 100644 index 0000000000000000000000000000000000000000..a87dca916a0d894c783359a3bd15a569f2b5e1a9 --- /dev/null +++ b/test/key_test.pem @@ -0,0 +1,5 @@ +-----BEGIN PRIVATE KEY----- +MIGHAgEBMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgVHMqpBZuX1szBY5U +uf3ghmtfc0HhRWDxSiJFL4fTV1mhRANCAASs8+hZ98UKywfKVVzLSfT48sua1bgx +CZdMQlx+0ThvjIDavfyLDyJVQVkxnnH0C15I56ZYNSyLUMZnZvUS8XLx +-----END PRIVATE KEY-----