ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

20213306 实验三《Python程序设计》实验报告

2022-04-26 21:02:04  阅读:202  来源: 互联网

标签:20213306 Python text self &% key encode 实验报告 key1


20213306《Python程序设计》实验三报告

课程:《Python程序设计》
班级:2133
姓名:李鹏宇
学号:20213306
实验教师:王志强
实验日期:2022年4月21日
必修/选修: 公选课

1.实验内容

创建服务端和客户端,服务端在特定端口监听多个客户请求。客户端和服务端通过Socket套接字(TCP/UDP)进行通信。

2.实验要求

  • 创建服务端和客户端,选择一个通信端口,用Python语言编程实现通信演示程序;
  • 要求包含文件的基本操作,例如打开和读写操作。
  • 要求发送方从文件读取内容,加密后并传输;接收方收到密文并解密,保存在文件中。
  • 程序代码托管到码云。

3. 实验过程及结果

3.1 代码

客户端

import socket      
import datetime#以当前日期加密  
from Crypto.Cipher import AES
from binascii import b2a_hex, a2b_hex
class AesCrypto():#支持中文的AES
    def __init__(self, key, IV):
        self.key = key #需为16位倍数
        self.iv = IV #必须为16位
        self.mode = AES.MODE_CBC
    def encrypt(self, text):
        cryptor = AES.new(self.key, self.mode, self.iv)
        length = 16
        count = len(text)
        if(count%length != 0):
            add = length-(count%length)
        else:
            add=0

        text = text+("\0".encode()*add)#因为中文位数原因,这里需要.encode

        self.ciphertext = cryptor.encrypt(text)
        return (self.ciphertext)
    
    def decrypt(self, text):
        cryptor = AES.new(self.key, self.mode, self.iv)
        plain_text = cryptor.decrypt((text)).decode()
        return plain_text
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
print("欢迎来到客户端")
port = input("请输入连接端口号")
s.connect(('localhost',int(port))) #暂时本地传输本地
mo = input("请选择模式\n1.文字2.传输文件")
if mo == '1':
    s.sendall(mo.encode())
    str1 = input("请输入传输内容")
    k = datetime.date.today()
    key1 = k.__format__('%Y&%m&%d%j%U%w').encode()
    mo1 = AesCrypto(key=key1, IV=key1)
    str1 = mo1.encrypt(str1.encode())
    s.sendall(str1)
    data = s.recv(1024)
    print(data.decode())
elif mo == '2':#文件传输
    s.sendall(mo.encode())
    mo2mo = input("新建文件请输入1,传输已有文件请输入2")
    addre = input("请输入文件路径")
    k = datetime.date.today()
    key1 = k.__format__('%Y&%m&%d%j%U%w').encode()
    mo2 = AesCrypto(key=key1, IV=key1)
    addre1 = mo2.encrypt(addre.encode())
    s.sendall(addre1)
    if mo2mo == "1":
        file1 = open(addre,"w+",encoding="utf-8")#新建文件
        neirong = input("请输入内容")
        file1.write(neirong)
        file1.close()
        file1 = open(addre,"r",encoding="utf-8")
    elif mo2mo == "2":
        file1 = open(addre,"r",encoding="utf-8")#只读
    file1.seek(0)
    str1 = file1.readlines()
    file1.close()
    lenfile = len(str1)#获取文件有几行
    lenfile = str(lenfile)
    k = datetime.date.today()
    key1 = k.__format__('%Y&%m&%d%j%U%w').encode()
    mo2 = AesCrypto(key=key1, IV=key1)
    lenfile = mo2.encrypt(lenfile.encode())#将文件行数发出去
    s.sendall(lenfile)
    for i in str1:#对于文件的每一行顺序发送
        k = datetime.date.today()
        key1 = k.__format__('%Y&%m&%d%j%U%w').encode()
        mo2 = AesCrypto(key=key1, IV=key1)
        i = mo2.encrypt(i.encode())
        s.sendall(i)
    data = s.recv(1024)#接收“已收到”信息
    print(data.decode())
s.close

服务端

import socket      
import datetime  
from Crypto.Cipher import AES
from binascii import b2a_hex, a2b_hex
class AesCrypto():
    def __init__(self, key, IV):
        self.key = key
        self.iv = IV
        self.mode = AES.MODE_CBC
    def encrypt(self, text):
        cryptor = AES.new(self.key, self.mode, self.iv)
        length = 16
        count = len(text)
        if(count%length != 0):
            add = length-(count%length)
        else:
            add=0

        text = text+("\0".encode()*add)

        self.ciphertext = cryptor.encrypt(text)
        return (self.ciphertext)
    
    def decrypt(self, text):
        cryptor = AES.new(self.key, self.mode, self.iv)
        plain_text = cryptor.decrypt((text)).decode('utf8','ignore')
        return plain_text#加密解密同理
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
port = input("欢迎使用服务端\n请输入开放连接端口号")
s.bind(("localhost", int(port)))#这里只写端口号没问题
s.listen()
con,addr= s.accept()
mo = con.recv(1024)
if mo.decode()== '1':
    print("已收到文字传输请求,对方正在输入...")
    data = con.recv(1024)
    k = datetime.date.today()
    key1 = k.__format__('%Y&%m&%d%j%U%w').encode()
    mo1 = AesCrypto(key=key1, IV=key1)
    data = mo1.decrypt(data)
    print(data)
    right = "信息已收到"#类似状态码,就没有加密
    con.sendall(right.encode())
elif mo.decode()=='2':
    print("已收到文件传输请求,对方正在输入...")
    addre = con.recv(1024)
    k = datetime.date.today()
    key1 = k.__format__('%Y&%m&%d%j%U%w').encode()
    mo2 = AesCrypto(key=key1, IV=key1)
    addre = mo2.decrypt(addre)
    addre = addre.encode()
    addre = addre.split(b"\x00")[0].decode("utf-8")#防‘\’导致打开文件不存在的问题
    file1 = open(addre+"1.txt","w+",encoding="utf-8")#为测试方便多加了后缀
    lenfile1 = con.recv(1024)
    k = datetime.date.today()
    key1 = k.__format__('%Y&%m&%d%j%U%w').encode()
    mo2 = AesCrypto(key=key1, IV=key1)
    lenfile1 = mo2.decrypt(lenfile1)
    lenfile1 = lenfile1.encode()
    lenfile1 = lenfile1.split(b"\x00")[0].decode("utf-8")
    lenfile1 = int(lenfile1)#解码文件行数
    for temp in range(1,lenfile1+1):
        temp = con.recv(1024)
        k = datetime.date.today()
        key1 = k.__format__('%Y&%m&%d%j%U%w').encode()
        mo2 = AesCrypto(key=key1, IV=key1)
        temp = mo2.decrypt(temp)
        temp = temp.encode()
        temp = temp.split(b"\x00")[0].decode("utf-8")#防字符串解密问题
        print(temp)#显示一下内容
        file1.write(temp)#写入文件
    file1.close()
    right = "文件传输完成"
    con.sendall(right.encode())
    print("文件已接收")
s.close

测试截图




上传gitee截图

4. 实验过程中遇到的问题和解决过程

  • 问题1:AES加密方式无法加密中文
  • 问题1解决方案:借用了csdn上一篇文章的的方案
  • 问题2:错误“ValueError:数据必须与 ECB 模式下的块边界对齐”
  • 问题2解决方案:补齐时中文需要encode
  • 问题3:错误“UnicodeDecodeError: ‘utf-8‘ codec can‘t decode byte 0xca in position 0: invalid continuation byte”
  • 问题3解决方案:转码错误,应严格按照utf-8方式
  • 问题4:路径传输时无法打开对应路径
  • 问题4解决方案:将接收到的多余‘/’删除

其他(感悟、思考等)

这次实验中,我在aes加解密和bytes与str类型转换上耗费了大量的时间,这次实验让我意识到了尽管python的变量开始时是自适应的,但每个函数要求的变量不是能够通过简单的强制转换就能满足的,有时即使用正确的方式也会得到错误的结果。应该善用调试,灵活的去判断传输时每个变量的具体情况。同时,对于file方法掌握仍然不熟练,尤其是常常分不清某时指针的位置,是否创建了新文件等等,在以后会更加深入的去了解。

参考资料

标签:20213306,Python,text,self,&%,key,encode,实验报告,key1
来源: https://www.cnblogs.com/lpy007/p/16196422.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有