From 5276f37d357ed9d5b3a94483afbd518758a7eb24 Mon Sep 17 00:00:00 2001 From: Q37ek6wrm <1641520215@qq.com> Date: Fri, 16 Dec 2022 20:26:23 +0800 Subject: [PATCH] ADD file via upload --- Server.py | 315 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 315 insertions(+) create mode 100644 Server.py diff --git a/Server.py b/Server.py new file mode 100644 index 0000000..d93f0d6 --- /dev/null +++ b/Server.py @@ -0,0 +1,315 @@ +import base64 +import struct +import sys +from tkinter import * +import time +from tkinter import filedialog +import pickle +import socket +import threading +import tkinter.messagebox +import AESalgorithm +import generateKey +import RSAalgorithm +import hashalg +import json + +# 使用tkinter建立GUI + +IP = '127.0.0.1' +PORT = 4396 +BUFF = 5120 +FIP='127.0.0.1' +FPORT=7932 + + +# CLIENTPUBLICs +# SERVERPUBLICs +# SERVERPRIVATEs +def initKey(): + global SERVERPUBLICs, SERVERPRIVATEs + (SERVERPRIVATEs, SERVERPUBLICs) = generateKey.generateMyKey("keys/server/server") + +def fileDecrypt(data): + (message,encrykey)=pickle.loads(data) + onceKey= RSAalgorithm.RsaDecrypt(encrykey, SERVERPRIVATEs) + print("接收到的密钥",onceKey,type(onceKey)) + message= AESalgorithm.AesDecrypt(message, onceKey.decode('unicode_escape')) + message=pickle.loads(message) + content=base64.b64decode(message['Message']) + print('传送的内容是',content) + digest=message['digest'] + if RSAalgorithm.VerRsaSignal(content, digest, CLIENTPUBLICs): + return content + +def initFileListen(): + try: + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + # 绑定端口为9001 + s.bind((FIP, FPORT)) + # 设置监听数 + s.listen(10) + except socket.error as msg: + print(msg) + sys.exit(1) + print('Waiting connection...') + + while True: + # 等待请求并接受(程序会停留在这一旦收到连接请求即开启接受数据的线程) + conn, addr = s.accept() + # 接收数据 + t = threading.Thread(target=deal_data, args=(conn, addr)) + t.start() + + +def deal_data(conn, addr): + print('Accept new connection from {0}'.format(addr)) + txtMsgList.insert(END, '文件系统收到一个新的连接,地址来自 {0}'.format(addr), 'greencolor') + # conn.settimeout(500) + # 收到请求后的回复 + conn.send('你好,连接建立成功了'.encode('utf-8')) + + while True: + # 申请相同大小的空间存放发送过来的文件名与文件大小信息 + fileinfo_size = struct.calcsize('128sl') + # 接收文件名与文件大小信息 + buf = conn.recv(fileinfo_size) + # 判断是否接收到文件头信息 + if buf: + # 获取文件名和文件大小 + filename, filesize = struct.unpack('128sl', buf) + fn = filename.strip(b'\00') + fn = fn.decode() + print('file new name is {0}, filesize if {1}'.format(str(fn), filesize)) + txtMsgList.insert(END, '收到的文件名字为 {0}, 文件大小为 {1}'.format(str(fn), filesize), 'greencolor') + recvd_size = 0 # 定义已接收文件的大小 + # 存储在该脚本所在目录下面 + fp = open('./' + str(fn), 'wb') + print('start receiving...') + txtMsgList.insert(END, '开始接受...', 'greencolor') + # 将分批次传输的二进制流依次写入到文件 + while not recvd_size == filesize: + if filesize - recvd_size > 1024: + lens=conn.recv(1024).decode('utf-8') + lens=int(lens) + print('该段发送长度为',lens) + data = conn.recv(lens) + data=fileDecrypt(data) + recvd_size += len(data) + else: + lens = conn.recv(1024).decode('utf-8') + lens = int(lens) + print('该段发送长度为', lens) + data = conn.recv(lens) + data = fileDecrypt(data) + recvd_size = filesize + conn.send('I have receive the past one'.encode('utf-8')) + fp.write(data) + fp.close() + print('end receive...') + txtMsgList.insert(END, '接收完毕...', 'greencolor') + # 传输结束断开连接 + conn.close() + break + + +def mainPage(): + def sendMsg(Sock): # 发送消息 + strMsg = "我:" + time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) + '\n' + txtMsgList.insert(END, strMsg, 'greencolor') + Mes = txtMsg.get('0.0', END) + txtMsgList.insert(END, Mes) + print(Mes) + onceKey = AESalgorithm.genKey() # 一次一密 密钥 + print("oncekey", onceKey) + digest = RSAalgorithm.RsaSignal(Mes, SERVERPRIVATEs) # 先hash再签名# 生成消息摘要 + message = {'Message': Mes, 'digest': digest.decode("utf-8")} # 把消息和摘要打包 + message = json.dumps(message) # 转成json字符串 + message = AESalgorithm.AesEncrypt(message, onceKey) # 合并加密 + encrykey = RSAalgorithm.RsaEncrypt(onceKey, CLIENTPUBLICs) # 用服务器公钥加密一次密钥 + txtMsg.delete('0.0', END) + Message = pickle.dumps([message, encrykey.decode('utf-8')]) # 序列化消息,用于传输 + Sock.send(Message) + + def RecvMsg(Sock, test): + global CLIENTPUBLICs + while True: + Message = Sock.recv(BUFF) # 收到文件 + (message, encrykey) = pickle.loads(Message) + mykey = RSAalgorithm.RsaDecrypt(encrykey, SERVERPRIVATEs) # 用私钥解密获得一次密钥 + decryMes = AESalgorithm.AesDecrypt(message, mykey.decode('utf-8')) # 用一次密钥解密消息,获得包含消息内容和摘要的json + decryMes = json.loads(decryMes) # 将json转换为python字典 + content = decryMes['Message'] + digest = decryMes['digest'].encode('utf-8') + if RSAalgorithm.VerRsaSignal(content, digest, CLIENTPUBLICs): + strMsg = "对方:" + time.strftime("%Y-%m-%d %H:%M:%S", + time.localtime()) + "通过数字签名认证,本次密钥为" + mykey.decode('utf-8') + '\n' + txtMsgList.insert(END, strMsg, 'greencolor') + txtMsgList.insert(END, content + '\n') + + + def cancelMsg(): # 取消信息 + txtMsg.delete('0.0', END) + + def sendMsgEvent(event, Sock): # 发送消息事件 + if event.keysym == 'Up': + sendMsg(Sock) + + def UploadAction(event=None): + filename = filedialog.askopenfilename() + print('Selected:', filename) + + def addSysTip(mes): + global txtMsgList + txtMsgList.insert(END, "系统消息:" + mes) + + def exchangePublicKey(dir): + global ConSock, txtMsgList + with open(dir, 'rb') as fi: + publicKey = fi.read() + # print(publicKey) + has = hashalg.hash_sha256(publicKey) + Message = pickle.dumps([publicKey, has]) + try: + ConSock.send(Message) + txtMsgList.insert(END, "发送公钥成功\n") + except: + txtMsgList.insert(END, "密钥发送失败,正在尝试重新发送...\n") + exchangePublicKey(dir) + + def verifyKey(Sock): + global txtMsgList, CLIENTPUBLICs + while True: + Message = Sock.recv(BUFF) + # print("shoudao:",Message) + (publickey, hash_256) = pickle.loads(Message) + if hash_256 == hashalg.hash_sha256(publickey): + txtMsgList.insert(END, "公钥完整性验证完成,可以开始传输文件\n") + CLIENTPUBLICs = publickey + txtMsgList.insert(END, "收到公钥\n" + CLIENTPUBLICs.decode('utf-8') + "\n") + # print("publicc:", CLIENTPUBLICs) + break + else: + txtMsgList.insert(END, "验证失败\n") + + def cnct(): + global txtMsgList, ConSock + HOSTIP = '127.0.0.1' + ServerSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + ServerSock.bind((HOSTIP, PORT)) + ServerSock.listen(8) + print("本机IP地址为", HOSTIP, "端口号为", PORT, ",正在监听中") + txtMsgList.insert(END, "系统消息:" + "本机IP地址为" + HOSTIP + "端口号为" + str(PORT) + ",正在监听中\n") + ConSock, addr = ServerSock.accept() + print('连接成功') + txtMsgList.insert(END, "系统消息:连接成功\n") + exchangePublicKey("keys/server/serverpublic.pem") + verifyKey(ConSock) + thread_rev = threading.Thread(target=RecvMsg, args=(ConSock, None)) + thread_rev.start() + return ConSock + + def setIpWindows(): + def setNewIP(newip, newport): + print(newip, newport) + global IP + IP = str(newip) + global PORT + PORT = int(newport) + set.destroy() + try: + cnct() + except: + addSysTip("连接异常,ip或端口不可访问") + tkinter.messagebox.showwarning('连接失败', '连接异常,ip或端口不可访问\n') + print("连接异常,ip或端口不可访问\n") + + set = Tk() + set.title('设置ip地址和端口号') + set.geometry('350x200') + set.resizable(0, 0) + # ip + Label(set, text='IP地址:').place(x=10, y=10) + ent1 = Entry(set) + ent1.place(x=150, y=10) + # port + Label(set, text='端口号:').place(x=10, y=50) + ent2 = Entry(set) + ent2.place(x=150, y=50) + bt_connect = Button(set, text='连接', command=lambda: setNewIP(ent1.get(), ent2.get())) + bt_connect.place(x=150, y=130) + set.mainloop() + + def start(): + global app, frmLT, frmLC, frmLB, txtMsgList, txtMsg, btnSend, btnCancel, btnFile, btnSet + # 创建窗口 + app = Tk() + app.title('Server') + app.resizable(0, 0) + + # 创建frame容器 + frmLT = Frame(width=500, height=320, bg='white') + frmLC = Frame(width=500, height=150, bg='white') + frmLB = Frame(width=500, height=30) + # frmRT = Frame(width = 200, height = 500) + + # 创建控件 + txtMsgList = Text(frmLT) + txtMsgList.tag_config('greencolor', foreground='#008C00') # 创建tag + txtMsg = Text(frmLC) + txtMsg.bind("", sendMsgEvent) + btnSend = Button(frmLB, text='发送', width=8, command=lambda: sendMsg(ServerSocket)) + btnCancel = Button(frmLB, text='取消', width=8, command=cancelMsg) + btnFile = Button(frmLB, text='上传文件', width=8, command=UploadAction) + btnSet = Button(frmLB, text='设置ip', width=8, command=setIpWindows) + # btnFile.pack() + # imgInfo = PhotoImage(file = "timg-2.gif") + # lblImage = Label(frmRT, image = imgInfo) + # lblImage.image = imgInfo + + # 窗口布局 + frmLT.grid(row=0, column=0, columnspan=2, padx=1, pady=3) + frmLC.grid(row=1, column=0, columnspan=2, padx=1, pady=3) + frmLB.grid(row=2, column=0, columnspan=2) + # frmRT.grid(row = 0, column = 2, rowspan = 3, padx =2, pady = 3) + + # 固定大小 + frmLT.grid_propagate(0) + frmLC.grid_propagate(0) + frmLB.grid_propagate(0) + # frmRT.grid_propagate(0) + + btnSend.grid(row=2, column=0) + btnCancel.grid(row=2, column=1) + btnFile.grid(row=2, column=2) + btnSet.grid(row=2, column=3) + # lblImage.grid() + txtMsgList.grid() + txtMsg.grid() + # 主事件循环 + app.mainloop() + + thread_gui = threading.Thread(target=start) + thread_gui.start() + + ServerSocket = cnct() + # try: + # ServerSocket=cnct() + # except: + # addSysTip("连接异常,ip或端口不可访问") + # tkinter.messagebox.showwarning('连接失败', '连接异常,ip或端口不可访问,点击设置按钮重新设置\n') + # print("连接异常,ip或端口不可访问\n") + + +def main(): + initKey() + thread_1=threading.Thread(target=initFileListen) + # thread_2=threading.Thread(target=mainPage) + mainPage() + thread_1.start() + # thread_2.start() + + +if __name__ == "__main__": + main()