2026年1月15日 星期四

Python 對稱式加密

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


需要注意:

  1. 金鑰格式限制Fernet 要求的金鑰必須是 Base64 編碼的 32 個位元組。如果您隨便輸入一個密碼(例如 123456),程式會報錯。

  2. 如果您想自定義「密碼」(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()


沒有留言:

張貼留言

CRC(循環冗餘檢查)

  CRC(循環冗餘檢查) 完整的 CRC(循環冗餘檢查)逐步演示器 。它支援自定義 生成多項式 與 資料位元流 ,並透過「下一步」按鈕展示二進制長除法(XOR 運算)的過程。 二進制長除法模擬 : CRC 的核心是模二除法(Modulo-2 Division),實務上就是不斷進...