天津理工大学信息安全综合实验4.1
需求: 使用 Java Security 或其它语言开发一个安全通信软件
要求:本实验应用 DES,RSA,MD5 等加密算法,以及 Socket 套接字实现一个简单的加密解密的聊天工具 CryptTalk。程序的步骤基本如下:首先,服务器端随机产生一对 RSA 密钥,将公钥发送给客户端,客户端将自己的对称密钥用公钥加密发送给服务器端,服务器端接收到加密后的密钥后,用自己的私钥解密得到对称密钥。然后服务器端和客户端都利用这个对称密钥对发送的消息加密,进行加密后的聊天。同时把消息经过 MD5 加密生成摘要发送,在接收端解密后进行 MD5 加密比较,检查信息是否被篡改。
流程图(上半部分为服务端操作,下半部分为客户端操作)
开发语言Python(世界上最好的语言 )
服务端
# 服务端
import socket
import tkinter as tk
import rsa
from tkinter import scrolledtext
import threading
from pyDes import des, CBC, PAD_PKCS5
import binascii
import hashlib
global conn
global pubkey
global privkey
des_str = ''
des_key = ''
msg_out = ''
server = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
server.bind(("localhost",6969)) # 绑定要监听的端口
server.listen(5) # 开始监听 表示可以使用五个链接排队
# 发送rsa数据
def send_rsa():
global conn
global pubkey
global privkey
(pubkey, privkey) = rsa.newkeys(1024)
print('发送的rsa公钥:',pubkey)
pub = pubkey.save_pkcs1().decode()
conn.send(pub.encode())
# 接受des数据
def recv_des():
global des_str
global privkey
global des_key
des_m = conn.recv(1024)
print('\n接受到加密的des密码:',des_m)
des_str = rsa.decrypt(des_m, privkey).decode()
print('\n私钥解密后的des密码:',des_str)
if len(des_str) > 8:
des_key = des_str[:8]
else:
des_key = des_str + (8-len(des_str))*'0'
print('\ndes_key:',des_key)
# 开启线程接受消息
t = threading.Thread(target = get_msg)
t.start()
# 获取消息
def get_msg():
global scr
global conn
global msg_in
while True:
# 接受密文
msg_in = conn.recv(1024)
print('\nc2s:',msg_in)
scr.insert('end','(密文)client:'+str(msg_in)[2:-1]+'\n')
# des解密
msg_in=des_descrypt(msg_in).decode()
print('client:',msg_in)
scr.insert('end','(明文)client:'+msg_in+'\n')
# MD5
md5_msg = msg_in
md5 = hashlib.md5()
md5.update(md5_msg.encode('utf-8'))
print('c_MD5:',md5.hexdigest())
scr.insert('end','(MD5)client:'+md5.hexdigest()+'\n\n')
# des加密
def des_encrypt(s):
global des_key
secret_key = des_key
iv = secret_key
k = des(secret_key, CBC, iv, pad=None, padmode=PAD_PKCS5)
en = k.encrypt(s, padmode=PAD_PKCS5)
return binascii.b2a_hex(en)
# des解密
def des_descrypt(s):
global des_key
secret_key = des_key
iv = secret_key
k = des(secret_key, CBC, iv, pad=None, padmode=PAD_PKCS5)
de = k.decrypt(binascii.a2b_hex(s), padmode=PAD_PKCS5)
return de
# __mian__
win = tk.Tk()
win.title('CryptTalk服务端') # 名称
win.geometry('500x300+200+200') # 窗口大小1
frame = tk.Frame(win,width=450, height=300)
frame.pack()
frame_l = tk.Frame(frame, width=300, height=300)# 第二层frame,左frame,长在主frame上
frame_r = tk.Frame(frame, width=150, height=300)# 第二层frame,右frame,长在主frame上
frame_l.pack(side='left')
frame_r.pack(side='right')
l1 = tk.Label(frame_l, text='消息窗口 ', font=('宋体', 10), width=40,height=2)
l1.pack()
scr = scrolledtext.ScrolledText(frame_l, bg='white', fg='black', font=('宋体', 12), width=30, height=10)
scr.pack()
l3 = tk.Label(frame_l, width=30, height=1)
l3.pack()
l4 = tk.Entry(frame_l, show=None, font=('宋体', 12),width=30)
l4.pack()
l3.pack()
def fasong():
global conn
global msg_out
# 原文
msg_out = l4.get()
print("\nme:",msg_out)
scr.insert('end','(明文)me:'+msg_out+'\n')
# MD5
md5_msg = msg_out
md5 = hashlib.md5()
md5.update(md5_msg.encode('utf-8'))
print('m_MD5:',md5.hexdigest())
scr.insert('end','(MD5)me:'+md5.hexdigest()+'\n')
# des加密
msg_out = msg_out.encode('utf-8')
msg_out = des_encrypt(msg_out)
scr.insert('end','(密文)me:'+str(msg_out)[2:-1]+'\n\n')
print('(密文)me:',msg_out)
# 发送
conn.send(msg_out)
b1 = tk.Button(frame_l, text='发送', font=('宋体', 12), width=10, height=1, command=fasong)
b1.pack()
r1 = tk.Label(frame_r, text='DES密码', font=('宋体', 12), width=20, height=2)
r1.pack()
var2 = tk.StringVar()
l2 = tk.Label(frame_r, textvariable=var2, bg='white', fg='black', font=('宋体', 12), width=20, height=2)
l2.pack()
b2 = tk.Button(frame_r, text='发送RSA公钥', font=('宋体', 10), width=10, height=2, command=send_rsa)
b2.pack()
b3 = tk.Button(frame_r, text='接受DES秘钥', font=('宋体', 10), width=10, height=2, command=recv_des)
b3.pack()
def refreshText():
global des_str
if des_str != '':
var2.set(des_str)
l2.pack()
win.after(1000,refreshText)
win.after(1000,refreshText)
while True:
conn,addr = server.accept() # 等待链接,多个链接的时候就会出现问题,其实返回了两个值
try:
win.iconbitmap('1.ico') # 更改窗口图标
win.mainloop()# 主窗口循环显示
except ConnectionResetError as e:
print("关闭了正在占线的链接!")
break
# 关闭当前端口
conn.shutdown()
conn.close()
客户端
# 客户端
import socket
import tkinter as tk
import rsa
from tkinter import scrolledtext
import threading
from pyDes import des, CBC, PAD_PKCS5
import binascii
import hashlib
global pubkey_str
global pubkey
global client
msg_out = ''
client = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
client.connect(("localhost", 6969)) # 建立一个链接,连接到本地的6969端口
# des加密
def des_encrypt(s):
global des_key
secret_key = des_key
iv = secret_key
k = des(secret_key, CBC, iv, pad=None, padmode=PAD_PKCS5)
en = k.encrypt(s, padmode=PAD_PKCS5)
return binascii.b2a_hex(en)
# des解密
def des_descrypt(s):
global des_key
secret_key = des_key
iv = secret_key
k = des(secret_key, CBC, iv, pad=None, padmode=PAD_PKCS5)
de = k.decrypt(binascii.a2b_hex(s), padmode=PAD_PKCS5)
return de
# 接受数据
def get_msg():
global scr
global client
global msg_in
while True:
# 接受密文
msg_in = client.recv(1024)
print('\ns2c:',msg_in)
scr.insert('end','(密文)server:'+str(msg_in)[2:-1]+'\n')
# des解密
msg_in=des_descrypt(msg_in).decode()
print('server:',msg_in)
scr.insert('end','(明文)server:'+msg_in+'\n')
# MD5
md5_msg = msg_in
md5 = hashlib.md5()
md5.update(md5_msg.encode('utf-8'))
print('s_MD5:',md5.hexdigest())
scr.insert('end','(MD5)server:'+md5.hexdigest()+'\n\n')
# __mian__
win = tk.Tk()
win.title('CryptTalk客户端') # 名称
win.geometry('500x300+800+200') # 窗口大小
frame = tk.Frame(win,width=450, height=300)
frame.pack()
frame_l = tk.Frame(frame, width=300, height=300)# 第二层frame,左frame,长在主frame上
frame_r = tk.Frame(frame, width=150, height=300)# 第二层frame,右frame,长在主frame上
frame_l.pack(side='left')
frame_r.pack(side='right')
l1 = tk.Label(frame_l, text='消息窗口 ', font=('宋体', 10), width=40,height=2)
l1.pack()
scr = scrolledtext.ScrolledText(frame_l, bg='white', fg='black', font=('宋体', 12), width=30, height=10)
scr.pack()
l3 = tk.Label(frame_l, width=30, height=1)
l3.pack()
l4 = tk.Entry(frame_l, show=None, font=('宋体', 12),width=30)
l4.pack()
l3.pack()
# 发送消息
def fasong():
global client
global msg_out
# 原文
msg_out = l4.get()
print("\nme:",msg_out)
scr.insert('end','(明文)me:'+msg_out+'\n')
# MD5
md5_msg = msg_out
md5 = hashlib.md5()
md5.update(md5_msg.encode('utf-8'))
print('m_MD5:',md5.hexdigest())
scr.insert('end','(MD5)me:'+md5.hexdigest()+'\n')
# des加密
msg_out =msg_out.encode('utf-8')
msg_out = des_encrypt(msg_out)
scr.insert('end','(密文)me:'+str(msg_out)[2:-1]+'\n\n')
print('c2s:',msg_out)
# 发送
client.send(msg_out)
b1 = tk.Button(frame_l, text='发送', font=('宋体', 12), width=10, height=1, command=fasong)
b1.pack()
r1 = tk.Label(frame_r, text='DES密码', font=('宋体', 12), width=20, height=2)
r1.pack()
r2 = tk.Entry(frame_r, show=None, font=('宋体', 12),width=20)
r2.pack()
# 加密后发送des密码
def send_des():
global pubkey
global pubkey_str
global num
global client
global des_key
msg = r2.get()
print('输入的des密码:',msg)
pubkey = rsa.PublicKey.load_pkcs1(pubkey_str.encode())
print('\n接受到的rsa公钥:',pubkey)
crypto = rsa.encrypt(msg.encode("utf-8"), pubkey)
print('\n加密后发送的des密码:',crypto)
client.send(crypto)
if len(msg) > 8:
des_key = msg[:8]
else:
des_key = msg + (8-len(msg))*'0'
print('\ndes_key:',des_key)
# 开启线程接受消息
t = threading.Thread(target = get_msg)
t.start()
b2 = tk.Button(frame_r, text='发送DES密码', font=('宋体', 10), width=10, height=2, command=send_des)
b2.pack()
while True:
pubkey_str = client.recv(1024).decode()
win.iconbitmap('1.ico') # 更改窗口图标
win.mainloop()# 主窗口循环显示
client.close() # 关闭这个链接