2026年5月18日 星期一

ISO/IEC DIS9789-2 標準中的「三步驟雙向加密認證(Three-Step Mutual Authentication)」

ISO/IEC DIS9789-2 標準中的「三步驟雙向加密認證(Three-Step Mutual Authentication)」


這是一個涉及到 資訊安全、射頻識別(RFID/NFC)高階安全認證 以及 圖形化使用者介面(GUI) 的整合實作。

在 ISO/IEC 的安全標準中,「三步驟異頻收發(Three-Step Mutual Authentication with Cryptographic Challenge-Response)」是防範重放攻擊(Replay Attack)非法竊聽(Eavesdropping)的核心技術。它的基本原理是:讀卡機(PCD)與卡片(PICC)雙方不直接在空中傳送密碼與真實的 UID(唯一原始單一序號),而是透過隨機亂數(Nonce)、外加密碼(Key)進行加密綁定與驗證。

為了清楚展示這「三步驟」是如何運作並保護資料的,底下為您撰寫一個 Python + Tkinter 的動態視覺化模擬程式。


「三步驟異頻認證」核心邏輯說明

  1. 步驟一(讀卡機 -> 卡片):讀卡機向卡片發送認證請求,並附帶一個讀卡機生成的隨機亂數 $R_A$

  2. 步驟二(卡片 -> 讀卡機):卡片收到後,自己也生成一個隨機亂數 $R_B$。接著,卡片使用雙方共享的「外加密碼(Key)」與加密演算法(此處模擬使用 AES 精神),將(卡片真實 UID + $R_A$ + $R_B$)進行加密封包並回傳。

  3. 步驟三(讀卡機 -> 卡片):讀卡機用相同的密碼解密,解讀出唯一的原始 UID 並驗證 $R_A$ 是否正確(防止非法入侵)。若正確,讀卡機再將 $R_B$ 加密回傳給卡片。卡片驗證 $R_B$ 成功後,雙方才建立信任鏈,允許後續讀寫。







import tkinter as tk

from tkinter import ttk

from tkinter import messagebox

import random

import hashlib


# 模擬簡單的加密與解密函數(基於 SHA256/XOR 示意,代表標準中的安全加密算法)

def encrypt_data(plain_text, key):

    # 將密鑰轉為雜湊值作為密鑰流

    key_hash = hashlib.sha256(key.encode()).hexdigest()

    cipher_text = ""

    for i in range(max(len(plain_text), len(key_hash))):

        p_ch = plain_text[i % len(plain_text)]

        k_ch = key_hash[i % len(key_hash)]

        cipher_text += chr(ord(p_ch) ^ ord(k_ch))

    return cipher_text.encode('utf-8').hex()


def decrypt_data(cipher_hex, key):

    try:

        cipher_text = bytes.fromhex(cipher_hex).decode('utf-8')

        key_hash = hashlib.sha256(key.encode()).hexdigest()

        plain_text = ""

        for i in range(max(len(cipher_text), len(key_hash))):

            c_ch = cipher_text[i % len(cipher_text)]

            k_ch = key_hash[i % len(key_hash)]

            plain_text += chr(ord(c_ch) ^ ord(k_ch))

        return plain_text

    except:

        return "【解密失敗/密碼錯誤】"


class AuthenticationSimApp:

    def __init__(self, root):

        self.root = root

        self.root.title("ISO/IEC DIS9789-2 三步驟異頻收發安全認證模擬器")

        self.root.geometry("850x650")

        

        # --- 原始安全數據 ---

        self.REAL_UID = "UID-9527-A8B9"  # 卡片內部的唯一原始單一序號

        self.CORRECT_KEY = "NFC_Secure_Key_2026"  # 系統預設的外加密碼

        

        # 運作暫存變數

        self.R_A = ""

        self.R_B = ""

        self.step = 0

        

        self.setup_ui()


    def setup_ui(self):

        # 標題

        title_lbl = ttk.Label(self.root, text="ISO/IEC DIS9789-2 三步驟安全認證技術展示", font=("Arial", 16, "bold"), foreground="#1A5276")

        title_lbl.pack(pady=10)

        

        # 參數設定區

        config_frame = ttk.LabelFrame(self.root, text=" 系統內部機密參數 (防偽起點) ")

        config_frame.pack(fill=tk.X, padx=15, pady=5)

        

        ttk.Label(config_frame, text="卡片內部原始唯一序號 (UID):").grid(row=0, column=0, padx=10, pady=5, sticky="e")

        ttk.Label(config_frame, text=self.REAL_UID, font=("Consolas", 11, "bold"), foreground="blue").grid(row=0, column=1, padx=10, pady=5, sticky="w")

        

        ttk.Label(config_frame, text="請輸入認證密碼 (外加密碼):").grid(row=1, column=0, padx=10, pady=5, sticky="e")

        self.key_entry = ttk.Entry(config_frame, width=25)

        self.key_entry.insert(0, "NFC_Secure_Key_2026") # 預設正確密碼

        self.key_entry.grid(row=1, column=1, padx=10, pady=5, sticky="w")

        

        # 流程控制與空中狀態區

        self.run_frame = ttk.LabelFrame(self.root, text=" 空中接口 (Air Interface) 數據監聽監控 ")

        self.run_frame.pack(fill=tk.BOTH, expand=True, padx=15, pady=10)

        

        # 三步驟動態顯示看板

        self.step1_box = tk.Text(self.run_frame, height=3, width=90, bg="#F2F4F4", state=tk.DISABLED, font=("Microsoft JhengHei", 10))

        self.step1_box.pack(pady=5)

        self.step2_box = tk.Text(self.run_frame, height=3, width=90, bg="#F2F4F4", state=tk.DISABLED, font=("Microsoft JhengHei", 10))

        self.step2_box.pack(pady=5)

        self.step3_box = tk.Text(self.run_frame, height=3, width=90, bg="#F2F4F4", state=tk.DISABLED, font=("Microsoft JhengHei", 10))

        self.step3_box.pack(pady=5)

        

        # 驗證結論看板

        self.result_label = ttk.Label(self.run_frame, text="等待認證啟動...", font=("Arial", 12, "bold"), foreground="gray")

        self.result_label.pack(pady=10)

        

        # 按鈕控制區

        btn_frame = ttk.Frame(self.root)

        btn_frame.pack(pady=10)

        

        self.btn_next = ttk.Button(btn_frame, text="啟動 / 執行下一步步驟", command=self.next_step)

        self.btn_next.pack(side=tk.LEFT, padx=10)

        

        btn_reset = ttk.Button(btn_frame, text="重置模擬", command=self.reset_sim)

        btn_reset.pack(side=tk.LEFT, padx=10)


    def update_box(self, box, text, bg_color):

        box.config(state=tk.NORMAL)

        box.delete("1.0", tk.END)

        box.insert(tk.END, text)

        box.config(bg=bg_color, state=tk.DISABLED)


    def next_step(self):

        user_key = self.key_entry.get()

        if not user_key:

            messagebox.showwarning("警告", "請輸入外加密碼!")

            return


        self.step += 1

        

        if self.step == 1:

            # 【步驟一】讀卡機 -> 卡片:發送隨機挑戰碼 R_A

            self.R_A = str(random.randint(100000, 999999))

            msg = f"【步驟一:讀卡機 -> 卡片】\n發送認證請求。讀卡機生成隨機亂數 R_A = {self.R_A}\n此時空中傳輸內容:【明文 R_A,此時駭客竊聽也拿不到 UID 或密碼】"

            self.update_box(self.step1_box, msg, "#EBF5FB") # 淺藍色代表進行中

            self.result_label.config(text="步驟一完成:挑戰碼 R_A 已發送。", foreground="blue")

            

        elif self.step == 2:

            # 【步驟二】卡片 -> 讀卡機:回傳加密後的 (UID + R_A + R_B)

            self.R_B = str(random.randint(100000, 999999))

            

            # 卡片內部進行加密:將 原始UID + R_A + R_B 綁定

            raw_packet = f"{self.REAL_UID}|{self.R_A}|{self.R_B}"

            # 使用正確的卡片內置密碼進行加密

            self.cipher_step2 = encrypt_data(raw_packet, self.CORRECT_KEY)

            

            msg = f"【步驟二:卡片 -> 讀卡機】\n卡片生成亂數 R_B = {self.R_B}。使用內置外加密碼將 (UID + R_A + R_B) 打包加密。\n空中攔截到的密文:{self.cipher_step2}\n【安全防護:防非法讀取!沒有密碼的入侵者在此步驟無法解讀出原始唯一序號 UID】"

            self.update_box(self.step2_box, msg, "#EBF5FB")

            self.result_label.config(text="步驟二完成:卡片已回傳加密權杖(Token)。", foreground="blue")

            

        elif self.step == 3:

            # 【步驟三】讀卡機解讀、驗證並回應

            # 讀卡機嘗試用使用者輸入的密碼解密步驟二傳回的密文

            decrypted_str = decrypt_data(self.cipher_step2, user_key)

            

            if "|" in decrypted_str:

                parts = decrypted_str.split("|")

                parsed_uid = parts[0]

                parsed_ra = parts[1]

                parsed_rb = parts[2]

                

                # 驗證 R_A 是否與步驟一相同 (防止重放攻擊)

                if parsed_ra == self.R_A:

                    # 讀卡機回應加密後的 R_B 給卡片以完成雙向認證

                    cipher_step3 = encrypt_data(parsed_rb, user_key)

                    

                    msg = f"【步驟三:讀卡機 -> 卡片】\n後台成功經由密碼解讀唯一原始單一序號:【{parsed_uid}】\n驗證 R_A 匹配成功!讀卡機回傳 R_B 的加密值:{cipher_step3} 給卡片確認身份。"

                    self.update_box(self.step3_box, msg, "#EAF2F8")

                    

                    # 最終安全判定

                    if user_key == self.CORRECT_KEY:

                        self.result_label.config(text=f"【認證成功】成功解讀原始序號:{parsed_uid}。安全阻斷非法入侵與非法讀取!", foreground="green")

                    else:

                        self.result_label.config(text="【認證失敗】雖然格式符合,但外加密碼非授權密碼。", foreground="red")

                else:

                    self.fail_display("R_A 驗證失敗,疑似遭受外部重放入侵!")

            else:

                # 解密出來是亂碼(密碼錯誤)

                msg = f"【步驟三:讀卡機 -> 卡片】\n讀卡機使用錯誤的密碼進行解密...\n解讀結果:{decrypted_str}\n無法取得唯一原始單一序號,拒絕存取!"

                self.update_box(self.step3_box, msg, "#FDEDEC")

                self.result_label.config(text="【認證失敗】非法入侵/密碼錯誤!無法解讀原始單一序號。", foreground="red")

                

            self.btn_next.config(state=tk.DISABLED)


    def fail_display(self, reason):

        msg = f"【驗證失敗】\n原因:{reason}"

        self.update_box(self.step3_box, msg, "#FDEDEC")

        self.result_label.config(text="【拒絕存取】非法入侵!", foreground="red")


    def reset_sim(self):

        self.step = 0

        self.R_A = ""

        self.R_B = ""

        self.update_box(self.step1_box, "", "#F2F4F4")

        self.update_box(self.step2_box, "", "#F2F4F4")

        self.update_box(self.step3_box, "", "#F2F4F4")

        self.result_label.config(text="等待認證啟動...", foreground="gray")

        self.btn_next.config(state=tk.NORMAL)


if __name__ == "__main__":

    root = tk.Tk()

    app = AuthenticationSimApp(root)

    root.mainloop()





這份程式碼的核心任務,是把 ISO/IEC DIS9789-2 標準中的「三步驟雙向加密認證(Three-Step Mutual Authentication)」流程用圖形化介面(GUI)展示出來。

我們可以將這段程式碼拆解為三大區塊:加密/解密底層介面初始化設定、以及核心三步驟控制邏輯,並為你逐行說明:


一、 基礎模組匯入與加解密底層 (工具準備)

這部分負責引進所需的庫,並建立一個模擬商用加密(如 AES/DES)邏輯的測試加解密函數。

Python
import tkinter as tk                  # 匯入內建的 GUI 圖形介面庫
from tkinter import ttk               # 匯入美化版控制元件(按鈕、框架等)
from tkinter import messagebox        # 匯入彈出式警告視窗模組
import random                         # 匯入亂數庫,用來生成每次認證都不同的隨機挑戰碼(Nonce)
import hashlib                        # 匯入雜湊庫,用來把密碼轉換成固定長度的密鑰流

1. 模擬流加密函數 (encrypt_data)

在實際標準中會使用高級對稱加密(如 AES-128)。這裡用 XOR 運算來模擬這個行為。

Python
def encrypt_data(plain_text, key):
    # 將輸入的外加密碼(key)透過 SHA-256 轉成長度 64 碼的十六進位雜湊值,作為密鑰流
    key_hash = hashlib.sha256(key.encode()).hexdigest()
    cipher_text = ""
    # 逐字元將明文(plain_text)與密鑰流進行 XOR (^) 互斥或運算
    for i in range(max(len(plain_text), len(key_hash))):
        p_ch = plain_text[i % len(plain_text)]
        k_ch = key_hash[i % len(key_hash)]
        cipher_text += chr(ord(p_ch) ^ ord(k_ch))
    # 將混淆後的結果轉成 16 進位字串(hex)回傳,方便在空中接口(文字框)顯示
    return cipher_text.encode('utf-8').hex()

2. 模擬流解密函數 (decrypt_data)

Python
def decrypt_data(cipher_hex, key):
    try:
        # 將 16 進位密文字串還原為原始位元組與字元
        cipher_text = bytes.fromhex(cipher_hex).decode('utf-8')
        key_hash = hashlib.sha256(key.encode()).hexdigest()
        plain_text = ""
        # 使用相同的外加密碼進行第二次 XOR 運算(XOR 的特徵:雙重 XOR 會還原明文)
        for i in range(max(len(cipher_text), len(key_hash))):
            c_ch = cipher_text[i % len(cipher_text)]
            k_ch = key_hash[i % len(key_hash)]
            plain_text += chr(ord(c_ch) ^ ord(k_ch))
        return plain_text
    except:
        # 如果格式不對或解密出錯,直接回傳錯誤提示
        return "【解密失敗/密碼錯誤】"

二、 類別初始化與 GUI 佈局 (__init__ & setup_ui)

這段負責撐起整個軟體視窗,並擺放「密碼輸入框」以及「三步驟空中數據監控看板」。

Python
class AuthenticationSimApp:
    def __init__(self, root):
        self.root = root
        self.root.title("ISO/IEC DIS9789-2 三步驟異頻收發安全認證模擬器")
        self.root.geometry("850x650") # 規定視窗大小
        
        # --- 原始安全數據(存放在硬體安全模組中的真實資料) ---
        self.REAL_UID = "UID-9527-A8B9"  # 卡片唯一的原始單一序號
        self.CORRECT_KEY = "NFC_Secure_Key_2026"  # 系統後台與卡片共享的正確外加密碼
        
        # 認證運作時的暫存變數
        self.R_A = ""    # 讀卡機挑戰碼
        self.R_B = ""    # 卡片挑戰碼
        self.step = 0    # 目前執行到第幾步
        
        self.setup_ui() # 呼叫介面佈局

介面佈局主體 (setup_ui)

Python
    def setup_ui(self):
        # 建立大標題文字
        title_lbl = ttk.Label(self.root, text="ISO/IEC DIS9789-2 三步驟安全認證技術展示", font=("Arial", 16, "bold"), foreground="#1A5276")
        title_lbl.pack(pady=10)
        
        # 1. 建立「系統內部機密參數」區塊
        config_frame = ttk.LabelFrame(self.root, text=" 系統內部機密參數 (防偽起點) ")
        config_frame.pack(fill=tk.X, padx=15, pady=5)
        
        # 顯示卡片內部的真實 UID (模擬實體卡片晶片內的唯讀區)
        ttk.Label(config_frame, text="卡片內部原始唯一序號 (UID):").grid(row=0, column=0, padx=10, pady=5, sticky="e")
        ttk.Label(config_frame, text=self.REAL_UID, font=("Consolas", 11, "bold"), foreground="blue").grid(row=0, column=1, padx=10, pady=5, sticky="w")
        
        # 建立讓使用者輸入密碼的輸入框(Entry)
        ttk.Label(config_frame, text="請輸入認證密碼 (外加密碼):").grid(row=1, column=0, padx=10, pady=5, sticky="e")
        self.key_entry = ttk.Entry(config_frame, width=25)
        self.key_entry.insert(0, "NFC_Secure_Key_2026") # 預設先填入正確密碼,方便測試
        self.key_entry.grid(row=1, column=1, padx=10, pady=5, sticky="w")
        
        # 2. 建立「空中接口數據監聽」區塊 (用來展示在空氣中傳輸的機密數據狀態)
        self.run_frame = ttk.LabelFrame(self.root, text=" 空中接口 (Air Interface) 數據監聽監控 ")
        self.run_frame.pack(fill=tk.BOTH, expand=True, padx=15, pady=10)
        
        # 建立三個不可編輯(DISABLED)的 Text 文字框,用來分別顯示三步驟的空中狀態
        self.step1_box = tk.Text(self.run_frame, height=3, width=90, bg="#F2F4F4", state=tk.DISABLED, font=("Microsoft JhengHei", 10))
        self.step1_box.pack(pady=5)
        self.step2_box = tk.Text(self.run_frame, height=3, width=90, bg="#F2F4F4", state=tk.DISABLED, font=("Microsoft JhengHei", 10))
        self.step2_box.pack(pady=5)
        self.step3_box = tk.Text(self.run_frame, height=3, width=90, bg="#F2F4F4", state=tk.DISABLED, font=("Microsoft JhengHei", 10))
        self.step3_box.pack(pady=5)
        
        # 最下方的結果大標題
        self.result_label = ttk.Label(self.run_frame, text="等待認證啟動...", font=("Arial", 12, "bold"), foreground="gray")
        self.result_label.pack(pady=10)
        
        # 3. 建立最底部的控制按鈕
        btn_frame = ttk.Frame(self.root)
        btn_frame.pack(pady=10)
        
        # 當點擊此按鈕時,觸發下一步邏輯(next_step)
        self.btn_next = ttk.Button(btn_frame, text="啟動 / 執行下一步步驟", command=self.next_step)
        self.btn_next.pack(side=tk.LEFT, padx=10)
        
        # 重置按鈕
        btn_reset = ttk.Button(btn_frame, text="重置模擬", command=self.reset_sim)
        btn_reset.pack(side=tk.LEFT, padx=10)

    # 輔助函式:用來動態更新文字框的內容與背景顏色
    def update_box(self, box, text, bg_color):
        box.config(state=tk.NORMAL)     # 解鎖文字框
        box.delete("1.0", tk.END)        # 清空
        box.insert(tk.END, text)         # 填入新進展
        box.config(bg=bg_color, state=tk.DISABLED) # 重新鎖定,防使用者手動修改

三、 三步驟防禦機制核心控制邏輯 (next_step)

這是全程式最重要的核心。當使用者每點一次「執行下一步步驟」,它就會推進一個狀態。

Python
    def next_step(self):
        user_key = self.key_entry.get() # 抓取使用者在密碼框輸入的字串
        if not user_key:
            messagebox.showwarning("警告", "請輸入外加密碼!")
            return

        self.step += 1 # 步驟計數加 1

【第 1 步】讀卡機發出隨機挑戰碼 ($R_A$)

Python
        if self.step == 1:
            # 隨機產生一組 6 位數亂數作為 R_A
            self.R_A = str(random.randint(100000, 999999))
            msg = f"【步驟一:讀卡機 -> 卡片】\n發送認證請求。讀卡機生成隨機亂數 R_A = {self.R_A}\n此時空中傳輸內容:【明文 R_A,此時駭客竊聽也拿不到 UID 或密碼】"
            self.update_box(self.step1_box, msg, "#EBF5FB") # 變為淺藍色代表進行中
            self.result_label.config(text="步驟一完成:挑戰碼 R_A 已發送。", foreground="blue")

【第 2 步】卡片端加密打包回傳 ($UID + R_A + R_B$)

卡片收到 $R_A$ 後,拒絕明文傳送 UID。而是用正確的外加密碼將它鎖起來。

Python
        elif self.step == 2:
            # 卡片自己也生成一組 6 位數隨機挑戰碼 R_B
            self.R_B = str(random.randint(100000, 999999))
            
            # 將 (真實唯獨 UID) + (讀卡機發的 R_A) + (卡片發的 R_B) 用管線符號 | 綁定成一條字串
            raw_packet = f"{self.REAL_UID}|{self.R_A}|{self.R_B}"
            
            # 關鍵:卡片使用自己內部晶片寫死的「正確外加密碼(CORRECT_KEY)」將整包資料加密
            self.cipher_step2 = encrypt_data(raw_packet, self.CORRECT_KEY)
            
            msg = f"【步驟二:卡片 -> 讀卡機】\n卡片生成亂數 R_B = {self.R_B}。使用內置外加密碼將 (UID + R_A + R_B) 打包加密。\n空中攔截到的密文:{self.cipher_step2}\n【安全防護:防非法讀取!沒有密碼的入侵者在此步驟無法解讀出原始唯一序號 UID】"
            self.update_box(self.step2_box, msg, "#EBF5FB")
            self.result_label.config(text="步驟二完成:卡片已回傳加密權杖(Token)。", foreground="blue")

【第 3 步】讀卡機解讀、經對驗證與回應

此時讀卡機要透過解密來嘗試解讀、經對唯一原始序號,同時防範重放攻擊。

Python
        elif self.step == 3:
            # 讀卡機收到密文後,嘗試用「使用者輸入的密碼 (user_key)」進行解密
            decrypted_str = decrypt_data(self.cipher_step2, user_key)
            
            # 如果密碼正確,解開的明文裡必然包含管線符號 "|"
            if "|" in decrypted_str:
                parts = decrypted_str.split("|") # 依據 "|" 將字串拆解回三個元素
                parsed_uid = parts[0]            # 解讀出來的原始唯一序號 (UID)
                parsed_ra = parts[1]             # 解讀出來的 R_A
                parsed_rb = parts[2]             # 解讀出來的 R_B
                
                # 【經對驗證 1】:檢查解密出來的 R_A 是否等於剛才步驟一發出去的 R_A
                if parsed_ra == self.R_A:
                    # 讀卡機把解出來的 R_B 再次加密,發還給卡片(證明讀卡機也擁有相同密碼)
                    cipher_step3 = encrypt_data(parsed_rb, user_key)
                    
                    msg = f"【步驟三:讀卡機 -> 卡片】\n後台成功經由密碼解讀唯一原始單一序號:【{parsed_uid}】\n驗證 R_A 匹配成功!讀卡機回傳 R_B 的加密值:{cipher_step3} 給卡片確認身份。"
                    self.update_box(self.step3_box, msg, "#EAF2F8")
                    
                    # 【經對驗證 2】:判定整體系統權限。如果密碼與預設完全相符
                    if user_key == self.CORRECT_KEY:
                        self.result_label.config(text=f"【認證成功】成功解讀原始序號:{parsed_uid}。安全阻斷非法入侵與非法讀取!", foreground="green")
                    else:
                        self.result_label.config(text="【認證失敗】雖然格式符合,但外加密碼非授權密碼。", foreground="red")
                else:
                    # R_A 不符,代表這可能是駭客拿昨天錄下來的舊密文直接重播(重放攻擊),予以拒絕
                    self.fail_display("R_A 驗證失敗,疑似遭受外部重放入侵!")
            else:
                # 密碼完全錯誤時,解密出來會是一堆亂碼,找不到 "|"
                msg = f"【步驟三:讀卡機 -> 卡片】\n讀卡機使用錯誤的密碼進行解密...\n解讀結果:{decrypted_str}\n無法取得唯一原始單一序號,拒絕存取!"
                self.update_box(self.step3_box, msg, "#FDEDEC") # 亮紅燈
                self.result_label.config(text="【認證失敗】非法入侵/密碼錯誤!無法解讀原始單一序號。", foreground="red")
                
            self.btn_next.config(state=tk.DISABLED) # 認證結束,鎖定「下一步」按鈕

四、 其他輔助機制 (重置功能)

Python
    # 失敗時的面板顯示處理
    def fail_display(self, reason):
        msg = f"【驗證失敗】\n原因:{reason}"
        self.update_box(self.step3_box, msg, "#FDEDEC")
        self.result_label.config(text="【拒絕存取】非法入侵!", foreground="red")

    # 清空所有暫存,回歸初始狀態
    def reset_sim(self):
        self.step = 0
        self.R_A = ""
        self.R_B = ""
        self.update_box(self.step1_box, "", "#F2F4F4")
        self.update_box(self.step2_box, "", "#F2F4F4")
        self.update_box(self.step3_box, "", "#F2F4F4")
        self.result_label.config(text="等待認證啟動...", foreground="gray")
        self.btn_next.config(state=tk.NORMAL)

# 程式執行進入點
if __name__ == "__main__":
    root = tk.Tk()
    app = AuthenticationSimApp(root)
    root.mainloop() # 開啟事件無窮迴圈,維持視窗運作

ISO/IEC DIS9789-2 標準中的「三步驟雙向加密認證(Three-Step Mutual Authentication)」

ISO/IEC DIS9789-2 標準中的「三步驟雙向加密認證(Three-Step Mutual Authentication)」 這是一個涉及到 資訊安全、射頻識別(RFID/NFC)高階安全認證 以及 圖形化使用者介面(GUI) 的整合實作。 在 ISO/IEC 的安...