python AES加密 客户端与服务端通信

一、 实验目的及要求
实验目的:
(1)
掌握身份认证的基本概念;
(2)
掌握报文认证的基本思想;
(3)
掌握 C/S 框架下的认证协议。
实验要求:
(1)实现可靠的安全的通信协议
二、实验设备(环境)及要求
Windows 操作系统,高级语言开发环境 python
三、实验内容与步骤
实验步骤:
1. 创建 sever 代码,以实现服务器端的功能,用来接收和验证消息;
2. 创建 client 代码,以实现客户端的功能,用来接收和验证消息;
3. 创建 E_C 代码,用来实现发送方传输的消息的加密,实现接收方的解密。
3.客户 A 要先发送一个随机码,这个码需要加密,加密的秘钥是对称秘钥。接下来,服务器
B 收到这个密文,然后进行解密,进行处理 f(x),然后在将 f(x)加密发送给客户端,客户端收
到后对其进行解密,得到 M2。因为双方先约定了方 f(x)这个函数的实现方法,所以发送方
只要把随机数进行 f(x)变换后的东西与 M2 比较,如果相同认为 B 是意定的站点,可以与之
通信,否则,A 认为 B 不是意定的站点,不能与之通信。
实验原理:
1.认证:是一个过程,通过这个过程,一个实体可以向另一个实体证明某种声称的属性。
协议:在两方或相互协作的多方之间进行通信的过程。因此,一个认证过程也是一个
认证协议。认证协议是安全协议的一种。
认证可以分为那些类别?
(1)单方认证(2)双方认证(3)包含可信第三方的认证
在本次实验中我实现的是基于 C/S 框架下的单向认证协议。
在建立传输链路时,我们要使用的是对称加密 AES 算法,因为这样的速度高,可加密的内
容多,可以用来加密会话过程中的消息。
首先我们需要创建一个具有加解密的函数的代码,我先对要加密的字符串做了处理,就是因
为 AES 是加密 32 字节(256 位)的,因此我需要补零来保证字符串长度是 32 的倍数,然
后对其进行加密,然后进行 base64 编码。如下所示:
import base64
from Crypto.Cipher import AES
# bytes 不是 32 的倍数那就补足为 32 的倍数
def add_to_32(value):
while len(value) % 32 != 0:
value += b'\x00'
return value
# 返回 bytes
# str 转换为 bytes 超过 32 位时处理
def cut_value(org_str):
org_bytes = str.encode(org_str)
n = int(len(org_bytes) / 32)
#print('bytes 长度:',len(org_bytes))
i = 0
new_bytes = b''
while n >= 1:
i = i + 1
new_byte = org_bytes[(i-1)*32:32*i-1]
new_bytes += new_byte
n = n - 1
if len(org_bytes) % 32 == 0:
# 如果是 32 的倍数,直接取值
all_bytes = org_bytes
elif len(org_bytes) % 32 != 0 and n>1:
# 如果不是 32 的倍数,每次截取 32 位相加,
最后再加剩下的并补齐 32 位
all_bytes = new_bytes + add_to_32 (org_bytes[i*32:])
else:
all_bytes = add_to_32 (org_bytes)
# 如果不是 32 的倍数,并且小于 32 位直接补
齐#print(all_bytes)
return all_bytes
def AES_encrypt(org_str,key):
# 初始化加密器
aes = AES.new(cut_value(key), AES.MODE_ECB)
#先进行 aes 加密
encrypt_aes = aes.encrypt(cut_value(org_str))
# 用 base64 转成字符串形式
encrypted_text = str(base64.encodebytes(encrypt_aes), encoding='utf-8') # 执行加密并
转码返回 bytes
#print(encrypted_text)
return(encrypted_text)
def AES_decrypt(secret_str,key):
# 初始化加密器
aes = AES.new(cut_value(key), AES.MODE_ECB)
# 优先逆向解密 base64 成 bytes
base64_decrypted = base64.decodebytes(secret_str.encode(encoding='utf-8'))
# 执行解密密并转码返回 str
decrypted_text = str(aes.decrypt(base64_decrypted), encoding='utf-8').replace('\0', '')
return decrypted_text
def jiami(mingwen):
key='12#aOc2&*22dfwfrvfasdewrgtegsfdw'
secret_str = AES_encrypt(mingwen,key)
secret_str = secret_str.replace("\n", "")
return secret_str
进行解密的话,要先逆向 base64 编码,然后再 AES 解密算法解密。
def jiemi(miwen):
key='12#aOc2&*22dfwfrvfasdewrgtegsfdw'
result=AES_decrypt(miwen,key)
return result
然后我们创建服务端的代码文件,采用的是 TCP 协议。传输控制协议 TCP 是一种面向连接
(连接导向)的、可靠的、基于字节流的运输层(Transport layer)通信协议。在简化的计
算机网络 OSI 模型中,它完成第四层传输层所指定的功能。在代码中我们 import socket,这
样我们就可以实现 TCP 的连接与释放,我设置的端口为 8888,可以连接的主机数最多为 5,
然后监听 A 发过来的消息,并且返回验证,如果 A 是确实要和服务器 B 通信,那么这个连
接就不会断,如果 A 不是要和 B 通信,那么 A 就会自动断开这个连接,而其他人连接 B 不
会受到影响。代码如下:from socket import *;
from time import ctime;
import E_C
host = "localhost";#服务器地址
port = 8888;#端口
#创建 Socket
tcpSocket = socket(AF_INET, SOCK_STREAM);
#绑定
tcpSocket.bind((host, port));
#设置最大连接数,超过后排队
tcpSocket.listen(5);
while True:
#建立连接
connect, addr = tcpSocket.accept();
data = connect.recv(1024);
data_result = str(data, "utf-8");
print(data_result)
#解密
mingwen=E_C.jiemi(data_result)
mingwen=mingwen+'1234'
#发送数据给客户端
mingwen_2=bytes(mingwen,"utf8")
connect.sendall(mingwen_2)
while True:
#接收客户端发来的数据并且小于 1024 字节的数据
data = connect.recv(1024);
#如果客户端退出,则执行以下语句
if not data:
break
#转换
data_result = str(data, "utf-8");
print(data_result)
print(E_C.jiemi(data_result))
recv_result = bytes("Recieved", "utf-8");
#发送数据给客户端
connect.sendall(recv_result)
#关闭连接套接字
connect.close()
#关闭套接字
tcpSocket.close();
然后在建立客户端的代码,以实现 C/S 架构下的认证协议。这个代码的功能就是先产生一个
随机数 a,然后把 a 转成字符串类型,对其进行加密,然后发送给服务端,同时对 a 进行一个变换,这里我选择的变换是在字符串的末尾添加上“1234”
之后受到的 B 发来的认证消息如果不正确,那么就会关闭套接字,断开连接。如果认证通
过,那么 A、B 之间可以继续进行通信。从而保证 B 不是第 3 人。
from socket import *;
import math
import random
import E_C
host = "localhost";#服务器地址
port = 8888;#端口
a=str(random.randint(1000,10000))#随机数 a
#创建 Socket
tcpSocket = socket(AF_INET, SOCK_STREAM);
#与服务端建立连接
tcpSocket.connect((host, port));
if (a>"0"):
send_info=E_C.jiami(a)
#加密 a,发送密文给 B,A 和 B 要做同一个置换即 a=a+"1234"
#发送数据给服务端
tcpSocket.sendall(bytes(send_info, "utf-8"));
#接收 B 发送过来的确认信息,与变换后的 a 做比较
recv_info = tcpSocket.recv(1024);
a=a+'1234'
if (str(recv_info, "utf-8")==a):
print("B 是合法的")
else:
print("B 是不合法的,不能继续通信")
tcpSocket.close();
while True:
send_info =input(">");
#如果输入 exit,则执行以下语句
if send_info == "exit":
break;
#发送数据给服务端
send_info=E_C.jiami(send_info)
tcpSocket.sendall(bytes(send_info, "utf-8"));
#接收服务端的数据
recv_info = tcpSocket.recv(1024);
print("服务端返回的内容是:" + str(recv_info, "utf-8"));
#关闭套接字
tcpSocket.close();
四、实验结果与数据
实验结果表示,在使用相同的秘钥时 A 发送的随机数 B 收到后返回来的是正确的。双方可
以互相通信,客户端 A 发送的全部消息都经过 AES 加密,而服务器 B 会收到 A 发送的密文,
然后进行解密打印出来,然后给 A 回复“Recieved”

猜你喜欢

转载自www.cnblogs.com/0001lizhubo/p/12076092.html