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)
mainloop()

  

補充:后來電腦重裝了,雙擊這個.pyw運行不起來,執行:  pip install  cryptography  ,然后直接雙擊腳本仍不行。於是打開IDLE加載這個腳本,竟然運行成功了,奇怪。

后來又一次重裝電腦及python,並pip 安裝相關的庫后,又正常了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM