python实现aes-256-gcm加密和解密-自已动手写个加解密软件(二)
之前用golang写了个练手的加解密https://www.cnblogs.com/pu369/p/12924007.html,但是思路有点问题,于是用python重新写了一个能够实用的
#-*- coding: utf-8 -*- #文件后缀pyw可隐藏命令行窗口 from cryptography.hazmat.primitives.ciphers.aead import AESGCM from tkinter import Tk,mainloop,StringVar,Frame,Text,Scrollbar,Toplevel,Entry,Button,Label,messagebox #可用*代替 import sys,os,time import hashlib,binascii,base64,cryptography.exceptions encryptfile = __file__.split("\\")[-1].split(".")[0] #加密文件名与脚本名相同 if os.path.exists(encryptfile): if os.path.isdir(encryptfile): messagebox.showinfo(title=\'提示\', message=\'当前目录不允许有脚本同名的文件夹\') sys.exit(0) else: with open(encryptfile,\'w\') as f: pass #time.sleep(1) #等待创建文件 root = Tk()# 初始化 root.title(encryptfile) root.geometry(\'1500x700+100+100\') #长x宽+左上角x和y #双向绑定变量 password0 = StringVar(value="") password1 = StringVar(value="") password_login = StringVar(value="") #全局变量 saved_cipher_base64 =b"" #加密函数 def encrypt_aes256gcm(key, ciphertext, aad): \'\'\' aes-256-gcm 加密 key: 为str,hex字符串,64字符(32字节) aad: 为str,hex字符串,32字符(16字节) ciphertext: 为bytes, 明文 返回: 为bytes, base64 的密文 \'\'\' aes_gcm_ivlen = 12 key_bytes = binascii.unhexlify(key) aad_bytes = binascii.unhexlify(aad) data = ciphertext iv_bytes = os.urandom(aes_gcm_ivlen) aesgcm = AESGCM(key_bytes) # tag_length=16 crypt_bytes = aesgcm.encrypt(iv_bytes, data, aad_bytes) return base64.b64encode(iv_bytes + crypt_bytes) #解密函数 def decrypt_aes256gcm(key, ciphertext, aad): \'\'\' aes-256-gcm 解密 key: 为str,hex字符串,64字符(32字节) aad: 为str,hex字符串,32字符(16字节) ciphertext: 为bytes, base64 的密文 返回: bytes 的明文, 或者解密失败 返回 b\'\' \'\'\' aes_gcm_ivlen = 12 key_bytes = binascii.unhexlify(key) aad_bytes = binascii.unhexlify(aad) try: data = base64.b64decode(ciphertext) except binascii.Error as e: return b\'\' iv_bytes = data[0:aes_gcm_ivlen] data = data[aes_gcm_ivlen:] aesgcm = AESGCM(key_bytes) # tag_length=16 try: text_bytes = aesgcm.decrypt(iv_bytes, data, aad_bytes) except cryptography.exceptions.InvalidTag as e: return b\'\' return text_bytes #加密文件,并存盘 def enc_writef(): \'\'\' aes-256-gcm 加密 key: 为str,hex字符串,64字符(32字节) aad: 为str,hex字符串,32字符(16字节) ciphertext: 为bytes, 明文 返回: 为bytes, base64 的密文 \'\'\' with open(encryptfile,\'wb\') as f: contents = text_box.get(\'0.0\', \'end\')#明文str contents_bytes = base64.b64encode(contents.encode())#转为Base64byes m = hashlib.md5(password0.get().encode()) aad =m.hexdigest() m = hashlib.sha3_256(password0.get().encode()) key =m.hexdigest() ciphertext_bytes = encrypt_aes256gcm(key, contents_bytes, aad) try: f.write(ciphertext_bytes) messagebox.showinfo(title=\'成功\', message=\'已经加密保存!\') root.destroy() except: messagebox.showinfo(title=\'成功\', message=\'已经加密保存!\') root.destroy() #两次输入密码确认 def btn_pw(): if password0.get()=="": messagebox.showinfo(title=\'错误\', message=\'密码不能为空\') elif password0.get()!=password1.get(): messagebox.showinfo(title=\'错误\', message=\'两次密码不一致\') else: enc_writef() #保存并退出按钮 def btn_save(): if messagebox.askokcancel(\'提示\',\'确认保存并退出?\'): #动态生成密码输入窗体 top_level = Toplevel() top_level.geometry(\'300x100+100+100\') #长x宽+左上角x和y top_level.title("请输入密码") entry_pw1 = Entry(top_level,textvariable=password0,show=\'*\') entry_pw1.grid(column=0,row=0) entry_pw2 = Entry(top_level,textvariable=password1,show=\'*\') entry_pw2.grid(column=0,row=1) button_pw = Button(top_level,text=\'确定\', command=btn_pw) button_pw.grid(column=0,row=2) top_level.attributes("-toolwindow", 1) top_level.wm_attributes("-topmost", 1) button_save = Button(root,text=\'保存并退出\', command=btn_save) button_save.grid(column=0,row=0) #文本框控件 width 单行可见字符# height 显示行数#autoseparators撤销操作分隔符 text_box = Text(root, width=100, height=20, undo=True, autoseparators=False) text_box.grid(column=0,row=2,columnspan=10) text_box.config(font=("宋体", 20)) #解密文件,并加载至GUI def btn_login(): m = hashlib.md5(password_login.get().encode()) aad =m.hexdigest() m = hashlib.sha3_256(password_login.get().encode()) key =m.hexdigest() try: plain_text_base64 = decrypt_aes256gcm(key,saved_cipher_base64, aad) if plain_text_base64 ==b"": messagebox.showinfo(title=\'失败\', message=\'解密失败!\') root.destroy() else: temp = base64.b64decode(plain_text_base64) plain_result = temp.decode() text_box.insert(\'insert\',plain_result) top_level.withdraw() messagebox.showinfo(title=\'成功\', message=\'解密成功!\') except: messagebox.showinfo(title=\'失败\', message=\'解密失败!\') root.destroy() #读取密文,保存为全局变量,并判断是否为空 with open(encryptfile,\'rb\') as f: saved_cipher_base64 = f.read() if saved_cipher_base64 ==b"":#刚刚建立的新密码本 pass else: #弹出解密密码窗体 top_level = Toplevel() top_level.geometry(\'300x100+100+100\') #长x宽+左上角x和y top_level.title("请输入解密密码") entry_pw = Entry(top_level,textvariable=password_login,show=\'*\') entry_pw.grid(column=0,row=0) button_pw = Button(top_level,text=\'确定\', command=btn_login) button_pw.grid(column=0,row=2) top_level.attributes("-toolwindow", 1) top_level.wm_attributes("-topmost", 1) #文本框加滚动条 scroll=Scrollbar() scroll.grid(column=10,row=2,sticky="NS") #文本框与滚动条关联 scroll.config(command=text_box.yview) text_box.config(yscrollcommand=scroll.set) #插入日期时间快捷键 def btn_cur_time(): cur_time = time.strftime(\'%Y-%m-%d %H:%M:%S \',time.localtime(time.time())) text_box.insert(\'insert\',cur_time) button_save = Button(root,text=\'插入日期时间\', command=btn_cur_time) button_save.grid(column=1,row=0) mainloop()