20212217刘恒谦 《Python程序设计》实验三报告
课程:《Python程序设计》
班级: 2122
姓名: 刘恒谦
学号:20212217
实验教师:王志强
实验日期:2022年4月23日
必修/选修: 公选课
代码链接:
服务器
https://gitee.com/besti-cs/modest-warehouse/blob/master/服务器.py
`
# 服务器
import socket as sk
def decipher(D:int, N:int, data:bytes)->int:
for i in data:
yield pow(i,D)%N
s = sk.socket(sk.AF_INET, sk.SOCK_STREAM)
s.bind(("", 5050))
s.listen(2)
conn,addr = s.accept()
data = conn.recv(1024)
f = open("C:\Users\Huawei\Desktop\write.txt", "a", encoding="utf-8")
info=bytes(decipher(77,259,data)).decode("utf-8")
f.write(info)
f.close()
print("已接收", info)
s.close()
`
客户端
https://gitee.com/besti-cs/modest-warehouse/blob/master/客户端.py
`
# 客户端
import socket as sk
def encrypt(E: int, N: int, string: str) -> int:
for i in string.encode("utf-8"):
yield pow(i, E) % N
HOST = "127.0.0.1"
# 这个是电脑自己的IP,和别人的电脑交流时要改成别人的IP
PORT = 5050
# 这个要和服务器的端口号一致
s = sk.socket(sk.AF_INET, sk.SOCK_STREAM)
s.connect((HOST, PORT))
# 读取文件
f = open("C:\Users\Huawei\Desktop\read.txt", "r", encoding="utf-8")
msg = f.read()
f.close()
# 发送密文
s.sendall(bytes(encrypt(101, 259, msg)))
data = s.recv(1024)
print("已写入", msg)
s.close()
`
1.实验内容
利用socket进行网络通信,并在客户端读取文件,加密传输至服务端,服务端解密并保存。
2. 实验过程及结果
结合知乎上的资料,基本写出了socket制作服务器和客户端的代码。
服务器的代码如下(初级代码,只能在终端你说一句,我说一句)
`
import socket
HOST = '' #主机
PORT = 5050 #端口
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.bind((HOST, PORT))
#bind(address), 传输层为AF_INET时address是(主机host,端口port)格式
s.listen(2)
conn, addr = s.accept()
#conn新的套接字对象,用于接收发送数据,
# addr客户端地址为元组(hostname, port)
with conn: #while里面只能有recieve和send
print('Connected by', addr)
while True: #server先接收再发送
data = conn.recv(1024)
print(f"{addr}说:{data.decode()}")
server_msg=input("请输入你想回复的内容,输入exit则退出:n")
conn.sendall(server_msg.encode())
if server_msg=="exit":
break
`
作为服务器,首先要能够一直等待来响应用户的请求,因此有了listen方法,它接受监听的最大用户数量,在Python中最多设置5个。如果监听到,那么它就会返回客户对象conn,以及它的IP地址。这个IP地址我们目前还用不着。而用户conn却有很大的用处,在这里我们设置一个监听用户的循环,直到服务器发出exit命令我们才退出。
客户端的代码如下(初级代码,只能在终端你说一句,我说一句)
`
# client.py
import socket
# HOST = 'localhost'
HOST = '192.168.10.191'
PORT = 5050
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.connect((HOST, PORT))
while True: #while里面只能有send和recieve
msg=input("请输入你想传达的信息,传入exit则退出n")
if msg=="exit":
break
# client先发送消息再接收
s.sendall(msg.encode())
data = s.recv(1024)
print(f"他说 {data.decode()}")
`
客户端和服务器类似,只不过不用listen。其他部分都是大同小异的。
3. 实验过程中遇到的问题和解决过程
-RSA加密算法
上网查资料,了解到现代加密算法基本包括RSA,Hash,等算法,其中可解密的加密称双向加密。利用这个关键词,我又去网上查阅了大量资料,决定采用RSA加密算法。它赫赫有名,广为流行,使用较多,算法简单,解密困难。
-
基本思路如下:
不同数据
可以用同样的字符排列组合来代表加密和解密只需要改变这个字符
-
RSA解密算法
N为字符总量,如果有一个D
(密文**D)%N=明文。
(D,N)称为私钥 -
加密算法
如果还有个E
(明文**E)%N=密文
(E,N)称为公钥 -
D和E的制作
选取2个质数:p=3; q=11
质数相乘:N=p*q=33
计算欧拉函数 T=(p-1)(q-1)=20
选取公钥 1st.E是质数;2nd.1<E<T;3st.E不是T的因数
计算私钥 (D *E)%T=1
字符串与字节串
在Python2中,字符以字节的形式在程序里运行。但在Python3之后,字符的编码变复杂了,出现了不同于于Python2的字符串,复杂的字符和简单的字符用着同一套字节却有着不同的编码规则。
Python3中,在字符的""前加b(表示binary二进制)即可表示字节串。bytes_string=b'xe4xbax94xe4xb8x80xe5x8axb3xe5x8axa8xe8x8ax82xe5xbfxabxe4xb9x90'
在网络传输过程中,为了保证字符能够被正确解读,要求发送方和接受方都必须知道传输过程中字符的编码。如果简单的字符和复杂的字符有不同的规则,那么传输的每一个字都必须标注它的编码格式,极大地占用了传输资源。因此,整个文件要有统一的编码标准,传输过程中要将字符串还原成字节串。
- 那么,怎么将str变成bytes呢,很简单,调用encode编码方法即可。
输出如下
字符的数字化不仅使其能在计算机中方便传输,同时也为加密和解密提供了新思路。
本代码中,读取的是明文,写入的是明文。但是发送、传输、接受都用的是密文。我们可以将字符数字化,之后再将其加密,解密。
-
那么怎么将数字变回字符呢?
用decode(解码)方法即可 -
用一张图来表示string和bytes的关系。
图片来源于CSDN,原文链接https://blog.csdn.net/beyondlee2011/article/details/86159151
其他(感悟、思考等)
密码是门大学问,学习密码要有深厚的数学基础。当然落实到计算机上,代码功底也必不可少。
参考资料
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:20212217刘恒谦 实验三《Python程序设计》实验报告 - Python技术站