1. 实验目的
借助异或操作,实现一个简单的文件加密和解密程序。
2. 实验所用仪器(或实验环境)
Python3.6
3. 实验基本原理及步骤(或方案设计及理论计算)
3.1 实验原理:
- 任务1:定义生成随机密钥的函数。函数带有一个参数L;函数生成一个包含L个字节的随机字节串(可以借助secrets包中的token_bytes模块实现),并将随机字节串转换成整数返回。
- 任务2:定义实现加密单元的函数。函数带有一个字符串参数;函数将字符串编码为字节串并转换为整数,然后将它与一个随机密钥进行异或运算生成密文,最后将密文和随机密钥返回。
- 任务3:定义实现解密单元的函数。函数带有两个参数,分别是任务2中函数返回的密文和密钥。函数将密文和密钥进行异或运算,然后计算密文的长度,最后返回解密后的字符串。
- 任务4:利用上面定义的三个函数,对下面两个字符串进行加解密操作。
string1 = “路漫漫其修远兮,吾将上下而求索。”
string2 = “Never put off until tomorrow what may be done today.” - 任务5:利用json 模块和pathlib包中的Path模块,分别定义一个加密文本文件的函数和一个解密文本文件的函数。
提示:在实验过程中,用help()和dir()等帮助函数查阅相关模块、函数和方法的用法。
3.2 实验步骤:
按照二进制数异或的原理,对文本文件进行加解密。
- 加密操作
首先将文本文件转换为二进制数,再生成与该二进制数等长的随机密钥,将二进制数与密钥进行异或操作,得到加密后的二进制数。 - 解密操作
将加密后的二进制文件与密钥进行异或操作,得到原来的二进制数,再将二进制数恢复成文本文件。
4. 实验数据记录(或仿真及软件设计)
4.1 任务一:
4.1.1 代码:
import secrets
def generateM(L):
bys=secrets.token_bytes(L) #返回包含nbytes个字节的字节字符串。
# 转化成整数M
# 只能用这个函数,用decode编码处理不了
M=int.from_bytes(bys,byteorder='little',signed='true')
return M
#print(generateM(10))
4.1.2 截图:
4.2 任务二:
代码:
def jiami(s):
#字符串编码为字节串
s=s.encode()
length=len(s)
#转换为整数
zhengshu=int.from_bytes(s, byteorder='big',signed='true')
#整数与密钥进行异或运算生成密文
miyao=generateIntM(length)
miwen=miyao^zhengshu
return {'miyao': miyao,'miwen': miwen}
4.3 任务三:
代码:
def jiemi(miwen,miyao):
afterJiemi=miwen^miyao
#计算密文的长度,注意这里的+7/8
length=int((afterJiemi.bit_length()+7)/8)
#转化成字节流
afterJiemi=int.to_bytes(afterJiemi,length,byteorder='big',signed='true')
#解码成字符串
afterJiemi=afterJiemi.decode()
return afterJiemi
4.4 任务四:
代码:
string1 = "路漫漫其修远兮,吾将上下而求索。"
string2 = "Never put off until tomorrow what may be done today."
#加密
JAM=jiami(string1)
print(JAM)
#解密
JEM=jiemi(JAM['miwen'],JAM['miyao'])
print(JEM)
#字符串2
JAM2=jiami(string2)
print(JAM2)
JEM2=jiemi(JAM2['miwen'],JAM2['miyao'])
print(JEM2)
以上四个任务运行截图:
4.5 任务五:
4.5.1 代码:
#加密文件
def jiamiText(path):
path=Path(path) #此处为密钥路径
jiamipath=input("请输入加密文件路径:")
jiemipath=input("请输入加密后文件路径:")
#如果你要处理的是文件而不是字符串,你可以使用 json.dump() 和 json.load() 来编码和解码JSON数据。
with open(path,'wt',encoding='utf-8') as fp0 , \
open(jiamipath,'rt',encoding='utf-8') as fp1 , \
open(jiemipath,'wt',encoding='utf-8') as fp2 :
#读取加密文件内容
jiamitxt=jiami(fp1.read())
#返回加密后的密文,密钥,并写入文件中
miwen1,miyao1=jiamitxt['miwen'],jiamitxt['miyao']
json.dump(miyao1,fp0)
json.dump(miwen1,fp2)
#解密文件
def jiemiText():
miyao_path=input("请输入密钥路径:")
miwen_path=input("请输入待解密文件路径:")
jiemi_path=input("请输入解密后文件路径:")
with open(miwen_path,'rt',encoding='utf-8') as fp1 , \
open(miyao_path,'rt',encoding='utf-8') as fp2, \
open(jiemi_path,'wt',encoding='utf-8') as fp3 :
#解密操作
jiemitxt=jiemi(json.load(fp2), json.load(fp1))
fp3.write(jiemitxt)
path=input("要写入的密钥路径:")
jiamiText(path)
jiemiText()
4.5.2 截图:
五、实验结果分析及回答问题(或测试环境及测试结果)
本次实验有几个难点:
- 将字节流转化成数字,采用:int.from_bytes()函数,我尝试str()进行编码,发现不可行。
- 在解密过程中计算密文的长度,length=int((afterJiemi.bit_length()+7)/8)
如果不采用+7将会出现溢出错误。 - 在于使用json于Path模块,之前没有使用过,正好通过这次了解学习查阅doc文档。