認證和斷言

WebAuthn 在註冊和身份驗證過程中使用了兩種不同型別的證書。它們名稱相似,用途也相似,但理解它們的區別可能是初學者容易混淆的地方。下面的章節將分別描述註冊過程中發生的證明(attestation)和身份驗證過程中發生的斷言(assertion)。

證明 (Attestation)

當身份驗證器向服務註冊新的金鑰對時,身份驗證器會使用證明證書對公鑰進行簽名。證明證書在製造時就已內建到身份驗證器中,並且特定於裝置型號。也就是說,所有在特定時間或特定生產批次製造的“三星 Galaxy S8”手機都擁有相同的證明證書。

證明透過 WebAuthn API 以 AuthenticatorAttestationResponse 的形式返回。證明格式包含兩個基本的 ArrayBuffer 物件。

  • clientDataJSON - 一個 ArrayBuffer,包含瀏覽器在被要求進行身份驗證時所看到內容的 JSON 表示。
  • attestationObject - 一個加密證明,表明新生成的金鑰對是由該身份驗證器建立的。它包含:
    • 身份驗證器資料,其中包含一個 attestedCredentialData 欄位,該欄位又包含 credentialIdcredentialPublicKeyattestedCredentialData 是在證明中使用的一個可選欄位。在 AuthenticatorAssertionResponse 中使用時,它不包含此欄位。
    • 一個證明宣告,該宣告是可選的,取決於信賴方是否請求證明。通常,不鼓勵信賴方請求證明,因此這個宣告更有可能不存在。

不同的裝置有不同的證明格式。WebAuthn 中 預定義的證明格式 包括:

  • Packed - 一種通用的證明格式,通常由僅作為 WebAuthn 身份驗證器執行的裝置使用,例如安全金鑰。
  • TPM - 可信平臺模組 (TPM) 是可信平臺組 (TPG) 的一組規範。此證明格式通常在臺式計算機中找到,並被 Windows Hello 作為其首選證明格式。
  • Android Key Attestation - Android O 中增加的功能之一是 Android Key Attestation,它使 Android 作業系統能夠證明金鑰。
  • Android SafetyNet - 在 Android Key Attestation 之前,Android 裝置唯一的選擇是建立 Android SafetyNet 證明。
  • FIDO U2F - 實現 FIDO U2F 標準的安全金鑰使用此格式。
  • none - 瀏覽器可能會提示使用者是否允許某個網站檢視其證明資料,並且/或者如果 navigator.credentials.create() 中的 attestation 引數設定為 none,則可能會從身份驗證器的響應中移除證明資料。

證明的目的是透過加密方式證明新生成的金鑰對來自特定裝置。這為新生成的金鑰對提供了信任根,同時也能夠識別正在使用的裝置的屬性(私鑰如何受到保護;是否/何種型別的生物識別技術正在使用;裝置是否已認證等)。應注意的是,儘管證明提供了信任根的能力,但驗證信任根通常並非必要。在為新帳戶註冊身份驗證器時,通常會應用“首次使用即信任” (TOFU) 模型;而在向現有帳戶新增身份驗證器時,使用者已經過身份驗證並建立了安全會話。

斷言 (Assertion)

當用戶選擇登入某個服務時,伺服器會發送一個挑戰,身份驗證器使用之前已註冊到該服務的金鑰對對此挑戰進行簽名。這就建立了一個斷言。與證明不同,斷言的格式始終相同,與所使用的裝置無關。

斷言透過 WebAuthn API 以 AuthenticatorAssertionResponse 的形式返回。斷言格式相當簡單,因為它包含四個基本的 ArrayBuffers:

  • clientDataJSON - 與證明中的相同。一個 ArrayBuffer,包含瀏覽器在被要求進行身份驗證時所看到內容的 JSON 表示。
  • authenticatorData - 由身份驗證器建立和/或使用的資料(另請參閱 身份驗證器資料)。
  • signature - 對 clientDataJSON 和 authenticatorData 的簽名,可以使用在註冊過程中建立的公鑰進行驗證。
  • userHandle - 可選。(可空)使用者識別符號。這可以是使用者名稱、使用者名稱的雜湊值等。服務用於為憑據設定範圍。最大長度為 64 位元組。較舊的身份驗證器(U2F)不支援此輸出。

需要強調的是,斷言的簽名使用的是與證明不同的金鑰對。斷言是使用在註冊過程中為服務生成的金鑰對進行簽名的。證明是使用刻錄到所有相同裝置型號中的證明私鑰和證明證書進行簽名的。(除了自證明的情況。)