-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.py
More file actions
224 lines (213 loc) · 9.75 KB
/
Copy pathmain.py
File metadata and controls
224 lines (213 loc) · 9.75 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
from sm4 import SM4Key
from PySide2.QtWidgets import *
from PySide2.QtUiTools import QUiLoader
from PySide2.QtCore import QFile,QThread
from Crypto.Cipher import AES
import hashlib
#import tkinter.filedialog
import os,sys
#import time,_thread
# 添加ui文件,main window
def md5(a_Str):
a=hashlib.md5()
a.update(a_Str.encode())
return a.digest()
#加密使用的线程
class encryThread(QThread):
def __init__(self):
super().__init__()
def run(self):
click_Toencry_Thread()
def encry_thread():
#启动加密的线程的函数
aa=encryThread()
aa.run()
class decryThread(QThread):
def __init__(self):
super().__init__()
def run(self):
click_Todecry_Thread()
def decry_thread():
#启动解密的线程的函数
aa=decryThread()
#aa.start()
aa.run()
class Mw():
def __init__(self):
qfile = QFile("./ui/main.ui")
qfile.open(QFile.ReadOnly)
qfile.close()
self.window = QUiLoader().load(qfile)
self.window.progressBar.setMinimum(0)
self.window.progressBar.setMaximum(100)#默认100吧
self.window.progressBar.setValue(0)
def empty_Text():
#清空消息
self.window.progressBar.setValue(0)
self.window.text_show.clear()
def click_Exit():
sys.exit()
self.window.encry_button.clicked.connect(encry_thread)#加密
self.window.decry_button.clicked.connect(decry_thread)#解密
self.window.exit_button.clicked.connect(click_Exit)#退出
self.window.empty_button.clicked.connect(empty_Text)#清空消息
#Qt窗口的接口
def get_input_text(self):
#获取设置文件名的接口
return self.window.setting.text()
def get_Password(self):
#获取写入的密码
return self.window.password_input.text()
def set_ProgressBar_value(self,num):
self.window.progressBar.setValue(num)
def show_Text(self,message):
#展示输出函数
self.window.text_show.insertPlainText(message+'\n')
def set_ProgressBar_Max(self,max):
#设定进度条最大值接口,max是整数
self.window.progressBar.setMaximum(max)
def get_AES_Checked(self):
return self.window.AES_Check.isChecked()
app = QApplication([])
a=Mw()
a.window.show()
#加密的线程
def click_Toencry_Thread(**args):
#读取16,加密,然后write
AES_Checked=a.get_AES_Checked()
password=a.get_Password()#获取输入的密码
if(len(password)==0):
a.show_Text("请先输入密码")
return -1
password=md5(password)
files=QFileDialog.getOpenFileNames()[0]
if(len(files) == 0):#用户取消
return 0
for input in files:
#获取文件的名字
filenamesplit=os.path.split(input)
filename=filenamesplit[1]
#获取/设定输出文件的名字
outputFileName = a.get_input_text()
if outputFileName!='':
outputFileName=a.get_input_text()+".encry"
else:
outputFileName=filename+".encry"
save_file=open(filenamesplit[0]+"/"+outputFileName,"wb")#保存文件的路径
if(AES_Checked):
cipher=AES.new(password,AES.MODE_ECB)#ECB不需要向量
else:
cipher=SM4Key(password)#SM4默认ECB模式,这里不使用ECB模式
spliteSize=1024*1024#文件分片大小,默认1024*1024,最大1MB,最后一个设定16bytes
#读取文件16进制
encring_file=open(input,'rb')
filesize=os.path.getsize(input)#获取文件长度,bytes
ite_1MB=filesize//spliteSize#获得1024*1024分片的迭代次数
ite_16bytes=(filesize%spliteSize)//16#获得16分片的迭代次数
sum_ite=ite_16bytes+ite_1MB#总的迭代次数,用于显示进度条
a.set_ProgressBar_Max(sum_ite+1)#设定进度条最大值
addDataLeng=16-(filesize%16)
#addData=(16-(filesize%16))*b'\0'#要添加到后面的数据
#addDataLeng=len(addData) #这里使用PKCS5 padding 后面添加N个N
if(addDataLeng==16):
#16=0x10,这里需要特殊处理一下
addData=16*b'\x10'
else:
addData=hex(addDataLeng)[2:] #去掉0x
addData='0'+addData
addData=bytes.fromhex(addData)
addData=addData*addDataLeng #这里使用PKCS5 padding 后面添加N个N
#print(addData)
a.show_Text("filesize:"+str(filesize))
progressBarValue=0
#先迭代前面的数据,大于1MB的数据
for _ in range(0,ite_1MB):
one_encry_chars=encring_file.read(spliteSize)#一次加密读取的数据
encrypted_content=cipher.encrypt(one_encry_chars)
save_file.write(encrypted_content)#写入一次的数据
a.set_ProgressBar_value(progressBarValue)
progressBarValue+=1
for _ in range(0,ite_16bytes):
one_encry_chars=encring_file.read(16)#一次加密读取的数据
encrypted_content=cipher.encrypt(one_encry_chars)
save_file.write(encrypted_content)#写入一次的数据
progressBarValue+=1
a.set_ProgressBar_value(progressBarValue)
one_encry_chars=encring_file.read(16)#最后一次读取,可能是0,但仍加addData
one_encry_chars+=addData
encrypted_content=cipher.encrypt(one_encry_chars)
save_file.write(encrypted_content)#写入最后一次的数据
save_file.close()
encring_file.close()
a.set_ProgressBar_value(progressBarValue+1)#进度条100%
a.show_Text("加密成功,文件保存在"+filenamesplit[0]+"/"+outputFileName)
#解密的线程
def click_Todecry_Thread(**args):
AES_Checked=a.get_AES_Checked()
#一边读取,解密,然后write
password=a.get_Password()#获取输入的密码
if(len(password)==0):
a.show_Text("请先输入密码")
return -1
password=md5(password)
#input=tkinter.filedialog.askopenfilename()#完整的路径
files=QFileDialog.getOpenFileNames()[0]
if(len(files)==0):
#用户取消
return 0
for input in files:
print(input)
#获取文件的名字
filenamesplit=os.path.split(input)
filename=filenamesplit[1]
#获取/设定输出文件的名字
outputFileName=filename[:-6]
save_file=open(filenamesplit[0]+"/decriedfile_"+outputFileName,"wb")#保存文件的路径
if(AES_Checked):
cipher=AES.new(password,AES.MODE_ECB)#ECB不需要向量
else:
cipher=SM4Key(password)
spliteSize=1024*1024#文件分片大小,默认1024*1024
#读取文件16进制
decring_file=open(input,'rb')
filesize=os.path.getsize(input)#获取文件长度,bytes
ite_1MB=filesize//spliteSize#获得1024*1024分片的迭代次数
ite_16bytes=(filesize%spliteSize)//16#获得16分片的迭代次数
if(ite_16bytes==0):
#这里防止解密数据刚好是1MB的倍数
if(ite_1MB==0):
#如果这里1MB的迭代次数==0,说明这个文件大小为0,出错
a.show_Text("Error! the file has no data?")
return
ite_1MB-=1
ite_16bytes+=1024*1024 #将减去的迭代次数加在16bytes上
sum_ite=ite_16bytes+ite_1MB#总的迭代次数,用于显示进度条
a.set_ProgressBar_Max(sum_ite+1)#设定进度条最大值
progressBarValue=0
#先迭代前面的数据,大于1MB的数据
for _ in range(0,ite_1MB):
one_encry_chars=decring_file.read(spliteSize)#一次加密读取的数据
encrypted_content=cipher.decrypt(one_encry_chars)
save_file.write(encrypted_content)#写入一次的数据
a.set_ProgressBar_value(progressBarValue)
progressBarValue+=1
for _ in range(0,ite_16bytes-1):
#这个循环不一定进,迭代次数减一,剪出来的有padding所以特殊处理
one_encry_chars=decring_file.read(16)#一次加密读取的数据
encrypted_content=cipher.decrypt(one_encry_chars)
save_file.write(encrypted_content)#写入一次的数据
progressBarValue+=1
a.set_ProgressBar_value(progressBarValue)
#对最后一行进行特殊处理,因为这里有padding
one_encry_chars=decring_file.read(16)#一次加密读取的数据
encrypted_content=cipher.decrypt(one_encry_chars)
subdataLeng=encrypted_content[15] #要减去的字节个数,看最后一个字节是什么(PKCS5 padding)
encrypted_content=encrypted_content[:16-subdataLeng]
save_file.write(encrypted_content)#写入一次的数据
save_file.close()
decring_file.close()
progressBarValue+=1
a.set_ProgressBar_value(progressBarValue)
a.set_ProgressBar_value(progressBarValue+1)#进度条100%
a.show_Text("解密成功,文件保存在"+filenamesplit[0]+"/decriedfile_"+outputFileName)
app.exec_() #暂停