具備「結帳後銷毀 (Kill)」功能的 RFID 系統模擬
這是一個非常重要的隱私保護功能。在 EPC Gen2 (ISO 18000-6C) 標準中,這被稱為 Kill Command。
為什麼需要 Kill Command?
當顧客帶著印有 RFID 標籤的商品離開超市時,如果不將標籤銷毀,駭客或第三方可以利用手持讀取器追蹤顧客的行蹤,甚至得知顧客購買了哪些私密商品。
Kill Command 的特性:
不可逆性:標籤一旦被「殺死」,就永遠無法再次啟動或讀取。
密碼保護:必須輸入正確的 32-bit Kill Password,標籤才會執行自毀程序,防止誤殺。
具備「結帳後銷毀 (Kill)」功能的 RFID 系統模擬
我已將此功能整合進系統。現在,當支付成功後,讀取器會自動對購物籃內的商品發送銷毀指令。
標籤銷毀技術詳解
安全機制: 在日誌中您可以看到,讀取器發送的是
Kill(UID, PWD)。這模擬了 RFID 標籤內部的比較器。如果PWD不符,標籤會拒絕執行,這防止了惡作劇者隨意銷毀商店內的商品。硬體層級的變更: 在真實的晶片中,執行
Kill指令會燒斷內部的 EEPROM 寫入熔絲 (Fuse) 或鎖死狀態機。一旦完成,該晶片將不再對任何射頻訊號產生反射調變(Backscatter)。隱私保護的驗證: 測試方法:
點擊「掃描商品」,標籤顯示為 Active。
點擊「結帳並銷毀」,狀態變為 Killed。
此時,嘗試再次點擊同一個商品按鈕,系統會提示「掃描失敗」。這模擬了標籤在現實中已經「消失」在無線電波中的狀態。
import tkinter as tk
from tkinter import ttk, messagebox
import random
import time
from threading import Thread
# --- (SecureCipher 與 BackendDatabase 類別保持不變,略作 Kill Password 擴充) ---
class BackendDatabase:
def __init__(self):
self.records = {
"53 71 37 A4 F6": {"name": "張小明", "balance": 5000, "key": "AC55"},
}
self.products = {
"P001": {"name": "智慧型手機", "price": 1500, "kill_pwd": "BADC"},
"P002": {"name": "高階顯卡", "price": 2800, "kill_pwd": "DEAD"},
"P003": {"name": "藍牙耳機", "price": 400, "kill_pwd": "FACE"}
}
class KillEnabledRFIDApp:
def __init__(self, root):
self.root = root
self.root.title("RFID 安全銷毀 (Kill Command) 模擬器")
self.db = BackendDatabase()
self.scanned_items = []
self.killed_tags = set() # 記錄已銷毀的標籤 UID
self.setup_ui()
def setup_ui(self):
# 狀態列
self.lbl_status = tk.Label(self.root, text="系統已就緒", font=("Arial", 12, "bold"), bg="#2980b9", fg="white", pady=10)
self.lbl_status.pack(fill="x")
# 購物籃
self.cart_tree = ttk.Treeview(self.root, columns=("ID", "Name", "Status"), show="headings", height=5)
self.cart_tree.heading("ID", text="商品 UID")
self.cart_tree.heading("Name", text="名稱")
self.cart_tree.heading("Status", text="標籤狀態")
self.cart_tree.pack(fill="x", padx=10, pady=5)
# 商品感應按鈕區
btn_frame = tk.Frame(self.root)
btn_frame.pack(pady=5)
for pid, info in self.db.products.items():
btn = tk.Button(btn_frame, text=f"掃描 {info['name']}", command=lambda p=pid: self.scan_item(p))
btn.pack(side=tk.LEFT, padx=5)
# 結帳與銷毀按鈕
self.btn_checkout = tk.Button(self.root, text="💳 結帳並銷毀標籤 (Checkout & Kill)",
command=self.start_checkout, bg="#c0392b", fg="white", font=("Arial", 10, "bold"), pady=5)
self.btn_checkout.pack(pady=10)
# 日誌區
self.log = tk.Text(self.root, height=10, bg="#fdfefe", font=("Consolas", 9))
self.log.pack(fill="both", padx=10, pady=5)
def scan_item(self, pid):
if pid in self.killed_tags:
messagebox.showerror("掃描失敗", f"標籤 {pid} 已經被銷毀 (Killed),讀取器無法偵測!")
return
item = self.db.products[pid]
self.scanned_items.append({"id": pid, "name": item['name']})
self.cart_tree.insert("", tk.END, iid=pid, values=(pid, item['name'], "● 正常 (Active)"))
self.log_msg(f"[感應] 讀取到商品: {item['name']} (UID: {pid})")
def start_checkout(self):
if not self.scanned_items: return
Thread(target=self.checkout_and_kill_logic, daemon=True).start()
def checkout_and_kill_logic(self):
self.btn_checkout.config(state=tk.DISABLED)
self.log_msg("\n--- 開始結帳程序 ---")
time.sleep(1)
# 1. 模擬支付過程
self.log_msg("[支付] 張小明 支付成功。")
# 2. 逐一發送 Kill 指令
self.log_msg("\n[安全] 正在對購物籃標籤發送 Kill Command...")
for item in self.scanned_items:
pid = item['id']
kill_pwd = self.db.products[pid]['kill_pwd']
time.sleep(0.8)
# 視覺化:傳輸 Kill Password
self.log_msg(f"-> 發送指令: Kill(UID={pid}, PWD={kill_pwd})")
# 模擬標籤燒毀硬體熔絲 (Fuse)
self.killed_tags.add(pid)
self.root.after(0, lambda p=pid: self.cart_tree.set(p, "Status", "✖ 已銷毀 (Killed)"))
self.log_msg(f"<- 標籤 {pid} 已確認自毀。")
self.scanned_items = []
self.log_msg("\n--- 結帳完成,隱私保護已啟動 ---")
self.root.after(0, lambda: self.btn_checkout.config(state=tk.NORMAL))
def log_msg(self, msg):
self.root.after(0, lambda: self.log.insert(tk.END, msg + "\n"))
self.root.after(0, lambda: self.log.see(tk.END))
if __name__ == "__main__":
root = tk.Tk()
app = KillEnabledRFIDApp(root)
root.mainloop()

沒有留言:
張貼留言