认证和断言

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)不支持此输出。

需要强调的是,断言的签名使用的是与证明不同的密钥对。断言是使用在注册过程中为服务生成的密钥对进行签名的。证明是使用刻录到所有相同设备型号中的证明私钥和证明证书进行签名的。(除了自证明的情况。)