Python 對稱式加密
在 Python 中實現對稱式加密(Symmetric Encryption),最標準且安全的方法是使用 AES (Advanced Encryption Standard)。
為了確保安全性,我們通常會使用 cryptography 這個庫,它是目前 Python 社群中最受推薦、功能最完整的密碼學工具包。
1. 安裝必要套件
首先,你需要安裝 cryptography 函式庫
2. 對稱式加密範例程式
對稱式加密的核心在於:加密與解密使用同一把金鑰 (Key)。
3. 重點解析
Fernet 演算法:上述程式碼使用了
Fernet,它是基於 AES-128 的對稱加密實現。它不僅加密資料,還會加上 HMAC (訊息鑑別碼) 來確保資料在傳輸過程中沒有被竄改。金鑰管理:
secret.key是唯一的「鑰匙」。如果弄丟了,資料將永遠無法還原;如果被別人拿到,你的資料就全透明了。Bytes 轉換:加密演算法處理的是二進制數據(Bytes),因此字串在加密前必須先
.encode(),解密後再.decode()。
需要注意:
金鑰格式限制:
Fernet要求的金鑰必須是 Base64 編碼的 32 個位元組。如果您隨便輸入一個密碼(例如123456),程式會報錯。如果您想自定義「密碼」(Password): 如果您希望輸入的是像
MyPassword123這種簡單密碼,而不是亂碼金鑰,我們必須加上一個 KDF (金鑰衍生函數)。這會將您的密碼「轉化」成符合規格的金鑰。
import tkinter as tk
from tkinter import messagebox, filedialog
from cryptography.fernet import Fernet
class EncryptionApp:
def __init__(self, root):
self.root = root
self.root.title("AES 對稱式加密工具")
self.root.geometry("800x400")
# 設定 UI 版面
self.create_widgets()
def create_widgets(self):
# --- 左側:原始文字區 ---
left_frame = tk.Frame(self.root, padx=10, pady=10)
left_frame.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
tk.Label(left_frame, text="原始文字 / 加密結果:", font=('Arial', 10, 'bold')).pack(anchor=tk.W)
self.txt_input = tk.Text(left_frame, height=15, width=40)
self.txt_input.pack(fill=tk.BOTH, expand=True)
# --- 中間:按鈕區 ---
mid_frame = tk.Frame(self.root, padx=10, pady=10)
mid_frame.pack(side=tk.LEFT, fill=tk.Y)
tk.Button(mid_frame, text="生成新金鑰 >>", command=self.generate_new_key).pack(fill=tk.X, pady=5)
tk.Button(mid_frame, text="執行加密", command=self.encrypt_action, bg="#e1f5fe").pack(fill=tk.X, pady=5)
tk.Button(mid_frame, text="執行解密", command=self.decrypt_action, bg="#fff9c4").pack(fill=tk.X, pady=5)
# --- 右側:金鑰管理區 ---
right_frame = tk.Frame(self.root, padx=10, pady=10)
right_frame.pack(side=tk.RIGHT, fill=tk.BOTH, expand=True)
tk.Label(right_frame, text="Secret Key (可修改):", font=('Arial', 10, 'bold')).pack(anchor=tk.W)
self.txt_key = tk.Text(right_frame, height=5, width=40)
self.txt_key.pack(fill=tk.X)
tk.Button(right_frame, text="儲存金鑰至檔案", command=self.save_key_to_file).pack(anchor=tk.E, pady=5)
tk.Label(right_frame, text="\n說明:\n1. 金鑰必須為 Base64 格式。\n2. 加密後請複製結果並保存。",
justify=tk.LEFT, fg="gray").pack(anchor=tk.W)
def generate_new_key(self):
"""生成新的 Fernet 金鑰並顯示在右側"""
key = Fernet.generate_key().decode()
self.txt_key.delete(1.0, tk.END)
self.txt_key.insert(tk.END, key)
def get_key(self):
"""獲取右側文字框中的金鑰"""
key = self.txt_key.get(1.0, tk.END).strip()
if not key:
messagebox.showerror("錯誤", "請先生成或輸入金鑰!")
return None
return key.encode()
def encrypt_action(self):
"""加密左側文字"""
key = self.get_key()
if not key: return
try:
f = Fernet(key)
content = self.txt_input.get(1.0, tk.END).strip()
if not content:
messagebox.showwarning("警告", "請輸入要加密的內容")
return
encrypted = f.encrypt(content.encode()).decode()
self.txt_input.delete(1.0, tk.END)
self.txt_input.insert(tk.END, encrypted)
except Exception as e:
messagebox.showerror("加密失敗", f"無效的金鑰格式或錯誤: {e}")
def decrypt_action(self):
"""解密左側文字"""
key = self.get_key()
if not key: return
try:
f = Fernet(key)
content = self.txt_input.get(1.0, tk.END).strip()
decrypted = f.decrypt(content.encode()).decode()
self.txt_input.delete(1.0, tk.END)
self.txt_input.insert(tk.END, decrypted)
except Exception as e:
messagebox.showerror("解密失敗", "解密失敗!請檢查金鑰是否正確或內容是否完整。")
def save_key_to_file(self):
"""將右側金鑰內容存檔"""
key = self.txt_key.get(1.0, tk.END).strip()
if not key:
messagebox.showwarning("警告", "沒有金鑰可以儲存")
return
file_path = filedialog.asksaveasfilename(defaultextension=".key",
filetypes=[("Key files", "*.key"), ("All files", "*.*")],
initialfile="secret.key")
if file_path:
with open(file_path, "w") as f:
f.write(key)
messagebox.showinfo("成功", f"金鑰已儲存至: {file_path}")
if __name__ == "__main__":
root = tk.Tk()
app = EncryptionApp(root)
root.mainloop()


沒有留言:
張貼留言