zoukankan      html  css  js  c++  java
  • 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()
  • 相关阅读:
    J2SE总结
    OSI模型与TCP/IP协议族
    poppler交叉编译
    摆脱技术思维,转向产品思维——寻找“万能”IDC的苦恼
    面向自由职业者和小型企业的开源开票工具
    3星|《中国做对了什么》:十几年前的文章集了,依旧不过时
    2星|《巴菲特致股东的信》:标题党,实际是1996年一次研讨会的发言记录,没有致股东的信
    3星|《不会被机器替代的人》:人在被服务的时候,更喜欢面对面跟人打交道,而不是跟机器打交道
    3星|《提高职场执行力》:执行力难关的根源是对话的无效性
    2星|《工业X.0》:物联网的资料汇编
  • 原文地址:https://www.cnblogs.com/pu369/p/15420768.html
Copyright © 2011-2022 走看看