為什麼 Passkey 安全 ── 圖解「不傳送秘密的驗證」機制

· · Passkey, WebAuthn, FIDO2, 資訊安全, 身分驗證, 網路釣魚對策, 資訊系統

「又有大型服務的密碼外洩了」這種新聞,已經沒有人會感到驚訝了。就算每年都做網路釣魚訓練,還是不可能把中招的人歸零。「密碼不要重複使用、要設長一點、定期更改……其實已經不用了」──連說法本身都反覆改變過。

近幾年急速普及的Passkey(通行密鑰),是 Apple、Google、微軟三家公司一致推動、作為這個困境解答的驗證方式。1 雖然常被介紹成「可以用指紋或臉部登入,很方便」,但其本質並不在此。Passkey 真正的價值,在於把安全性的依據從「人的注意力」轉移到了「協定的結構」

  • 密碼會外洩是因為使用者不小心,所以要教育 → 人一定會犯錯
  • 訓練大家去辨別假網站 → 做得出讓人辨別不出來的假網站
  • 如果是 Passkey → 原本就沒有可傳送的秘密,假網站上簽章也無法成立

本文將從密碼的機制究竟壞在哪裡出發,用圖解說明 Passkey 為什麼安全。接著會正面回答「同步的 Passkey 真的安全嗎」「有沒有弱點」這類理所當然的疑問,最後整理在 Web 應用程式與 Windows 環境中導入 Passkey 時的實務要點。

1. 先講結論

Passkey 之所以安全,可以歸納為以下三點。

  1. 伺服器上不存在秘密。伺服器儲存的只有公開金鑰,這是即使外洩也無法被濫用的資訊。就算資料庫整個外流,攻擊者也拿不到任何可用來冒充身分的材料。2
  2. 秘密不會在網路上傳輸。登入時傳送的只是針對一次性亂數(挑戰值)的簽章。私密金鑰完全不會離開裝置的驗證器,因此無論在路徑上哪個環節竊聽或中繼,都拿不到秘密。2
  3. 在假網站上簽章無法成立。Passkey 與網站的網域綁定,瀏覽器會強制比對網域。即使使用者被假網站騙到,真網站用的 Passkey 原本就不會出現在候選中,就算中繼簽章也會在驗證時被擋下。3

這三點並非各自獨立的巧思,而是從「共用秘密並傳送」的驗證方式,轉變為「用簽章證明自己持有秘密」的驗證方式這一個設計變更,所導出的結果。以下依序來看。

名詞之間的關係 ── Passkey・WebAuthn・FIDO2・CTAP

這個領域名詞很多,而且不同文章所指的範圍也不盡相同,先把彼此的關係整理清楚。Passkey 並不是一項新協定,而是既有規格組合起來的「稱呼」21

名詞 正式名稱 所指為何
WebAuthn Web Authentication API(W3C 建議標準) 瀏覽器與網站之間的規格。透過 navigator.credentials 要求建立金鑰對與簽章的 API
CTAP Client to Authenticator Protocol(FIDO 聯盟) 瀏覽器與外接驗證器之間的規格。透過 USB、NFC、藍牙與安全金鑰或手機通訊的部分
FIDO2 結合以上兩者的整體架構總稱。FIDO2 = WebAuthn + CTAP
Passkey(通行密鑰) FIDO2 的憑證中,可單獨用來取代密碼登入的(可探索憑證)那一種的稱呼

表1:Passkey 是建立在 FIDO2 這個地基之上的稱呼,而不是規格名稱

也就是說,「支援 Passkey」換成實作的說法,就是「實作 WebAuthn」。CTAP 是使用外接驗證器時由瀏覽器與作業系統代為處理的一層,開發 Web 應用程式的一方通常不會直接接觸到。

2. 密碼驗證究竟壞在哪裡

理解 Passkey 安全性的捷徑,是用「所在位置」來掌握密碼的弱點。在密碼驗證中,秘密本身在每一次驗證時都要走完整段路程

伺服器瀏覽器使用者伺服器瀏覽器使用者在腦中持有秘密(密碼)【弱點①】可被猜中・被重複使用【弱點②】在假網站上也能同樣輸入(外觀無法區分)【弱點③】秘密在路徑上流動雖有 TLS 保護,但終端會還原為明文【弱點④】所有使用者的秘密(雜湊)都集中在此一旦外洩就成為離線暴力破解的箭靶輸入密碼直接傳送密碼本身與已儲存的雜湊值比對

圖1:在密碼驗證中,秘密本身存在於整段路程

從攻擊者的角度來看,這是一種靶多、容易射中的結構。

  • 弱點①(使用者):強度僅止於人能記住的程度,且會在多個網站重複使用。一處外洩就會波及所有帳號(密碼列表攻擊)。
  • 弱點②(輸入的瞬間):只要準備一個與真網站幾乎無法區分的假網站,使用者就會自己把秘密交出來(網路釣魚)。
  • 弱點③(路徑):雖有 TLS 讓路徑本身的竊聽變得困難,但只要插入一個「外觀正規的中繼點」就沒有意義了(後述的 AiTM)。
  • 弱點④(伺服器):即使做了雜湊儲存,一旦資料庫外流,就能離線暴力破解,較弱的密碼會依序被破解。

「那麼加上一次性代碼(簡訊或 TOTP)不就好了嗎」──這就是傳統的多因素驗證,但這種方式傳送共用秘密的結構並沒有改變。TOTP 讓伺服器與驗證應用程式共用同一顆種子(秘密),而產生出來的 6 位數代碼終究還是可以被使用者輸入到假網站上。實際上,假網站即時中繼到真伺服器的AiTM(Adversary-in-the-Middle,中間人)型網路釣魚,就是直接把「密碼+一次性代碼」整組轉手而攻破的。美國網路安全暨基礎設施安全局(CISA)之所以把 FIDO/WebAuthn 方式與智慧卡(PIV/CAC)等以 PKI 為基礎的驗證,列為僅有的兩種「抗網路釣魚 MFA」,並將 FIDO 定位為黃金標準,正是因為這個原因。4

也就是說,問題不在於密碼的「強度」,而在於「共用秘密,且每次都傳送」這個結構本身

3. Passkey 的真面目 ── 不傳送秘密,而是證明自己持有秘密

Passkey 是建立在 W3C 的WebAuthn與 FIDO 聯盟的CTAP這兩項標準(合稱 FIDO2)之上,以公開金鑰加密為基礎的憑證。21 聽起來很難,但結構其實很單純。

伺服器使用者的裝置本機比對數學上的配對(產生簽章的一方)公開金鑰即使外洩也無法被濫用『僅供驗證用』的資訊驗證器(保險箱)Windows Hello / Face ID /Android 螢幕鎖定 / 安全金鑰私密金鑰完全不會流出此處指紋・臉部・PIN= 只用來打開保險箱門這也不會流出

圖2:Passkey 的實體是每個網站各自的金鑰對。私密的一側不會離開裝置,伺服器只持有用於驗證的公開金鑰

  • 私密金鑰是能產生簽章的一方,儲存在裝置內的驗證器中(Windows Hello、iPhone 的 Face ID/Touch ID、Android 的螢幕鎖定,或 YubiKey 之類的安全金鑰),不會流出。
  • 公開金鑰是只能驗證簽章的一方,會被交給伺服器保管。由公開金鑰反推私密金鑰在計算上是不可行的,因此即使外洩也無妨。
  • 指紋或臉部等生物特徵資訊只用於在本機打開保險箱的門,同樣不會流出裝置。生物特徵資訊不會被傳送到伺服器。1

註冊:只交出公開金鑰

在網站上註冊 Passkey 時的流程如下。

驗證器瀏覽器伺服器(example.com)驗證器瀏覽器伺服器(example.com)伺服器收到的只有「即使外洩也無法被濫用的資訊」註冊要求(亂數挑戰值 + 網站資訊)幫這個網站(example.com)建立金鑰以指紋・臉部・PIN 進行本人驗證(本機)產生新的金鑰對私密金鑰保存在內部公開金鑰 + credential ID(金鑰的名牌)傳送公開金鑰 + credential ID儲存為此帳號的公開金鑰

圖3:註冊時在網路上傳輸、並儲存於伺服器的只有公開金鑰

重點在於,此時金鑰對是與網站的網域(RP ID)綁定產生的。為 example.com 建立的 Passkey,只能在 example.com 這個網站上使用(由於 RP ID 是以網域為單位,所以 login.example.com 這種同一網域底下的子網域頁面可以使用,但無關的網域則無法使用)。這個綁定關係,正是後面會提到的抗網路釣魚能力的基礎。3

此外,金鑰對是每個網站每次都重新建立的。網站 A 和網站 B 的 Passkey 在數學上毫無關聯,因此「重複使用」這個概念本身並不存在,也無法作為在不同網站之間比對使用者身分的材料。

驗證:回傳一次性簽章

登入時的流程如下。請與密碼驗證(圖1)對照著看。

驗證器瀏覽器伺服器(example.com)驗證器瀏覽器伺服器(example.com)在路徑上傳輸的只有一次性的簽章就算被偷,下次的挑戰值也用不上登入要求(一次性的亂數挑戰值)要求對 example.com 進行簽章以指紋・臉部・PIN 進行本人驗證(本機)用私密金鑰產生簽章把挑戰值 + 來源 + RP ID 雜湊一併嵌入簽章(並非私密金鑰本身)傳送簽章用已儲存的公開金鑰驗證簽章同時確認挑戰值・來源・RP ID

圖4:驗證時秘密同樣不會移動。傳輸的只有「當場作廢的證明文件」

伺服器每次都出一個新的亂數(挑戰值),驗證器則針對「該挑戰值 + 瀏覽器目前所見的來源 + RP ID 的雜湊」進行簽章。伺服器以儲存好的公開金鑰驗證簽章,確認挑戰值確實是自己出的、來源與 RP ID 也確實是自家網站的。5

作為這套設計的結果,開頭三個理由中的兩個已經成立了。

  • 伺服器上沒有秘密:儲存的只有公開金鑰。就算外洩,攻擊者也無法產生簽章,不像密碼雜湊那樣可以「帶回家慢慢破解」。
  • 秘密不會流動:即使在路徑上偷走簽章,挑戰值是一次性的,無法重複使用(重放攻擊)。

剩下的最後一項,「假網站上簽章無法成立」,是 Passkey 最大的賣點。以下另闢一節詳細說明。

4. 網路釣魚為何「在結構上」無法成立

密碼之所以會被網路釣魚攻破,是因為能把真正的秘密輸入到假網站上。人類(尤其是疲累的時候)分辨不出 example.comexamp1e.com 的差異,但密碼輸入欄位在任何一個網站上都會照樣運作。

在 Passkey 中,這項比對不是由人來做,而是由瀏覽器機械式地進行。依 WebAuthn 規範,瀏覽器只有在「目前顯示畫面的來源網域」與「Passkey 的 RP ID」相符時,才能呼叫驗證器。3 以下用圖說明存取假網站的那一刻究竟發生了什麼事。

真正的伺服器(example.com)假網站(examp1e.com)中繼到真網站的 AiTM 代理伺服器瀏覽器使用者真正的伺服器(example.com)假網站(examp1e.com)中繼到真網站的 AiTM 代理伺服器瀏覽器使用者就算用某種方法產生了簽章,由於簽章中已嵌入 examp1e.com,在真正伺服器的驗證階段必定會被擋下存取外觀幾可亂真的登入畫面(在背後)啟動真正的登入處理挑戰值轉手挑戰值,要求簽章目前的來源是 examp1e.com無法列出 example.com 用的 Passkey不會產生簽章(使用者根本無從被騙)

圖5:AiTM 型網路釣魚能攻破密碼+一次性代碼,但在 Passkey 上於簽章階段就無法成立

請注意這裡的防護是雙重的。

  1. 不會出現在候選中:瀏覽器只會列舉對應該來源的 RP ID 的 Passkey。在假網域上,真網站用的 Passkey 不會出現在選項中,使用者連「不小心用到」都做不到。
  2. 簽章無法通過:簽章目標中包含瀏覽器所確認的來源與 RP ID 的雜湊。真正的伺服器在驗證時會比對這些內容,因此在別的來源下產生的簽章必定會被拒絕。5

密碼的網路釣魚對策,依賴的是「使用者仔細看清 URL」這種人的努力。而在 Passkey 上,使用者原本就不需要辨別假網站。這正是「抗網路釣魚(phishing-resistant)」一詞真正的含意,也是 CISA 與美國國家標準暨技術研究院(NIST)特別看重 FIDO/WebAuthn 方式的原因。46

到此為止的內容,依攻擊手法整理如下。

攻擊 密碼 密碼+TOTP Passkey
猜測・暴力破解 ✗ 弱 △ 能擋代碼,但原本的密碼仍然很弱 ○ 沒有可猜測的對象
重複使用(列表攻擊) ✗ 一處外洩就波及全部 △ 從未支援代碼的網站開始崩潰 ○ 每個網站都是獨立金鑰
伺服器資料庫外洩 ✗ 雜湊值可離線暴力破解 ✗ TOTP 的種子(共用秘密)也會外洩 ○ 只有公開金鑰
傳統網路釣魚(誘導在假網站輸入) ✗ 能被輸入進去 ✗ 代碼也能被輸入進去 ○ 不會出現在候選中,簽章也無法通過
AiTM(即時中繼) ✗ 直接被轉手 ✗ 連代碼一起被轉手 ○ 因來源比對而無法產生簽章
重放(重複使用通訊內容) ✗ 同一組密碼可無限次有效 △ 若在本人使用前被攔截,該代碼仍有效(正確實作下會拒絕已使用過的代碼再次被接受) ○ 挑戰值每次都是一次性的

表2:依攻擊手法比較各方式的抵抗力。Passkey 的每一個「○」都不是來自運用或注意力,而是來自結構本身

5. 「會同步的 Passkey」安全嗎

讀到這裡,自然會冒出這樣的疑問:「不是說私密金鑰不會離開裝置嗎,那為什麼在 iPhone 上建立的 Passkey 在 iPad 上也能用?」──這是個好問題,答案是「Passkey 有兩種」。

先把結論整理成速查表放在前面。這一節和下一節,可以當作是在說明這張表裡每一列為什麼會是這樣。

觀點 同步型 Passkey 裝置固定型 Passkey
代表範例 iCloud 鑰匙圈、Google 密碼管理員、1Password 等密碼管理員 安全金鑰(YubiKey 等)、Windows Hello、Microsoft Authenticator 內的 Passkey
私密金鑰的保存位置 平台的憑證保管庫。以端對端加密的形式複製到同一帳號的各裝置之間 驗證器的硬體內部。不會離開 TPM 或安全元件
遺失・換機時 只要登入同一個 Apple ID/Google 帳號,就能還原到新裝置 該驗證器的 Passkey 會遺失。前提是預先登錄多個備援驗證器
單點故障 平台的雲端帳號 實體裝置本身
是否適合企業管理 由於金鑰存放在個人的雲端帳號中,組織端較難掌握所在位置或一併撤銷。適合 BYOD 或小規模場景 管理者可配發・撤銷,金鑰所在位置明確。適合規範嚴格的環境
NIST 的 AAL 適用性 若滿足要求可達 AAL2。由於私密金鑰可被匯出,無法用於 AAL36 由硬體保護、無法取出金鑰的驗證器,可能符合 AAL3 所要求的條件6

表3:同步型與裝置固定型的速查表。該選哪一種,取決於要優先考量「抗遺失能力」還是「掌控金鑰所在位置」

裝置固定型 Passkey安全金鑰(YubiKey 等) /Windows Hello /Microsoft Authenticator(Entra ID)私密金鑰不會從該硬體物理性地流出(由 TPM 等保護)優點:金鑰所在位置單一且明確注意:必須為遺失情況登錄多個備援同步型 Passkey(消費端的預設選項)iCloud 鑰匙圈 /Google 密碼管理員 /1Password 等密碼管理員在同一帳號的裝置之間以端對端加密同步業者本身也無法讀取內容優點:抗換機、抗遺失注意:需要保護好雲端帳號本身

圖6:同步型與裝置固定型。兩者「不把私密金鑰傳送到伺服器」這一點相同,差別在於防護的重心

同步型 Passkey是指 iCloud 鑰匙圈或 Google 密碼管理員在同一帳號的裝置之間同步私密金鑰的類型。這裡重要的是,同步是端對端加密的。Apple 和 Google 都明確表示,Passkey 會先在裝置上加密後才同步,就連業者自己也無法讀取內容。78 也就是說,「私密金鑰不會離開裝置」這個原則,正確來說被放寬為「私密金鑰不會以明文形式離開裝置」,換來的則是對換機或遺失的抵抗力。

這個放寬會如何改變威脅模型,值得明確說清楚。需要防護的地方,會從「各個網站的伺服器」集中到「單一個雲端帳號」。對各網站資料庫外洩或網路釣魚仍然保持強韌,但這次換成 Apple ID/Google 帳號本身遭劫持,成為新的單點故障。正因如此,替 Passkey 所寄存的平台帳號施加最強的防護(強力的螢幕鎖定、整理好復原手段、可能的話再加上實體安全金鑰),是不可或缺的前提。NIST 也在 2024 年 4 月發布了NIST SP 800-63B 補篇(Supplement 1: Incorporating Syncable Authenticators Into NIST SP 800-63B),正式將這類同步型 Passkey(syncable authenticator)定位為:若滿足要求,可符合政府標準的AAL2(Authenticator Assurance Level 2,驗證器保證等級 2)。不過,由於私密金鑰有可能被匯出,因此規定要求硬體隔離環境的 AAL3 不得使用同步型。6

裝置固定型 Passkey則是私密金鑰不會離開硬體的類型。典型代表是 YubiKey 之類的安全金鑰,在法人環境中,Microsoft Entra ID 的 Passkey(建立在 Microsoft Authenticator 內的那種)也屬於裝置固定型。9 Windows 的 Windows Hello 也是一樣,只要有 TPM,就會在 TPM 底下保護私密金鑰。這種「不讓金鑰流出的硬體保險箱」機制本身,與TPM 那篇文章中詳細解說的地基是相同的。

順帶一提,或許你曾經好奇過:「用手機的 Passkey 登入 PC 上的瀏覽器」時,為什麼要掃描 QR Code。那並不只是單純的畫面切換,而是透過藍牙確認手機與 PC 在實體上彼此靠近的混合式驗證(FIDO 的跨裝置驗證)。這種近距離確認,正是用來阻擋「遠端攻擊者透過 QR Code 讓別人替自己核准登入自己的 PC」這種攻擊。1

6. 並非萬靈丹 ── 弱點不是「消失」,而是「移動」

到目前為止說明了 Passkey 的強項,但誠實地說,Passkey 並不是消滅攻擊的技術,而是把攻擊者逼向更弱的地方的技術。當驗證這道玄關變得堅固之後,攻擊者會轉往何處,用圖來呈現。

攻擊者驗證本身挑戰值簽章【堅固】帳號復原流程謊報『Passkey 弄丟了』用簡訊或 email 重新設定,登錄攻擊者自己的 Passkey並存的備援手段若仍保留密碼・簡訊登入,最弱的一環就在那裡雲端帳號若是同步型,Apple ID /Google 帳號就是單點故障工作階段只要偷到登入後的 Cookie,驗證方式就無關緊要

圖7:玄關(驗證)變堅固之後,攻擊會轉往復原流程・備援手段・雲端帳號・工作階段

實務上必須留意的殘存風險有以下四項。

  1. 並存的備援手段會成為最弱的一環。如果只是「讓 Passkey 也能用」,但密碼或簡訊登入仍然保留著,攻擊者只要用那些就好。整個帳號的抗網路釣魚能力,會被最弱的登入手段的等級所限制。導入的重點工作,並不是新增 Passkey 本身,而是有計畫地縮減、廢除備援手段。
  2. 復原流程會成為新的攻擊面。謊稱「裝置弄丟了」,透過客服窗口或 email 的重新設定流程,讓攻擊者登錄自己的 Passkey,這是一種常見手法。實際上,繞過堅固的驗證機制、以社交工程手法欺騙客服人員,已成為大規模入侵事件的慣用手段。驗證變堅固之後,如何設計復原流程的本人驗證,就成了關鍵課題。
  3. 同步型的雲端帳號是單點故障。如前一節所述。需要防護寄存 Passkey 的帳號本身,並在組織使用時決定「允許同步到哪些平台」的方針。
  4. 無法防止工作階段被竊取。Passkey 保護的只有登入那一瞬間,登入後的工作階段 Cookie 若被惡意軟體或 XSS 竊取,驗證方式就無關緊要了。權杖有效期限、綁定、裝置健康狀態管理等另一層的工作依然存在。

這些並不是在說「還是別用 Passkey 了」,而是理所當然的道理:即使把玄關的鎖換成最新款,窗戶的上鎖仍然是另一件要做的事。反而正因為弱點的位置變得明確,才更能把防禦資源集中投入在復原流程與工作階段管理上。

7. 實務導入 ── WebAuthn API 與 Windows 環境

最後從導入方的角度整理重點。

為自家的 Web 服務加上 Passkey 登入

瀏覽器端只需要 WebAuthn API 的兩個函式。註冊時呼叫 navigator.credentials.create(),驗證時呼叫 navigator.credentials.get()

// 註冊(瀏覽器端)
const credential = await navigator.credentials.create({
  publicKey: {
    challenge: challengeFromServer,   // 由伺服器產生的一次性亂數
    rp: { id: "example.com", name: "Example" },
    user: { id: userIdBytes, name: "taro@example.com", displayName: "太郎" },
    pubKeyCredParams: [{ type: "public-key", alg: -7 }],  // ES256
    authenticatorSelection: {
      residentKey: "required",        // 設為可探索憑證(=Passkey)
      userVerification: "required",   // 要求以生物驗證/PIN 進行本人驗證
    },
  },
});
// 公開金鑰從 credential.response 取出,credential ID 則從最上層的
// credential.id / credential.rawId 取出。註冊回應也和驗證時一樣,
// 要在伺服器端先驗證挑戰值・來源・RP ID 之後才儲存

主要參數的意義如下。

參數 作用 實作時的注意事項
challenge 伺服器每次產生的一次性亂數 使用不可猜測的密碼學亂數。伺服器端要驗證「這是自己發出過且尚未使用」的值後再消耗掉
rp.id 憑證所綁定的網域(RP ID) 省略時會取呼叫端來源的有效網域。可以像從 login.example.com 指定 example.com 那樣,但僅限於可註冊網域的範圍內
user.id 伺服器內部的使用者識別碼(user handle) 64 位元組以下的不透明值。不要直接放入 email 或使用者名稱這類可辨識個人的資訊2
user.name / user.displayName 顯示在驗證器或瀏覽器 UI 上、供使用者選擇帳號用的字串 僅供顯示用。伺服器不應信任這個值來判定帳號
pubKeyCredParams 依優先順序列出可接受的公開金鑰演算法 除了 -7(ES256)之外,一併列上 -257(RS256),可擴大能被接受的驗證器範圍
authenticatorSelection 對驗證器要求的性質 residentKey: "required" 使其成為 Passkey(可探索憑證),userVerification: "required" 使生物驗證・PIN 的本人驗證成為必要條件

表4:navigator.credentials.create() 的主要參數

測試環境注意事項:由於 WebAuthn API 只在安全情境下才會公開,若以純 http:// 提供頁面,navigator.credentials 的呼叫會失敗。例外是 http://localhost(以及 127.0.0.1),這些會被視為可信任的來源,因此在開發機上即使不做 HTTPS 化也能直接測試。不過由於 RP ID 必須是來源的有效網域(或其上層網域),因此在 localhost 上建立的 Passkey 無法用在正式環境的網域上。就算手邊沒有驗證器,只要在 Chrome 開發人員工具的「WebAuthn」分頁啟用虛擬驗證器,也能完整測試從註冊到驗證的整個流程。

// 驗證(瀏覽器端)
const assertion = await navigator.credentials.get({
  publicKey: {
    challenge: challengeFromServer,
    rpId: "example.com",
    userVerification: "required",
  },
  // 以登入欄位的自動填入候選方式提示 Passkey。事先透過
  // PublicKeyCredential.isConditionalMediationAvailable() 確認是否支援,
  // 不支援的瀏覽器則退回不加 mediation 的一般呼叫方式
  mediation: "conditional",
  // (對應的 <input> 需要加上 autocomplete="username webauthn")
});
// 在伺服器端驗證 assertion.response 的簽章

主體是伺服器端的驗證。至少必須確實執行以下項目。5

  • 比對挑戰值:是否為自己發出且尚未使用的挑戰值。是否採一次性使用(防重放)。此外,要與發行時的瀏覽器工作階段(登入嘗試)綁定儲存,只允許來自同一工作階段的回應消耗它。這裡若做得不夠嚴謹,就會出現攻擊者透過受害者的瀏覽器,把針對自己的挑戰值的簽章送進系統,讓受害者登入攻擊者帳號的空間(登入型 CSRF)。
  • 比對來源clientDataJSONorigin 是否為自家網站的正規來源(這是網路釣魚對策的關鍵)。
  • 比對 RP ID 雜湊authenticatorDatarpIdHash 是否與自家網站 RP ID 的 SHA-256 一致。
  • 確認儀式種類與旗標clientDataJSONtype 在驗證時應為 webauthn.get,註冊時應為 webauthn.createauthenticatorData 的 UP(使用者在場)旗標是否已設定。若要求了使用者驗證(UV),UV 旗標是否也已設定。
  • 驗證簽章:能否用註冊時儲存的公開金鑰正確驗證簽章。
  • 與帳號綁定:以呈現的 credential ID(及 userHandle)在自家資料庫中查找,並確認是對該憑證的持有者發行工作階段。若無條件信任另外輸入的使用者名稱,就會出現用正確簽章卻登入成他人的漏洞。
  • 儲存並比較簽章計數器:把 authenticatorData 的 signCount 依憑證分別儲存,並確認下一次的值是否比上一次大。若小於等於上一次的值(含相同值),就視為驗證器被複製(複製攻擊)的徵兆來處理。不過同步型 Passkey 有許多實作會固定回傳 0,因此僅在雙方都為 0 時例外放行。

自行手寫這套驗證容易出事故,請使用有實績的函式庫(.NET 可用 fido2-net-lib,Node.js 可用 SimpleWebAuthn 等)。把規格細節(CBOR 解析、演算法協商、挑戰值管理)交給函式庫處理,自己則專注在挑戰值的儲存與失效、多把 Passkey 的管理介面、復原流程的設計上,才是正確的力氣分配方式。

Windows 環境・企業內部系統的情況

作為本站的讀者群——「負責維護 Windows 業務系統」的立場,只要掌握以下三點就足夠了。

  • Windows 用戶端已經支援。Windows 11 支援以 Windows Hello 作為驗證器來建立、使用、管理 Passkey(設定 > 帳戶 > Passkey),只要有 TPM,私密金鑰就會受到硬體保護。10 透過瀏覽器(Edge/Chrome)使用的 WebAuthn,在 Windows 10 上也能運作。
  • 在 Entra ID 環境中,啟用「Passkey=FIDO2 驗證方式」。Microsoft Entra ID 支援安全金鑰以及 Microsoft Authenticator 應用程式內的 Passkey(裝置固定型),只要在條件式存取的驗證強度中要求「抗網路釣魚 MFA」,就能將對目標資源的存取限制為 Passkey 等方式。9 從 NTLM 或密碼到期原則的世界遷移過來,並非一蹴可幾,可以與NTLM 和 Kerberos 那篇文章中討論的驗證基礎架構盤點同時進行,先從管理員帳號開始強制要求抗網路釣魚 MFA,是常見的做法。
  • 企業內部 Web 應用程式受惠的方式相同,但前提是要有 HTTPS。由於 WebAuthn API 只能在安全情境下運作,即使是內部網路的應用程式,也需要(開發時的 localhost 除外)先完成 HTTPS 化,並整理好可作為 RP ID 使用的內部網域名稱。只要做到這一步,RP ID 對內部網域同樣有效。從貼在螢幕上的密碼便利貼中解放出來的意義上,內部系統往往比對外服務更快看到成效,這種情況並不少見。

8. 總結

  • 密碼的弱點不在於強度,而在於「共用秘密,且每次驗證都傳送」的結構。秘密同時存在於使用者、輸入欄位、路徑、伺服器等所有位置,因此攻擊目標眾多。就算加上一次性代碼,也會在 AiTM 型網路釣魚面前被中繼攻破。
  • Passkey 是每個網站各自的公開金鑰加密金鑰對,交給伺服器的只有即使外洩也無法被濫用的公開金鑰,登入時傳送的只有針對一次性挑戰值的簽章。伺服器上沒有秘密,路徑上也不會有秘密流動
  • 簽章中嵌入了瀏覽器所確認的來源與 RP ID,因此在假網站上真網站用的 Passkey 不會出現在候選中,即使中繼也會在驗證時被擋下。使用者不需要辨別假網站,這正是「抗網路釣魚」的真正含意,安全的依據也從人的注意力轉移到了協定的結構。
  • 同步型 Passkey 以端對端加密方式同步,對換機、遺失有很強的抵抗力。相對地,需要防護的地方會集中到雲端帳號,因此 Apple ID/Google 帳號本身的防護就成了大前提。法人也可以選擇裝置固定型(安全金鑰、Entra ID 的 Authenticator Passkey)。
  • Passkey 並不是消滅攻擊,而是把攻擊逼向較弱的地方。並存的密碼、帳號復原流程、工作階段竊取仍是殘留的攻擊面,導入的重點工作在於有計畫地縮減備援手段,以及強化復原流程。
  • 實作上就是 WebAuthn API 的 create / get 兩個函式,加上伺服器端驗證。驗證不要自行實作,交給有實績的函式庫,把力氣花在挑戰值管理、多把 Passkey 的介面、復原流程設計上。

相關文章

相關諮詢領域

合同會社小村軟體承接的委外開發範圍,包括支援企業內部 Web 系統的 Passkey 登入・WebAuthn 實作、在 Entra ID 環境中設計抗網路釣魚 MFA 的部署,以及將驗證機制整合進 WinForms/WPF 等 Windows 業務應用程式。

  1. FIDO 聯盟, Passkeys(通行密鑰)How FIDO Works。關於 Passkey 作為 FIDO 憑證取代密碼;生物特徵資訊不會從裝置傳送出去,只用於本機比對;2022 年 5 月 Apple、Google、微軟共同宣布擴大支援以 FIDO 標準實現無密碼化;跨裝置使用時採用透過 QR Code 與藍牙進行近距離確認的混合式方式。  2 3 4 5

  2. W3C, Web Authentication: An API for accessing Public Key Credentials Level 2(W3C 建議標準)。關於 WebAuthn 是一套用來建立、使用以公開金鑰加密為基礎的憑證的 API:憑證的私密金鑰保存在驗證器中,伺服器(Relying Party)只登錄公開金鑰與 credential ID;驗證是透過對伺服器發出的挑戰值進行簽章(斷言)來完成;以及憑證的範圍與保護的設計目標。本文也一併參照了:API 只在安全情境下公開、RP ID 省略時會取呼叫端來源的有效網域,以及 user handle(user.id)是最大 64 位元組的不透明值、不應包含使用者名稱或 email 等可辨識個人的資訊(§14.6.1 User Handle Contents)等內容。  2 3 4 5

  3. W3C, Web Authentication Level 2 — §5.1.3 Create / RP ID validation, §13.4.9 Regarding phishing。關於公開金鑰憑證的範圍限定於 RP ID(Relying Party 識別碼=網域);瀏覽器(用戶端)會驗證呼叫端來源的可註冊網域與 RP ID 是否對應,若不對應則拒絕建立、使用憑證;由此使得假來源無法存取其他網站用的憑證,讓 WebAuthn 對包含中間人型在內的網路釣魚攻擊具有抵抗力。  2 3

  4. CISA, Implementing Phishing-Resistant MFA(2022 年 10 月的說明文件)。關於使用簡訊、語音、推播通知、OTP 的 MFA 對網路釣魚及 AiTM(中繼)攻擊、MFA 疲勞攻擊的脆弱性;具抗網路釣魚能力的方式僅列出 FIDO/WebAuthn 驗證與以 PKI 為基礎的驗證(智慧卡等)兩種,其中 FIDO/WebAuthn 驗證被定位為黃金標準;以及組織應優先從高風險帳號開始遷移至抗網路釣魚 MFA。  2

  5. W3C, Web Authentication Level 2 — §7.2 Verifying an Authentication Assertion。關於伺服器端的驗證步驟:規定要驗證 clientDataJSON 的 type、challenge(與自己發出的是否一致)、origin,驗證 authenticatorData 中的 rpIdHash 是否與預期的 RP ID 的 SHA-256 雜湊一致,確認 User Present / User Verified 旗標,並以已儲存的公開金鑰驗證簽章。  2 3

  6. NIST, Incorporating Syncable Authenticators Into NIST SP 800-63B(2024 年 4 月的補篇,已整合進 SP 800-63B 第 4 版)。關於可同步驗證器(同步型 Passkey)的私密金鑰若以符合要求的形式儲存並複製於同步結構中,可滿足 AAL2;另一方面,AAL3 的加密驗證器要求硬體保護、隔離的環境,因此私密金鑰可被匯出的同步型驗證器不得用於 AAL3;以及像 WebAuthn 這類會進行來源驗證的方式,被歸類為具有驗證者冒充抵抗力(抗網路釣魚)。原文 PDF 見NIST SP 800-63B Supplement 1。  2 3 4

  7. Apple 支援, 關於通行密鑰的安全性。關於 Passkey 透過 iCloud 鑰匙圈同步;iCloud 鑰匙圈採端對端加密,就連 Apple 也無法讀取;同步受使用者裝置上的金鑰保護,並提供附有速率限制的託管復原機制。 

  8. Google, Security of Passkeys in the Google Password Manager。關於 Passkey 的私密金鑰會先在裝置上加密後才同步;由於端對端加密,就連 Google 自己也無法存取私密金鑰的內容;還原時需要基於裝置螢幕鎖定等機制的保護。 

  9. Microsoft Learn, 在 Microsoft Entra ID 中啟用 FIDO2 驗證(通行密鑰)。關於 Entra ID 支援以 FIDO2 安全金鑰及 Microsoft Authenticator 的 Passkey(裝置繫結)實現具抗網路釣魚能力的無密碼驗證;可透過驗證方法原則啟用,並可用條件式存取的驗證強度(抗網路釣魚 MFA)進行要求。  2

  10. Microsoft Learn, Windows 上的通行密鑰支援。關於 Windows 11 支援以 Windows Hello 建立、使用 Passkey;已儲存的 Passkey 可從設定 > 帳戶 > Passkey 進行管理;在可使用 TPM 的環境中,Windows Hello 的憑證會受到硬體保護;行動裝置上的 Passkey 可透過 QR Code 使用。 

共用相同標籤的最新文章。能以相近的主題延伸理解。

與本文相近的主題頁面。以本文為起點,可進一步連到相關服務與其他文章。

常見問題

整理諮詢這個主題時常見的問題。

Passkey 和密碼的根本差異是什麼?
密碼是一種「使用者與伺服器共用同一個秘密,每次登入都要傳送這個秘密」的機制。由於秘密存在於使用者腦中、輸入欄位、通訊路徑、伺服器資料庫等所有地方,所有這些地方都會成為攻擊目標。Passkey 使用公開金鑰加密的金鑰對,私密金鑰不會被傳送到伺服器。在裝置固定型中,私密金鑰完全不會離開驗證器;即使在同步型中,也只會以端對端加密的形式流出。伺服器儲存的只有公開金鑰這種「即使外洩也無法被濫用的資訊」,登入時傳送的也只是針對當下一次性挑戰值的簽章。也就是說,密碼的弱點——「被共用的秘密」本身——並不存在。此外,金鑰對是針對每個網站分別產生的,因此「重複使用」這個概念本身也不成立。
生物特徵資訊(指紋・臉部)會被傳送到伺服器嗎?
不會。指紋或臉部資料只在裝置內部用於「打開存放私密金鑰的保險箱門」這項本機比對,依 FIDO 的設計,生物特徵資訊不會被傳送到裝置之外。伺服器收到的只是一個表示「已完成使用者本人驗證(使用者驗證)」的旗標簽章,完全不包含指紋本身,當然也不包含其特徵值。在無法使用生物驗證的場合可以用 PIN 代替,但這個 PIN 和 Windows Hello 的 PIN 一樣,只會在裝置本機進行比對,不會在網路上傳輸,這一點與密碼有決定性的不同。
為什麼 Passkey 對網路釣魚有抵抗力?
因為在機制上,使用者原本就不需要辨別假網站。Passkey 是與網站的網域(RP ID)綁定產生的,瀏覽器只會列出對應「目前顯示網站的網域」的 Passkey 作為候選。即使存取了與真網站幾可亂真的假網域,真網站專用的 Passkey 也不會出現在選項中,使用者根本無從被騙。此外,簽章中還會嵌入瀏覽器所確認的來源(origin)與 RP ID 的雜湊值,因此即使中繼簽章,也會在真正的伺服器端驗證時被擋下。像密碼或簡訊驗證碼那樣「把真正的憑證輸入到假網站」這種事故,在結構上就無法發生,這是與依賴訓練和提醒的對策根本不同之處。
如果手機遺失,會不會無法登入帳號?
如果是同步型 Passkey(儲存在 iCloud 鑰匙圈或 Google 密碼管理員中的那種),可以還原到已登入相同 Apple ID/Google 帳號的新裝置上。不過,還原端對端加密保管庫時,除了帳號密碼之外,通常還會要求輸入舊裝置的螢幕鎖定密碼等額外的本人驗證,因此如果連這些復原手段也一併遺失,就可能無法還原。不要把一切都只交給一支手機,這一點很重要。裝置固定型(安全金鑰或 Windows Hello 等)與裝置命運與共,因此對於重要帳號,通常的做法是登錄多個 Passkey。許多服務都允許一個帳號登錄多個 Passkey。請注意,遺失時的失效程序會因種類而異:同步型因為各裝置上的副本其實是同一份憑證,所以要先在平台帳號端刪除遺失裝置或執行遠端清除,讓裝置上的副本失效(在服務端的帳號設定中刪除該 Passkey,會一次讓所有裝置上的副本失效)。裝置固定型的話,只要在服務端刪除該驗證器的 Passkey,就能只讓遺失的那把鑰匙失效。若是在組織中使用,重要的是同時設計「使用者能自行復原的雙重化機制」與「遺失時由管理者強制失效的程序」。
Passkey 也有弱點嗎?
有。不過更準確的說法是,弱點的位置改變了。由於驗證本身透過公開金鑰加密而變得堅固,攻擊者會轉而瞄準較弱的周邊環節。具體來說包括:如果密碼或簡訊等傳統手段仍並存,那裡就會成為最弱的一環;濫用帳號復原流程讓攻擊者登錄自己的 Passkey 的手法;以及在同步型中,雲端帳號本身遭劫持會成為新的單點故障。此外,竊取登入後的工作階段 Cookie 這類攻擊,Passkey 也無法防止,並非所有無關的威脅都會消失。導入時不能只是「加上 Passkey」,還必須連同強化復原流程、有計畫地縮減備援手段一併納入設計。

作者檔案

本文作者的個人檔案頁面。

Go Komura

小村軟體有限公司 代表

以 Windows 軟體開發、技術諮詢與故障調查為中心,在難以重現的故障調查與既有資產仍在運作的專案上具有優勢。

回到部落格一覽