├── .gitignore ├── .idea ├── .gitignore ├── .name ├── inspectionProfiles │ └── profiles_settings.xml ├── misc.xml ├── modules.xml ├── networksec.iml └── vcs.xml ├── Client.py ├── README.md ├── Server.py ├── algorithms ├── AESalgorithm.py ├── RSAalgorithm.py ├── __pycache__ │ ├── AESalgorithm.cpython-38.pyc │ └── RSAalgorithm.cpython-38.pyc ├── generateKey.py └── hashalg.py ├── img.assets ├── clip_image002.png ├── clip_image004.png ├── clip_image006.jpg ├── clip_image008.jpg ├── clip_image010.jpg ├── clip_image012.jpg ├── clip_image014.jpg ├── clip_image016.jpg ├── clip_image018.jpg ├── clip_image020.jpg ├── clip_image022.jpg ├── clip_image024.jpg ├── clip_image026.jpg ├── clip_image028.jpg ├── clip_image030.jpg └── clip_image032.jpg ├── keys ├── client │ ├── clientprivate.pem │ └── clientpublic.pem └── server │ ├── serverprivate.pem │ └── serverpublic.pem └── test ├── client.py ├── tclient.py └── tserver.py /.gitignore: -------------------------------------------------------------------------------- 1 | /venv/ 2 | /venv1/ 3 | -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | # Datasource local storage ignored files 5 | /dataSources/ 6 | /dataSources.local.xml 7 | # Editor-based HTTP Client requests 8 | /httpRequests/ 9 | -------------------------------------------------------------------------------- /.idea/.name: -------------------------------------------------------------------------------- 1 | windowsGui.py -------------------------------------------------------------------------------- /.idea/inspectionProfiles/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/networksec.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Client.py: -------------------------------------------------------------------------------- 1 | import struct 2 | from tkinter import * 3 | import time 4 | from tkinter import filedialog 5 | import pickle 6 | import socket 7 | import threading 8 | import tkinter.messagebox 9 | from algorithms import AESalgorithm, generateKey, RSAalgorithm, hashalg 10 | from tkinter import ttk 11 | import json 12 | import os 13 | import base64 14 | 15 | # 使用tkinter建立GUI 16 | 17 | IP = '127.0.0.1' 18 | PORT = 4396 19 | BUFF = 5120 20 | FIP='127.0.0.1' 21 | FPORT=7932 22 | 23 | # SERVERPUBLIC 24 | # CLIENTPUBLIC 25 | # CLIENTPRIVATE 26 | def initKey(): 27 | global CLIENTPUBLIC, CLIENTPRIVATE 28 | (CLIENTPRIVATE, CLIENTPUBLIC) = generateKey.generateMyKey("keys/client/client") 29 | 30 | def fileEncrypt(data): 31 | onceKey = AESalgorithm.genKey() 32 | print("发送的密钥",onceKey) 33 | digest = RSAalgorithm.RsaSignal(data, CLIENTPRIVATE) 34 | message = {'Message': base64.b64encode(data), 'digest': digest.decode("utf-8")} # 把消息和摘要打包 35 | message = pickle.dumps(message) # 转成json字符串 36 | message = AESalgorithm.AesEncrypt(message, onceKey) 37 | encrykey = RSAalgorithm.RsaEncrypt(onceKey, SERVERPUBLIC) 38 | MES = pickle.dumps([message, encrykey.decode('utf-8')]) 39 | return MES 40 | 41 | 42 | 43 | 44 | 45 | def initSendSocket(filepath): 46 | try: 47 | s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 48 | s.connect((FIP, FPORT)) 49 | except socket.error as msg: 50 | print(msg) 51 | sys.exit(1) 52 | print(s.recv(10240)) 53 | 54 | # 需要传输的文件路径 55 | 56 | # 判断是否为文件 57 | if os.path.isfile(filepath): 58 | # 定义定义文件信息。128s表示文件名为128bytes长,l表示一个int或log文件类型,在此为文件大小 59 | fileinfo_size = struct.calcsize('128sl') 60 | # 定义文件头信息,包含文件名和文件大小 61 | fhead = struct.pack('128sl', os.path.basename(filepath).encode('utf-8'), os.stat(filepath).st_size) 62 | # 发送文件名称与文件大小 63 | s.send(fhead) 64 | 65 | # 将传输文件以二进制的形式分多次上传至服务器 66 | fp = open(filepath, 'rb') 67 | while True: 68 | global rere 69 | rere='' 70 | data = fp.read(1024) 71 | if not data: 72 | print('{0} 文件发送完毕...'.format(os.path.basename(filepath))) 73 | txtMsgList.insert(END, '{0} 文件发送完毕...'.format(os.path.basename(filepath)), 'greencolor') 74 | break 75 | print("发送的内容",data) 76 | tosend=fileEncrypt(data) 77 | s.send(str(len(tosend)).encode('utf-8')) 78 | s.send(tosend) 79 | while True: 80 | if s.recv(1024).decode('utf-8')=='I have receive the past one': 81 | break 82 | 83 | 84 | # 关闭当期的套接字对象 85 | s.close() 86 | 87 | 88 | 89 | # 主页 90 | def mainPage(): 91 | def sendMsg(Sock): # 发送消息 92 | strMsg = "我:" + time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) + '\n' 93 | txtMsgList.insert(END, strMsg, 'greencolor') 94 | Mes = txtMsg.get('0.0', END) 95 | txtMsgList.insert(END, Mes) 96 | onceKey = AESalgorithm.genKey() # 一次一密 密钥 97 | digest = RSAalgorithm.RsaSignal(Mes, CLIENTPRIVATE) # 先hash再签名# 生成消息摘要 98 | message = {'Message': Mes, 'digest': digest.decode("utf-8")} # 把消息和摘要打包 99 | message = json.dumps(message) # 转成json字符串 100 | message = AESalgorithm.AesEncrypt(message, onceKey) # 合并加密 101 | encrykey = RSAalgorithm.RsaEncrypt(onceKey, SERVERPUBLIC) # 用服务器公钥加密一次密钥 102 | txtMsg.delete('0.0', END) 103 | Message = pickle.dumps([message, encrykey.decode('utf-8')]) # 序列化消息,用于传输 104 | Sock.send(Message) 105 | 106 | def RecvMsg(Sock, test): # 接受消息函数 107 | global SERVERPUBLICs 108 | while True: 109 | Message = Sock.recv(BUFF) # 收到文件 110 | (message, encrykey) = pickle.loads(Message) 111 | 112 | mykey = RSAalgorithm.RsaDecrypt(encrykey, CLIENTPRIVATE) # 用私钥解密获得一次密钥 113 | print('mykey', mykey.decode('utf-8')) 114 | decryMes = AESalgorithm.AesDecrypt(message, mykey.decode('utf-8')) # 用一次密钥解密消息,获得包含消息内容和摘要的json 115 | decryMes = json.loads(decryMes) # 将json转换为python字典 116 | content = decryMes['Message'] 117 | digest = decryMes['digest'].encode('utf-8') 118 | 119 | if RSAalgorithm.VerRsaSignal(content, digest, SERVERPUBLIC): 120 | strMsg = "对方:" + time.strftime("%Y-%m-%d %H:%M:%S", 121 | time.localtime()) + "通过数字签名认证,本次密钥为" + mykey.decode('utf-8') + '\n' 122 | txtMsgList.insert(END, strMsg, 'greencolor') 123 | txtMsgList.insert(END, content + '\n') 124 | 125 | def cancelMsg(): # 清空消息内容 126 | txtMsg.delete('0.0', END) 127 | 128 | def sendMsgEvent(event, Sock): # 发送消息事件 129 | if event.keysym == 'Up': 130 | sendMsg(Sock) 131 | 132 | def UploadAction(event=None): # 上传文件 133 | filename = filedialog.askopenfilename() 134 | print('Selected:', filename) 135 | initSendSocket(filename) 136 | 137 | def exchangePublicKey(dir): 138 | global ClientSock, txtMsgList 139 | with open(dir, 'rb') as fi: 140 | publicKey = fi.read() 141 | has = hashalg.hash_sha256(publicKey) 142 | Message = pickle.dumps([publicKey, has]) 143 | try: 144 | ClientSock.send(Message) 145 | txtMsgList.insert(END, "发送公钥成功\n") 146 | except: 147 | txtMsgList.insert(END, "密钥发送失败,正在尝试重新发送...\n") 148 | exchangePublicKey(dir) 149 | 150 | def verifyKey(Sock): 151 | global txtMsgList, SERVERPUBLIC 152 | while True: 153 | Message = Sock.recv(BUFF) 154 | (publickey, hash_256) = pickle.loads(Message) 155 | if hash_256 == hashalg.hash_sha256(publickey): 156 | txtMsgList.insert(END, "公钥完整性验证完成,可以开始传输文件\n") 157 | SERVERPUBLIC = publickey 158 | txtMsgList.insert(END, "收到公钥\n" + SERVERPUBLIC.decode('utf-8') + "\n") 159 | 160 | break 161 | else: 162 | txtMsgList.insert(END, "验证失败\n") 163 | 164 | def cnct(): # 连接操作 165 | global txtMsgList, ClientSock 166 | ClientSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 167 | ServerAddr = IP 168 | ClientSock.connect((ServerAddr, PORT)) 169 | print('连接成功,可以开始传输消息和文件了\n') 170 | txtMsgList.insert(END, "连接成功,可以开始传输消息和文件了" + IP + ":" + str(PORT) + "\n") 171 | exchangePublicKey("keys/client/clientpublic.pem") # 发送公钥 172 | verifyKey(ClientSock) # 验证对方密钥 173 | thread = threading.Thread(target=RecvMsg, args=(ClientSock, None)) 174 | thread.start() 175 | return ClientSock 176 | 177 | def setIpWindows(): # 设置ip的子窗口 178 | def setNewIP(newip, newport): 179 | global txtMsgList 180 | print(newip, newport) 181 | global IP 182 | IP = str(newip) 183 | global PORT 184 | PORT = int(newport) 185 | set.destroy() 186 | try: 187 | cnct() 188 | except: 189 | txtMsgList.insert(END, "连接异常,ip或端口不可访问") 190 | tkinter.messagebox.showwarning('连接失败', '连接异常,ip或端口不可访问\n') 191 | print("连接异常,ip或端口不可访问\n") 192 | 193 | set = Tk() 194 | set.title('设置ip地址和端口号') 195 | set.geometry('350x200') 196 | set.resizable(0, 0) 197 | # ip 198 | Label(set, text='IP地址:').place(x=10, y=10) 199 | ent1 = Entry(set) 200 | ent1.place(x=150, y=10) 201 | # port 202 | Label(set, text='端口号:').place(x=10, y=50) 203 | ent2 = Entry(set) 204 | ent2.place(x=150, y=50) 205 | bt_connect = Button(set, text='连接', command=lambda: setNewIP(ent1.get(), ent2.get())) 206 | bt_connect.place(x=150, y=130) 207 | set.mainloop() 208 | 209 | def start(): 210 | # 以下是生成聊天窗口的代码 211 | def selectEven(*args): 212 | print(selal.get()) 213 | 214 | global app, frmLT, frmLC, frmLB, txtMsgList, txtMsg, btnSend, btnCancel, btnFile, btnSet 215 | # 创建窗口 216 | app = Tk() 217 | app.title('网络加密软件-Client') 218 | app.resizable(0, 0) 219 | 220 | # 创建frame容器 221 | frmLT = Frame(width=500, height=320, bg='white') 222 | frmLC = Frame(width=500, height=150, bg='white') 223 | frmLB = Frame(width=500, height=30) 224 | # frmRT = Frame(width = 200, height = 500) 225 | 226 | # 创建控件 227 | txtMsgList = Text(frmLT) 228 | txtMsgList.tag_config('greencolor', foreground='#008C00') # 创建tag 229 | txtMsg = Text(frmLC) 230 | txtMsg.bind("", sendMsgEvent) 231 | selal = StringVar() 232 | btnSend = Button(frmLB, text='发送', width=8, command=lambda: sendMsg(ClientSocket)) 233 | btnCancel = Button(frmLB, text='取消', width=8, command=cancelMsg) 234 | btnFile = Button(frmLB, text='上次文件', width=8, command=UploadAction) 235 | btnSet = Button(frmLB, text='设置ip', width=8, command=setIpWindows) 236 | btnAlSel = ttk.Combobox(frmLB, textvariable=selal, state='readonly') 237 | btnAlSel['values'] = ('AES-CBC-一次一密', '待定2') 238 | btnAlSel.current(0) 239 | btnAlSel.bind("<>", selectEven) 240 | print("selal is ", selal.get()) 241 | # btnFile.pack() 242 | # imgInfo = PhotoImage(file = "timg-2.gif") 243 | # lblImage = Label(frmRT, image = imgInfo) 244 | # lblImage.image = imgInfo 245 | 246 | # 窗口布局 247 | frmLT.grid(row=0, column=0, columnspan=2, padx=1, pady=3) 248 | frmLC.grid(row=1, column=0, columnspan=2, padx=1, pady=3) 249 | frmLB.grid(row=2, column=0, columnspan=2) 250 | # frmRT.grid(row = 0, column = 2, rowspan = 3, padx =2, pady = 3) 251 | 252 | # 固定大小 253 | frmLT.grid_propagate(0) 254 | frmLC.grid_propagate(0) 255 | frmLB.grid_propagate(0) 256 | # frmRT.grid_propagate(0) 257 | 258 | btnSend.grid(row=2, column=0) 259 | btnCancel.grid(row=2, column=1) 260 | btnFile.grid(row=2, column=2) 261 | btnSet.grid(row=2, column=3) 262 | btnAlSel.grid(row=2, column=4) 263 | # lblImage.grid() 264 | txtMsgList.grid() 265 | txtMsg.grid() 266 | # 主事件循环 267 | app.mainloop() 268 | 269 | thread_gui = threading.Thread(target=start) 270 | thread_gui.start() 271 | 272 | ClientSocket = cnct() 273 | # try: 274 | # ClientSocket=cnct() 275 | # except: 276 | # addSysTip("连接异常,ip或端口不可访问") 277 | # tkinter.messagebox.showwarning('连接失败', '连接异常,ip或端口不可访问,点击设置按钮重新设置\n') 278 | # print("连接异常,ip或端口不可访问\n") 279 | 280 | 281 | def main(): 282 | initKey() 283 | mainPage() 284 | 285 | 286 | if __name__ == "__main__": 287 | main() 288 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 本项目为本科课程设计项目,时间比较久远,已经停止维护,一些异常是由于包版本或者python版本兼容性的问题导致的(例如一些三方加密包)。由于个人没有多余的精力重新维护该项目,故无法提供支持,望理解。如有对本项目感兴趣的小伙伴欢迎修复并提交合并。有维护意向的小伙伴欢迎与我联系。 2 | 3 | ## 1 设计思路 4 | 5 | 在本安全通讯系统中,我采用了先签名后加密的设计思路,并且结合了电子信封将对称密钥通过非对称加密,实现密钥安全传输的一次一密加密系统。提供了保密性、消息认证和数字签名。在系统连接之初,双方生成公钥私钥后,进行公钥交换,通过SHA256算法生成数字摘要,提供完整性校验。本系统单钥加密算法采用CBC模式的AES算法,用于对消息和签名一起进行加密和解密。非对称加密算法采用RSA,用于签名和验证签名,加密密钥和解密密钥。系统采用CS模式的TCP连接,消息系统和文件传输系统采用独立线程,同时GUI也单独运行在一个线程中。消息系统和文件系统采用相同的加密算法,实现上略有不同,消息系统建立的是长连接。文件系统传送文件时建立连接,传送完成即断开连接。编程语言采用Python。 6 | 7 | ### 1.2 发送方加密过程 8 | 9 | ![img](img.assets/clip_image002.png) 10 | 11 | ### 1.3 接收方解密过程 12 | 13 | ![img](img.assets/clip_image004.png) 14 | 15 | ### 1.4 软件界面 16 | 17 | 18 | 19 | ![img](img.assets/clip_image006.jpg)![img](img.assets/clip_image008.jpg) 20 | 21 | ![img](img.assets/clip_image010.jpg)![img](img.assets/clip_image012.jpg) 22 | 23 | 24 | 25 | 26 | 27 | ## 2 核心算法 28 | 29 | ### 2.1 RSA算法 30 | 31 | RSA算法使用发送方的私钥进行签名,使用对方公钥对单次密钥进行加密。接收方使用公钥解密单次密钥并通过发送方公钥验证签名。 32 | 33 | ![img](img.assets/clip_image014.jpg) 34 | 35 | ![img](img.assets/clip_image016.jpg) 36 | 37 | ![img](img.assets/clip_image018.jpg) 38 | 39 | ![img](img.assets/clip_image020.jpg) 40 | 41 | ### 2.2 CBC模式的AES算法 42 | 43 | CBC模式(密码分组链接),该模式的特点是使得每个分组加密依赖于所有以前的分组。AES算法采用的密钥长度和分组长度都是128位,如果分组长度不满足128位要进行填充。 44 | 45 | ![img](img.assets/clip_image022.jpg) 46 | 47 | ![img](img.assets/clip_image024.jpg) 48 | 49 | ### 2.3 加密过程(以传送消息为例,文件传输类似,实现略有不同) 50 | 51 | ![img](img.assets/clip_image026.jpg) 52 | 53 | ### 2.4 解密过程 54 | 55 | ![img](img.assets/clip_image028.jpg) 56 | 57 | ### 2.5 文件传输的加解密 58 | 59 | 文件传输采用的加解密过程和消息传输一样,采用先签名后加密的思想,并且签名前先生成消息摘要。密钥通过对方公钥进行加密,一并传输。消息传输和文件传输最大的区别是,文件大小不确定,每次发送的文件大小可能不一样,格式多样。并且因为socket缓冲区大小有限,为了实现大文件传输,必须要将大文件拆分,分段传输。每一次从文件中读取固定长度,然后对该部分内容加密后发送,由于每一段密文长度可能不同(最后一段和前面段),那么在传送每一段前先发送一个该段加密后的长度,便于接收方设置接受缓存。同时,为了解决文件格式以及方便接收方对文件完整性检验,需要在建立传输连接时,将文件名、格式、大小等信息传送给接收方。对每一段加密和解密的过程同消息传输。以下是部分核心代码。 60 | 61 | ![img](img.assets/clip_image030.jpg) 62 | 63 | ![img](img.assets/clip_image032.jpg) 64 | 65 | 66 | -------------------------------------------------------------------------------- /Server.py: -------------------------------------------------------------------------------- 1 | import base64 2 | import struct 3 | from tkinter import * 4 | import time 5 | from tkinter import filedialog 6 | import pickle 7 | import socket 8 | import threading 9 | import tkinter.messagebox 10 | from algorithms import AESalgorithm, generateKey, RSAalgorithm, hashalg 11 | import json 12 | 13 | # 使用tkinter建立GUI 14 | 15 | IP = '127.0.0.1' 16 | PORT = 4396 17 | BUFF = 5120 18 | FIP='127.0.0.1' 19 | FPORT=7932 20 | 21 | 22 | # CLIENTPUBLICs 23 | # SERVERPUBLICs 24 | # SERVERPRIVATEs 25 | def initKey(): 26 | global SERVERPUBLICs, SERVERPRIVATEs 27 | (SERVERPRIVATEs, SERVERPUBLICs) = generateKey.generateMyKey("keys/server/server") 28 | 29 | def fileDecrypt(data): 30 | (message,encrykey)=pickle.loads(data) 31 | onceKey= RSAalgorithm.RsaDecrypt(encrykey, SERVERPRIVATEs) 32 | print("接收到的密钥",onceKey,type(onceKey)) 33 | message= AESalgorithm.AesDecrypt(message, onceKey.decode('unicode_escape')) 34 | message=pickle.loads(message) 35 | content=base64.b64decode(message['Message']) 36 | print('传送的内容是',content) 37 | digest=message['digest'] 38 | if RSAalgorithm.VerRsaSignal(content, digest, CLIENTPUBLICs): 39 | return content 40 | 41 | def initFileListen(): 42 | try: 43 | s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 44 | s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 45 | # 绑定端口为9001 46 | s.bind((FIP, FPORT)) 47 | # 设置监听数 48 | s.listen(10) 49 | except socket.error as msg: 50 | print(msg) 51 | sys.exit(1) 52 | print('Waiting connection...') 53 | 54 | while True: 55 | # 等待请求并接受(程序会停留在这一旦收到连接请求即开启接受数据的线程) 56 | conn, addr = s.accept() 57 | # 接收数据 58 | t = threading.Thread(target=deal_data, args=(conn, addr)) 59 | t.start() 60 | 61 | 62 | def deal_data(conn, addr): 63 | print('Accept new connection from {0}'.format(addr)) 64 | txtMsgList.insert(END, '文件系统收到一个新的连接,地址来自 {0}'.format(addr), 'greencolor') 65 | # conn.settimeout(500) 66 | # 收到请求后的回复 67 | conn.send('你好,连接建立成功了'.encode('utf-8')) 68 | 69 | while True: 70 | # 申请相同大小的空间存放发送过来的文件名与文件大小信息 71 | fileinfo_size = struct.calcsize('128sl') 72 | # 接收文件名与文件大小信息 73 | buf = conn.recv(fileinfo_size) 74 | # 判断是否接收到文件头信息 75 | if buf: 76 | # 获取文件名和文件大小 77 | filename, filesize = struct.unpack('128sl', buf) 78 | fn = filename.strip(b'\00') 79 | fn = fn.decode() 80 | print('file new name is {0}, filesize if {1}'.format(str(fn), filesize)) 81 | txtMsgList.insert(END, '收到的文件名字为 {0}, 文件大小为 {1}'.format(str(fn), filesize), 'greencolor') 82 | recvd_size = 0 # 定义已接收文件的大小 83 | # 存储在该脚本所在目录下面 84 | fp = open('./' + str(fn), 'wb') 85 | print('start receiving...') 86 | txtMsgList.insert(END, '开始接受...', 'greencolor') 87 | # 将分批次传输的二进制流依次写入到文件 88 | while not recvd_size == filesize: 89 | if filesize - recvd_size > 1024: 90 | lens=conn.recv(1024).decode('utf-8') 91 | lens=int(lens) 92 | print('该段发送长度为',lens) 93 | data = conn.recv(lens) 94 | data=fileDecrypt(data) 95 | recvd_size += len(data) 96 | else: 97 | lens = conn.recv(1024).decode('utf-8') 98 | lens = int(lens) 99 | print('该段发送长度为', lens) 100 | data = conn.recv(lens) 101 | data = fileDecrypt(data) 102 | recvd_size = filesize 103 | conn.send('I have receive the past one'.encode('utf-8')) 104 | fp.write(data) 105 | fp.close() 106 | print('end receive...') 107 | txtMsgList.insert(END, '接收完毕...', 'greencolor') 108 | # 传输结束断开连接 109 | conn.close() 110 | break 111 | 112 | 113 | def mainPage(): 114 | def sendMsg(Sock): # 发送消息 115 | strMsg = "我:" + time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) + '\n' 116 | txtMsgList.insert(END, strMsg, 'greencolor') 117 | Mes = txtMsg.get('0.0', END) 118 | txtMsgList.insert(END, Mes) 119 | print(Mes) 120 | onceKey = AESalgorithm.genKey() # 一次一密 密钥 121 | print("oncekey", onceKey) 122 | digest = RSAalgorithm.RsaSignal(Mes, SERVERPRIVATEs) # 先hash再签名# 生成消息摘要 123 | message = {'Message': Mes, 'digest': digest.decode("utf-8")} # 把消息和摘要打包 124 | message = json.dumps(message) # 转成json字符串 125 | message = AESalgorithm.AesEncrypt(message, onceKey) # 合并加密 126 | encrykey = RSAalgorithm.RsaEncrypt(onceKey, CLIENTPUBLICs) # 用服务器公钥加密一次密钥 127 | txtMsg.delete('0.0', END) 128 | Message = pickle.dumps([message, encrykey.decode('utf-8')]) # 序列化消息,用于传输 129 | Sock.send(Message) 130 | 131 | def RecvMsg(Sock, test): 132 | global CLIENTPUBLICs 133 | while True: 134 | Message = Sock.recv(BUFF) # 收到文件 135 | (message, encrykey) = pickle.loads(Message) 136 | mykey = RSAalgorithm.RsaDecrypt(encrykey, SERVERPRIVATEs) # 用私钥解密获得一次密钥 137 | decryMes = AESalgorithm.AesDecrypt(message, mykey.decode('utf-8')) # 用一次密钥解密消息,获得包含消息内容和摘要的json 138 | decryMes = json.loads(decryMes) # 将json转换为python字典 139 | content = decryMes['Message'] 140 | digest = decryMes['digest'].encode('utf-8') 141 | if RSAalgorithm.VerRsaSignal(content, digest, CLIENTPUBLICs): 142 | strMsg = "对方:" + time.strftime("%Y-%m-%d %H:%M:%S", 143 | time.localtime()) + "通过数字签名认证,本次密钥为" + mykey.decode('utf-8') + '\n' 144 | txtMsgList.insert(END, strMsg, 'greencolor') 145 | txtMsgList.insert(END, content + '\n') 146 | 147 | 148 | def cancelMsg(): # 取消信息 149 | txtMsg.delete('0.0', END) 150 | 151 | def sendMsgEvent(event, Sock): # 发送消息事件 152 | if event.keysym == 'Up': 153 | sendMsg(Sock) 154 | 155 | def UploadAction(event=None): 156 | filename = filedialog.askopenfilename() 157 | print('Selected:', filename) 158 | 159 | def addSysTip(mes): 160 | global txtMsgList 161 | txtMsgList.insert(END, "系统消息:" + mes) 162 | 163 | def exchangePublicKey(dir): 164 | global ConSock, txtMsgList 165 | with open(dir, 'rb') as fi: 166 | publicKey = fi.read() 167 | # print(publicKey) 168 | has = hashalg.hash_sha256(publicKey) 169 | Message = pickle.dumps([publicKey, has]) 170 | try: 171 | ConSock.send(Message) 172 | txtMsgList.insert(END, "发送公钥成功\n") 173 | except: 174 | txtMsgList.insert(END, "密钥发送失败,正在尝试重新发送...\n") 175 | exchangePublicKey(dir) 176 | 177 | def verifyKey(Sock): 178 | global txtMsgList, CLIENTPUBLICs 179 | while True: 180 | Message = Sock.recv(BUFF) 181 | # print("shoudao:",Message) 182 | (publickey, hash_256) = pickle.loads(Message) 183 | if hash_256 == hashalg.hash_sha256(publickey): 184 | txtMsgList.insert(END, "公钥完整性验证完成,可以开始传输文件\n") 185 | CLIENTPUBLICs = publickey 186 | txtMsgList.insert(END, "收到公钥\n" + CLIENTPUBLICs.decode('utf-8') + "\n") 187 | # print("publicc:", CLIENTPUBLICs) 188 | break 189 | else: 190 | txtMsgList.insert(END, "验证失败\n") 191 | 192 | def cnct(): 193 | global txtMsgList, ConSock 194 | HOSTIP = '127.0.0.1' 195 | ServerSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 196 | ServerSock.bind((HOSTIP, PORT)) 197 | ServerSock.listen(8) 198 | print("本机IP地址为", HOSTIP, "端口号为", PORT, ",正在监听中") 199 | txtMsgList.insert(END, "系统消息:" + "本机IP地址为" + HOSTIP + "端口号为" + str(PORT) + ",正在监听中\n") 200 | ConSock, addr = ServerSock.accept() 201 | print('连接成功') 202 | txtMsgList.insert(END, "系统消息:连接成功\n") 203 | exchangePublicKey("keys/server/serverpublic.pem") 204 | verifyKey(ConSock) 205 | thread_rev = threading.Thread(target=RecvMsg, args=(ConSock, None)) 206 | thread_rev.start() 207 | return ConSock 208 | 209 | def setIpWindows(): 210 | def setNewIP(newip, newport): 211 | print(newip, newport) 212 | global IP 213 | IP = str(newip) 214 | global PORT 215 | PORT = int(newport) 216 | set.destroy() 217 | try: 218 | cnct() 219 | except: 220 | addSysTip("连接异常,ip或端口不可访问") 221 | tkinter.messagebox.showwarning('连接失败', '连接异常,ip或端口不可访问\n') 222 | print("连接异常,ip或端口不可访问\n") 223 | 224 | set = Tk() 225 | set.title('设置ip地址和端口号') 226 | set.geometry('350x200') 227 | set.resizable(0, 0) 228 | # ip 229 | Label(set, text='IP地址:').place(x=10, y=10) 230 | ent1 = Entry(set) 231 | ent1.place(x=150, y=10) 232 | # port 233 | Label(set, text='端口号:').place(x=10, y=50) 234 | ent2 = Entry(set) 235 | ent2.place(x=150, y=50) 236 | bt_connect = Button(set, text='连接', command=lambda: setNewIP(ent1.get(), ent2.get())) 237 | bt_connect.place(x=150, y=130) 238 | set.mainloop() 239 | 240 | def start(): 241 | global app, frmLT, frmLC, frmLB, txtMsgList, txtMsg, btnSend, btnCancel, btnFile, btnSet 242 | # 创建窗口 243 | app = Tk() 244 | app.title('Server') 245 | app.resizable(0, 0) 246 | 247 | # 创建frame容器 248 | frmLT = Frame(width=500, height=320, bg='white') 249 | frmLC = Frame(width=500, height=150, bg='white') 250 | frmLB = Frame(width=500, height=30) 251 | # frmRT = Frame(width = 200, height = 500) 252 | 253 | # 创建控件 254 | txtMsgList = Text(frmLT) 255 | txtMsgList.tag_config('greencolor', foreground='#008C00') # 创建tag 256 | txtMsg = Text(frmLC) 257 | txtMsg.bind("", sendMsgEvent) 258 | btnSend = Button(frmLB, text='发送', width=8, command=lambda: sendMsg(ServerSocket)) 259 | btnCancel = Button(frmLB, text='取消', width=8, command=cancelMsg) 260 | btnFile = Button(frmLB, text='上次文件', width=8, command=UploadAction) 261 | btnSet = Button(frmLB, text='设置ip', width=8, command=setIpWindows) 262 | # btnFile.pack() 263 | # imgInfo = PhotoImage(file = "timg-2.gif") 264 | # lblImage = Label(frmRT, image = imgInfo) 265 | # lblImage.image = imgInfo 266 | 267 | # 窗口布局 268 | frmLT.grid(row=0, column=0, columnspan=2, padx=1, pady=3) 269 | frmLC.grid(row=1, column=0, columnspan=2, padx=1, pady=3) 270 | frmLB.grid(row=2, column=0, columnspan=2) 271 | # frmRT.grid(row = 0, column = 2, rowspan = 3, padx =2, pady = 3) 272 | 273 | # 固定大小 274 | frmLT.grid_propagate(0) 275 | frmLC.grid_propagate(0) 276 | frmLB.grid_propagate(0) 277 | # frmRT.grid_propagate(0) 278 | 279 | btnSend.grid(row=2, column=0) 280 | btnCancel.grid(row=2, column=1) 281 | btnFile.grid(row=2, column=2) 282 | btnSet.grid(row=2, column=3) 283 | # lblImage.grid() 284 | txtMsgList.grid() 285 | txtMsg.grid() 286 | # 主事件循环 287 | app.mainloop() 288 | 289 | thread_gui = threading.Thread(target=start) 290 | thread_gui.start() 291 | 292 | ServerSocket = cnct() 293 | # try: 294 | # ServerSocket=cnct() 295 | # except: 296 | # addSysTip("连接异常,ip或端口不可访问") 297 | # tkinter.messagebox.showwarning('连接失败', '连接异常,ip或端口不可访问,点击设置按钮重新设置\n') 298 | # print("连接异常,ip或端口不可访问\n") 299 | 300 | 301 | def main(): 302 | initKey() 303 | thread_1=threading.Thread(target=initFileListen) 304 | # thread_2=threading.Thread(target=mainPage) 305 | mainPage() 306 | thread_1.start() 307 | # thread_2.start() 308 | 309 | 310 | if __name__ == "__main__": 311 | main() 312 | -------------------------------------------------------------------------------- /algorithms/AESalgorithm.py: -------------------------------------------------------------------------------- 1 | import base64 2 | from Crypto.Cipher import AES 3 | import random 4 | import string 5 | 6 | # 采用AES对称加密算法,CBC 7 | 8 | 9 | iv=b'0000100010010010' 10 | # str不是16的倍数那就补足为16的倍数 11 | def add_to_16(value): 12 | if isinstance(value,bytes): 13 | value.decode() 14 | while len(value) % 16 != 0: 15 | value += '\0' 16 | return str.encode(value) # 返回bytes 17 | #加密方法 18 | def AesEncrypt(data,key): 19 | if isinstance(data,bytes): 20 | text=base64.b64encode(data).decode('ascii') 21 | else: 22 | text = base64.b64encode(data.encode('utf-8')).decode('ascii') 23 | # 初始化加密器 24 | aes = AES.new(add_to_16(key), AES.MODE_CBC,IV=iv) 25 | #先进行aes加密 26 | encrypt_aes = aes.encrypt(add_to_16(text)) 27 | #用base64转成字符串形式 28 | encrypted_text = str(base64.encodebytes(encrypt_aes), encoding='utf-8') # 执行加密并转码返回bytes 29 | return encrypted_text 30 | #解密方法 31 | def AesDecrypt(text,key): 32 | # 初始化加密器 33 | aes = AES.new(add_to_16(key), AES.MODE_CBC,IV=iv) 34 | #优先逆向解密base64成bytes 35 | if isinstance(text,str): 36 | base64_decrypted = base64.decodebytes(text.encode(encoding='utf-8')) 37 | else: 38 | base64_decrypted=base64.decodebytes(text) 39 | decrypted_text = str(aes.decrypt(base64_decrypted),encoding='utf-8') # 执行解密密并转码返回str 40 | decrypted_text = base64.b64decode(decrypted_text.encode('utf-8'))\ 41 | # .decode('utf-8') 42 | return decrypted_text 43 | 44 | 45 | def genKey(): 46 | source=string.ascii_letters+string.digits 47 | key="".join(random.sample(source,16)) 48 | return key 49 | 50 | if __name__ == '__main__': 51 | text='你好你好' 52 | mykey=genKey() 53 | print("加密密钥是"+mykey) 54 | e=AesEncrypt(text,mykey) 55 | d=AesDecrypt(e,mykey) 56 | print(e) 57 | print(d) -------------------------------------------------------------------------------- /algorithms/RSAalgorithm.py: -------------------------------------------------------------------------------- 1 | from Crypto import Random 2 | from Crypto.Hash import SHA 3 | from Crypto.Cipher import PKCS1_v1_5 as Cipher_pkcs1_v1_5 4 | from Crypto.Signature import PKCS1_v1_5 as Signature_pkcs1_v1_5 5 | from Crypto.PublicKey import RSA 6 | import base64 7 | random_generator= Random.new().read 8 | print("rand:",random_generator) 9 | def RsaEncrypt(message,key): 10 | rsakey = RSA.importKey(key) #生成RSA密钥对象 11 | cipher = Cipher_pkcs1_v1_5.new(rsakey) #生成一个pkcs1 对象 12 | if isinstance(message,str): 13 | message=message.encode('utf-8') 14 | cipher_text = base64.b64encode(cipher.encrypt(message)) #生成一个bytes对象 15 | print(cipher_text.decode('utf-8')) 16 | return cipher_text #返回一个bytes对象,如果要显示需要utf8编码 17 | def RsaDecrypt(encrypt_text,key): 18 | global random_generator 19 | rsakey = RSA.importKey(key) 20 | cipher = Cipher_pkcs1_v1_5.new(rsakey) 21 | if isinstance(encrypt_text,str): 22 | encrypt_text=base64.b64decode(encrypt_text) 23 | text = cipher.decrypt(encrypt_text,random_generator) 24 | print("测试点test",type(text)) 25 | return text #返回bytes对象,显示需要utf8编码 26 | 27 | def RsaSignal(message,key): 28 | if isinstance(message,str): 29 | message=message.encode() 30 | rsakey = RSA.importKey(key) 31 | signer = Signature_pkcs1_v1_5.new(rsakey) 32 | digest = SHA.new() 33 | digest.update(message) 34 | sign = signer.sign(digest) 35 | signature = base64.b64encode(sign) 36 | print(signature) 37 | return signature 38 | 39 | def VerRsaSignal(message,signature,key): 40 | if isinstance(message,str): 41 | message=message.encode() 42 | print("signtype",type(signature)) 43 | rsakey = RSA.importKey(key) 44 | verifier = Signature_pkcs1_v1_5.new(rsakey) 45 | 46 | digest = SHA.new() 47 | # Assumes the data is base64 encoded to begin with 48 | digest.update(message) 49 | 50 | is_verify = verifier.verify(digest, base64.b64decode(signature)) 51 | print(is_verify) 52 | return is_verify 53 | 54 | if __name__ == '__main__': 55 | mes='你好yo' 56 | pubkey='''-----BEGIN PUBLIC KEY----- 57 | MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvSChFb9Y6xwb+XTMIcHR 58 | Q5lujD1J7v93TwJvUE7e6SEVpQEjfFKpjVEFpJUONdagBRYYkO4TA6k9gpAPmPCF 59 | nucttQBMAkTMDtxLndOKI0MOc5THw0h1fschm6CyJzkGoVYlPr0vU2Oq10yK0s7y 60 | uYqTzJB5sOLjRCGxdIw9V3UmpggK+IfQ6yXrM/dXy4h13zR6IzHnJ8tBH0VvvPes 61 | z/fMrN/HWw6av13CZuS12qEU/Jij+8ZvpKxn6kd1BO4+g9UW4ExsEq95+qFTOJIj 62 | hlm7yJCCsHfNq/r1nIa/NbpigQG0TS26r8sWTLgPmYysBTONFwX+NtCbbESRwRMo 63 | gQIDAQAB 64 | -----END PUBLIC KEY-----''' 65 | prikey='''-----BEGIN RSA PRIVATE KEY----- 66 | MIIEowIBAAKCAQEAvSChFb9Y6xwb+XTMIcHRQ5lujD1J7v93TwJvUE7e6SEVpQEj 67 | fFKpjVEFpJUONdagBRYYkO4TA6k9gpAPmPCFnucttQBMAkTMDtxLndOKI0MOc5TH 68 | w0h1fschm6CyJzkGoVYlPr0vU2Oq10yK0s7yuYqTzJB5sOLjRCGxdIw9V3UmpggK 69 | +IfQ6yXrM/dXy4h13zR6IzHnJ8tBH0VvvPesz/fMrN/HWw6av13CZuS12qEU/Jij 70 | +8ZvpKxn6kd1BO4+g9UW4ExsEq95+qFTOJIjhlm7yJCCsHfNq/r1nIa/NbpigQG0 71 | TS26r8sWTLgPmYysBTONFwX+NtCbbESRwRMogQIDAQABAoIBABCU9cqkVjV253T9 72 | qpAjICffIfQlw3+y4lEJE51k7OJfxjgLW4Mg9ECxo98EOpS51pnbkBfU59HgWsZB 73 | vzxXij+eYUGHXyKryYBcDD0wOOJSlMfJeaJDjhmpd+bfNf9+Xnhyxx0zFR0olef+ 74 | jAVjo6Bk6AR9fk3l9qsYkSh4y0AJnJuPnMjISqjn6LfGXf1VAVCkHljLRTHzIzw3 75 | ZbV1rNWNQq8znaNGQP1sGAXpu1x+XfQFJZVUDtVeC9E2bB3TQe5D+LIFCtZrUkpK 76 | PNOCqce9oOUgErUub73+fTMMvBX5rU2m6zuhmZjl9s8PHVsDv1/GMyU/6Krrhh8E 77 | n11ipEkCgYEAw+oFfJhs4DtC+IqC0WaI4v6BB4EoYDoaAhHjNQZ0gx5k1AtIeNpN 78 | YKCFF0IPyIQbDWve+hspxJ47zcOZuS85UfRFjkfohwYE4UdhViUAwsIiFePZMEz8 79 | 3R2XGL0lHbXnZ2KRD0u9w+u9YfPLngsnHBUZxRp7iG48apP2nYfRCrcCgYEA9yHC 80 | NOVb7ER9NMrSRkCCh6qM0jPUsCFFBPv63s6ZKKioyqHYUPVPP9ZxxsQpya+NUPiS 81 | vf56ccGFqtjKMDIMQh+POTPkFEyjFHwoxXxg76xz2uCpyQVsSQTNCwy9LkEavjNe 82 | sebB+a8iH2gTL5zIXObaTBC4iANhQ+OtR6BDjocCgYAVT6qjIA2P4sJpON/8GVRA 83 | pQCyKUmUFh3oJbv6c6ZO8Qp0ynlqtAyAu1Ve70+6NyyeLCLIQBYuDixhOKrLKyjo 84 | ElNSo93WekAjpVkgPswzY1zD1tI0X9uNzf82sLSN49C1PVKcQFf3LPif5B49Jedu 85 | NZllCHlxoNQvn8LO5gxGRwKBgQCD+CYSQyy8VbKa33g8hbRuqBe9JGp+h7WovLqy 86 | ApdtS+ufEaBHU0g3qddmMliyWCnZxHPwO5W9a39qxYvrAr7jDKFaBajVYjtv9AF9 87 | vDazpl7T0kc4jsnNkF/Cd9IKgj+6tAnsbHLHV8ucA+LC+TFR0wFdv0wbbdqh+1IM 88 | Prv0vwKBgFUAow5ttHgBtG5Ap4evsRgWzGaF2wOGzEOK3rwS5fIGY67A1YN35Q+C 89 | SmkGVcozf8rFeyMCwk68XoLff1i14iQDAarAjvdWo0ww/gjA50kdrgFb7FpjbZNE 90 | 0kOV6q4vFJIjT8g2CeJ1MmBEuHhflC+gNBWmlEs+xaghA7/cbop2 91 | -----END RSA PRIVATE KEY-----''' 92 | a=RsaEncrypt(mes,pubkey) 93 | b=RsaDecrypt(a,prikey) 94 | c=RsaSignal(mes,prikey) 95 | 96 | 97 | 98 | 99 | digitttt='IUvR9162yrRtQAfhhVZrefB9yCwSL+kf81iudLqcDyKesokwvhjZeOpUlXR7zYOokThhelPrqtE4DIsXIxNb7FY9QgwLFkCGSQG17h09FJaZQmDLaUmtDutXDFgGZ9j5Mzln1nCtOWDreey9YbeJaRsDRj4jjp1ZOCdsC8pN65M=' 100 | digitttt=digitttt.encode('utf-8') 101 | pppuuu='''-----BEGIN PUBLIC KEY----- 102 | MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCsCp6xhC5Tr7ucaRNU3aKMsvv8 103 | PtxlQdl4LTys5F6wKM11MeJSXwruiUBbDHhySLfy5ZPpYxsfa5ez6hbaZoMyk+xd 104 | p1jWehUWqouFA/OmHxQ4jjmhxJ40cNcm/TAkyl8zci0uGaird26x2NUa4o8BpnE5 105 | TokPhvYzdhsx05FQuwIDAQAB 106 | -----END PUBLIC KEY-----''' 107 | pppuuu=pppuuu.encode('utf-8') 108 | mess='你好,世界' 109 | d = VerRsaSignal(mess, digitttt, pppuuu) 110 | print("d",d) -------------------------------------------------------------------------------- /algorithms/__pycache__/AESalgorithm.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wenjunjiecn/Cybersecurity-EncryptChatProject/7a0201a0d8b7ca0aa2ae073bd6df70e089803401/algorithms/__pycache__/AESalgorithm.cpython-38.pyc -------------------------------------------------------------------------------- /algorithms/__pycache__/RSAalgorithm.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wenjunjiecn/Cybersecurity-EncryptChatProject/7a0201a0d8b7ca0aa2ae073bd6df70e089803401/algorithms/__pycache__/RSAalgorithm.cpython-38.pyc -------------------------------------------------------------------------------- /algorithms/generateKey.py: -------------------------------------------------------------------------------- 1 | import Crypto.PublicKey.RSA 2 | import Crypto.Random 3 | #生成密钥 4 | #利用库中默认的generate来生成 5 | def generateMyKey(dir): 6 | x = Crypto.PublicKey.RSA.generate(1024) 7 | privateKey = x.exportKey("PEM") # 生成私钥 8 | publicKey = x.publickey().exportKey() # 生成公钥 9 | with open(dir+"private.pem", "wb") as x: 10 | x.write(privateKey) 11 | with open(dir+"public.pem", "wb") as x: 12 | x.write(publicKey) 13 | return(privateKey,publicKey) 14 | 15 | 16 | -------------------------------------------------------------------------------- /algorithms/hashalg.py: -------------------------------------------------------------------------------- 1 | import hashlib 2 | #hash函数 3 | def hash_sha256(datas): #sha256 哈希函数 4 | x=hashlib.sha256() 5 | x.update(datas) 6 | s=x.hexdigest() 7 | return s 8 | 9 | if __name__ == '__main__': 10 | e=hash_sha256('你好'.encode('utf-8')) 11 | print(e) -------------------------------------------------------------------------------- /img.assets/clip_image002.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wenjunjiecn/Cybersecurity-EncryptChatProject/7a0201a0d8b7ca0aa2ae073bd6df70e089803401/img.assets/clip_image002.png -------------------------------------------------------------------------------- /img.assets/clip_image004.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wenjunjiecn/Cybersecurity-EncryptChatProject/7a0201a0d8b7ca0aa2ae073bd6df70e089803401/img.assets/clip_image004.png -------------------------------------------------------------------------------- /img.assets/clip_image006.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wenjunjiecn/Cybersecurity-EncryptChatProject/7a0201a0d8b7ca0aa2ae073bd6df70e089803401/img.assets/clip_image006.jpg -------------------------------------------------------------------------------- /img.assets/clip_image008.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wenjunjiecn/Cybersecurity-EncryptChatProject/7a0201a0d8b7ca0aa2ae073bd6df70e089803401/img.assets/clip_image008.jpg -------------------------------------------------------------------------------- /img.assets/clip_image010.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wenjunjiecn/Cybersecurity-EncryptChatProject/7a0201a0d8b7ca0aa2ae073bd6df70e089803401/img.assets/clip_image010.jpg -------------------------------------------------------------------------------- /img.assets/clip_image012.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wenjunjiecn/Cybersecurity-EncryptChatProject/7a0201a0d8b7ca0aa2ae073bd6df70e089803401/img.assets/clip_image012.jpg -------------------------------------------------------------------------------- /img.assets/clip_image014.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wenjunjiecn/Cybersecurity-EncryptChatProject/7a0201a0d8b7ca0aa2ae073bd6df70e089803401/img.assets/clip_image014.jpg -------------------------------------------------------------------------------- /img.assets/clip_image016.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wenjunjiecn/Cybersecurity-EncryptChatProject/7a0201a0d8b7ca0aa2ae073bd6df70e089803401/img.assets/clip_image016.jpg -------------------------------------------------------------------------------- /img.assets/clip_image018.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wenjunjiecn/Cybersecurity-EncryptChatProject/7a0201a0d8b7ca0aa2ae073bd6df70e089803401/img.assets/clip_image018.jpg -------------------------------------------------------------------------------- /img.assets/clip_image020.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wenjunjiecn/Cybersecurity-EncryptChatProject/7a0201a0d8b7ca0aa2ae073bd6df70e089803401/img.assets/clip_image020.jpg -------------------------------------------------------------------------------- /img.assets/clip_image022.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wenjunjiecn/Cybersecurity-EncryptChatProject/7a0201a0d8b7ca0aa2ae073bd6df70e089803401/img.assets/clip_image022.jpg -------------------------------------------------------------------------------- /img.assets/clip_image024.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wenjunjiecn/Cybersecurity-EncryptChatProject/7a0201a0d8b7ca0aa2ae073bd6df70e089803401/img.assets/clip_image024.jpg -------------------------------------------------------------------------------- /img.assets/clip_image026.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wenjunjiecn/Cybersecurity-EncryptChatProject/7a0201a0d8b7ca0aa2ae073bd6df70e089803401/img.assets/clip_image026.jpg -------------------------------------------------------------------------------- /img.assets/clip_image028.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wenjunjiecn/Cybersecurity-EncryptChatProject/7a0201a0d8b7ca0aa2ae073bd6df70e089803401/img.assets/clip_image028.jpg -------------------------------------------------------------------------------- /img.assets/clip_image030.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wenjunjiecn/Cybersecurity-EncryptChatProject/7a0201a0d8b7ca0aa2ae073bd6df70e089803401/img.assets/clip_image030.jpg -------------------------------------------------------------------------------- /img.assets/clip_image032.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wenjunjiecn/Cybersecurity-EncryptChatProject/7a0201a0d8b7ca0aa2ae073bd6df70e089803401/img.assets/clip_image032.jpg -------------------------------------------------------------------------------- /keys/client/clientprivate.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIICXAIBAAKBgQC0oO4QTVvWto0ddIRNTx5de6bfGm75B4Q3yoXaDYVn7G76hdtF 3 | vGvM3VPjtX3YwT2Skcn+p1XqCdA2JkoGueigKgy5EpkvNPitaenDumbzbaTu8f+f 4 | VtlMuwt5g0eTcsYee1je4e0PfYx0txGOi/wMuZ2zXcHeuDwOP5p1t1G6qwIDAQAB 5 | AoGAAsCC8Aelsw9D9iNs0pq2fTkhkTufXjbxmkIBKRHUqwEsra91aEoXIF9s5EbD 6 | HJbRH9cNy030XqT4oaKStSiG9UcwezsFpq/eLrQe5y1Y8XOZKteFHGzX+9GkG6Bc 7 | qGpmU9RFL6Yww4qMv3LdhGV2vdkcVDFuC6yQmnukYpfTVLUCQQDQhbdTeMQ0ay9/ 8 | 3gJP0SwZ/CVpQiMRTSKcw1Z92QLHTfWWyUvLIskvFHfTj7pB20bsQpmzjK4DngIX 9 | wuH2O2WXAkEA3cFa1t9e8nwq5WdWLvHfScIOdB0AtLauw+zLmg/jVszWDjgrB00Z 10 | fKwIyBUu7Sc7Af9daYmkb1KHq4eGXkU+DQJAWSL/5ge2361+BYvyswn4bzcxCtjB 11 | wtCVXivGWk+c93Ok6wsrgi9hjuWR/3buKN7CZ5Zku7MEY/l0bZHaI/bqCwJAYm8o 12 | xoaim9qYI/qJ3A7Lge8dAVe6b31D+H5NJlb1IBuOzQMLvpLvxFKNF1un1+d5Hvre 13 | 2TEbB7tHs9FVyNTNpQJBAKw/gyv2gauM9egKc0ohlrVpz92hzCotqY94VpMWceXz 14 | aVyCHzBEzTfDAwBob63/C8F4LDBmwULB81nePoy7x3E= 15 | -----END RSA PRIVATE KEY----- -------------------------------------------------------------------------------- /keys/client/clientpublic.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC0oO4QTVvWto0ddIRNTx5de6bf 3 | Gm75B4Q3yoXaDYVn7G76hdtFvGvM3VPjtX3YwT2Skcn+p1XqCdA2JkoGueigKgy5 4 | EpkvNPitaenDumbzbaTu8f+fVtlMuwt5g0eTcsYee1je4e0PfYx0txGOi/wMuZ2z 5 | XcHeuDwOP5p1t1G6qwIDAQAB 6 | -----END PUBLIC KEY----- -------------------------------------------------------------------------------- /keys/server/serverprivate.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIICXAIBAAKBgQCZlWShX2hGOY2XgNP8SDf7UxdQa8oeK8iEPe571jrdduHYvDTG 3 | Oj5XA+3X9LwZafMQmTBaJcvgtezT0ObTxm8mm6pyftWVtG2uuGFqsGECA5lq0vWz 4 | 6VUoOHUPBP+BwmKPqo5p/o7howp0lpDuqxjTYixM1WbWFTbl6pNUsJzC5QIDAQAB 5 | AoGAG7s7Z937zI5Q0DXdURTTMuiucYF9BdSfCK3MFYU5rMpt/j4Bg3d50Slu9UsF 6 | +crFLk6SyfxAI2uF/zsdqsiOQhEm0R/aPGNJaxfmecF60rXLXnz4XenMXQQByCMZ 7 | ZbTY/yyi09IwZVaSPkAvRm3HGTn+uHw5Xlqy5cZkYwb+1sMCQQC626B4kfdIxXGf 8 | xW3AcMXY474Ai9iTTa49hfyYiEseD7p1C0edxddGz8HnJj6DZXWI4CTxGnCOdg7j 9 | 4P+pOkmjAkEA0mnOwQ/E2hmyuKyRFZyH6fsD4OwBpTk0gc0uEum+0cgu65ctvDx5 10 | 6gNzK7urr8ZWzhpxRhiHUQKd/nYpCigZ1wJAQ55ev8LynZ71sz+aq90je41OoJv6 11 | z7N4rkLiWcBYjpRagSiHzgxeDv33yVIJpTr+AX47YBSVTrhiQwyU+ARjyQJBAJR2 12 | JXShDLMaiLi2wdOu01MrUmxD+VE70Kl5PPYJSSM5jKmbzKBRR2/vKTcFPrlSR3M6 13 | wwvDSM7G+vVNJ93Lt5cCQBqvn3S9tZHmsgWGZU6E9xGTxAf9eRME4P99yXVBk6MV 14 | kK3sOJZcKDKaGHX4AShxTb+yMV6FkBlj/+l+CqznxVE= 15 | -----END RSA PRIVATE KEY----- -------------------------------------------------------------------------------- /keys/server/serverpublic.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCZlWShX2hGOY2XgNP8SDf7UxdQ 3 | a8oeK8iEPe571jrdduHYvDTGOj5XA+3X9LwZafMQmTBaJcvgtezT0ObTxm8mm6py 4 | ftWVtG2uuGFqsGECA5lq0vWz6VUoOHUPBP+BwmKPqo5p/o7howp0lpDuqxjTYixM 5 | 1WbWFTbl6pNUsJzC5QIDAQAB 6 | -----END PUBLIC KEY----- -------------------------------------------------------------------------------- /test/client.py: -------------------------------------------------------------------------------- 1 | import socket 2 | import threading 3 | import pickle 4 | from algorithms import RSAalgorithm 5 | 6 | PORT = 4396 7 | BUFF = 1024 8 | 9 | def SendMessage(Sock, test): 10 | while True: 11 | SendData = input() 12 | (encryptdata, PrivateKey) = RSAalgorithm.RsaEncrypt(SendData) 13 | print('encrypted data is ' + str(encryptdata)) 14 | Message = pickle.dumps([encryptdata, PrivateKey]) 15 | if len(SendData) > 0: 16 | Sock.send(Message) 17 | 18 | 19 | def RecvMessage(Sock, test): 20 | while True: 21 | Message = Sock.recv(BUFF) 22 | (recvdata, PrivateKey) = pickle.loads(Message) 23 | decryptdata = RSAalgorithm.RsaDecrypt(recvdata, PrivateKey) 24 | if len(Message) > 0: 25 | print("receive message:" + decryptdata) 26 | 27 | #获取本机ip地址 28 | def get_host_ip(): 29 | try: 30 | s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 31 | s.connect(('8.8.8.8', 80)) 32 | ip = s.getsockname()[0] 33 | finally: 34 | s.close() 35 | 36 | return ip 37 | 38 | 39 | def main(): 40 | type = input('您是server还是client?') 41 | if type == 'server': 42 | IPADD=get_host_ip() 43 | print("您的ip地址为:",IPADD) 44 | ServerSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 45 | ServerSock.bind((IPADD, PORT)) 46 | ServerSock.listen(5) 47 | print("正在监听中...") 48 | while True: 49 | ConSock, addr = ServerSock.accept() 50 | print('connection succeed' + '\n' + 'you can chat online') 51 | thread_1 = threading.Thread(target=SendMessage, args=(ConSock, None)) 52 | thread_2 = threading.Thread(target=RecvMessage, args=(ConSock, None)) 53 | thread_1.start() 54 | thread_2.start() 55 | elif type == 'client': 56 | ClientSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 57 | ServerAddr = input("请输入您要通讯的ip地址") 58 | ClientSock.connect((ServerAddr, PORT)) 59 | print('连接成功,可以开始传输消息和文件了') 60 | thread_3 = threading.Thread(target=SendMessage, args=(ClientSock, None)) 61 | thread_4 = threading.Thread(target=RecvMessage, args=(ClientSock, None)) 62 | thread_3.start() 63 | thread_4.start() 64 | 65 | 66 | if __name__ == '__main__': 67 | main() 68 | -------------------------------------------------------------------------------- /test/tclient.py: -------------------------------------------------------------------------------- 1 | import socket 2 | import threading 3 | import pickle 4 | from algorithms import RSAalgorithm 5 | 6 | PORT = 4396 7 | BUFF = 1024 8 | 9 | 10 | def SendMessage(Sock, test): 11 | while True: 12 | SendData = input() 13 | (encryptdata, PrivateKey) = RSAalgorithm.RsaEncrypt(SendData) 14 | print('encrypted data is ' + str(encryptdata)) 15 | Message = pickle.dumps([encryptdata, PrivateKey]) 16 | if len(SendData) > 0: 17 | Sock.send(Message) 18 | 19 | 20 | def RecvMessage(Sock, test): 21 | while True: 22 | Message = Sock.recv(BUFF) 23 | (recvdata, PrivateKey) = pickle.loads(Message) 24 | decryptdata = RSAalgorithm.RsaDecrypt(recvdata, PrivateKey) 25 | if len(Message) > 0: 26 | print("receive message:" + decryptdata) 27 | 28 | 29 | # 获取本机ip地址 30 | def get_host_ip(): 31 | try: 32 | s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 33 | s.connect(('8.8.8.8', 80)) 34 | ip = s.getsockname()[0] 35 | finally: 36 | s.close() 37 | 38 | return ip 39 | 40 | 41 | def main(): 42 | ClientSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 43 | # ServerAddr = input("请输入您要通讯的ip地址") 44 | ServerAddr ="127.0.0.1" 45 | ClientSock.connect((ServerAddr, PORT)) 46 | print('连接成功,可以开始传输消息和文件了') 47 | thread_3 = threading.Thread(target=SendMessage, args=(ClientSock, None)) 48 | thread_4 = threading.Thread(target=RecvMessage, args=(ClientSock, None)) 49 | thread_3.start() 50 | thread_4.start() 51 | 52 | 53 | 54 | if __name__ == '__main__': 55 | main() 56 | -------------------------------------------------------------------------------- /test/tserver.py: -------------------------------------------------------------------------------- 1 | import socket 2 | import threading 3 | import pickle 4 | from algorithms import RSAalgorithm 5 | 6 | HOSTIP='127.0.0.1' 7 | PORT = 4396 8 | BUFF = 1024 9 | 10 | 11 | def SendMessage(Sock, test): 12 | while True: 13 | SendData = input() 14 | (encryptdata, PrivateKey) = RSAalgorithm.RsaEncrypt(SendData) 15 | print('encrypted data is ' + str(encryptdata)) 16 | Message = pickle.dumps([encryptdata, PrivateKey]) 17 | if len(SendData) > 0: 18 | Sock.send(Message) 19 | 20 | 21 | def RecvMessage(Sock, test): 22 | while True: 23 | Message = Sock.recv(BUFF) 24 | (recvdata, PrivateKey) = pickle.loads(Message) 25 | decryptdata = RSAalgorithm.RsaDecrypt(recvdata, PrivateKey) 26 | if len(Message) > 0: 27 | print("receive message:" + decryptdata) 28 | 29 | 30 | # 获取本机ip地址 31 | def get_host_ip(): 32 | try: 33 | s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 34 | s.connect(('8.8.8.8', 80)) 35 | ip = s.getsockname()[0] 36 | finally: 37 | s.close() 38 | 39 | return ip 40 | 41 | 42 | def main(): 43 | HOSTIP = '127.0.0.1' 44 | ServerSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 45 | ServerSock.bind((HOSTIP, PORT)) 46 | ServerSock.listen(8) 47 | print("本机IP地址为",HOSTIP,"端口号为",PORT,",正在监听中") 48 | while True: 49 | ConSock, addr = ServerSock.accept() 50 | print('connection succeed' + '\n' + 'you can chat online') 51 | thread_1 = threading.Thread(target=SendMessage, args=(ConSock, None)) 52 | thread_2 = threading.Thread(target=RecvMessage, args=(ConSock, None)) 53 | thread_1.start() 54 | thread_2.start() 55 | 56 | 57 | 58 | 59 | 60 | if __name__ == '__main__': 61 | main() 62 | --------------------------------------------------------------------------------