返回

文章详情

不透明的可互操作通行证记录(以及 Go API)

Hacker News2026年7月20日 23:00

通行证是当前信息安全领域最重要的事情,因为它们是针对网络钓鱼攻击压倒性有效性唯一合乎原则的解决方案。就像内存安全是应对内存损坏攻击的唯一合乎原则的解决方案一样。不幸的是,在服务器端实现这些功能似乎比使用密码哈希更复杂。这部分是不可避免的,因为通行证需要与浏览器交互以获得其抗钓鱼特性。然而,另一部分可以通过定义可互操作的通行证记录编码更有效地抽象化。WebAuthn 规范将凭证记录定义为一个抽象概念,包含多个组件,如类型、ID、公钥、备份状态、传输方式和其他标志。谷歌建议使用一个包含凭证 ID 主键,以及公钥、已备份和传输方式列的数据库表。Adam Langley 的杰出 WebAuthn 之旅同样推荐使用 cred_id 主键,以及单独的 public_key_spki 和 backed_up 列。所有指导都建议使用库来处理 WebAuthn 身份验证,但这仍然使得应用程序可能拥有一个不可互操作的数据库 schema。将整个身份验证流程和数据库交互推迟给库或框架可能也不切实际。可互操作的、良好指定的通行证记录,可以让应用程序像处理密码哈希一样以不透明字符串的形式处理,可能是一个中间抽象层。c2sp.org/passkey-record 是一个规范提案,借用了密码哈希竞赛 (PHC) 字符串的语法,并重用了现有的身份验证器数据编码来处理大部分工作。记录的形式如下:$webauthn$v=1$transports=hybrid+internal$<base64 身份验证器数据> 负载是身份验证器数据,是 CTAP2 CBOR 编码的大部分凭证记录字段,已由 WebAuthn 指定,并包含在 AuthenticatorAttestationResponse 的 JSON 编码中(即使没有使用证明)。传输是唯一缺失的字段,并作为 PHC 参数存储。然后,应用程序只需负责跟踪与用户账户关联的通行证记录,这是一个网络开发人员熟悉的任务,因为它与实现密码身份验证并没有太大区别(除了每个账户有多个通行证)。这些不透明字符串可以传递给库以验证登录声明(或使用适当的 excludedCredentials 生成注册请求)。有了良好指定的可互操作存储格式,希望能够在保留凭证数据库的同时更换通行证库(甚至后端语言)。 你可能想要存储的其他字段 除了通行证记录外,应用程序可能仍希望存储元数据字段,如用户选择的昵称以及创建和最后使用的时间戳,以提供优雅的通行证管理用户界面。这些都不需要 WebAuthn 库的特殊处理。唯一的例外是备份状态标志。通行证向服务器报告它们是否被备份(例如,备份到 iCloud 钥匙串或 Google 账户),服务器可以使用该信号建议从账户中移除密码。此标志可以在登录之间变化,而通行证记录是不可变的,因此必须单独存储并在每次登录时更新。我认为对于普通网站来说,这一逻辑被高估了,因为无论如何,它们仍将支持电子邮件密码重置。一个潜在的加密/通行证 API 在这些通行证记录的基础上,我草拟了一个潜在的无状态 Go 包 API。注册流程是调用 RelyingParty.NewRegistration,传入已登录(或其他识别)的用户详细信息和任何现有的通行证记录,把返回的 JSON 传递给 parseCreationOptionsFromJSON(),然后传递给 navigator.credentials.create(),将返回的 JSON 编码的 PublicKeyCredential 传递给 RelyingParty.Register,将返回的通行证记录存储在数据库中。登录流程是调用 RelyingParty.NewLogin,同时生成登录页面,将返回的请求存储在键值缓存中,TTL 较短,作为 RequestID(request),并将返回的 JSON 传递给 parseRequestOptionsFromJSON(),然后传递给 navigator.credentials.get(),将返回的 JSON 编码的 PublicKeyCredential 传递给 Inspect,并使用返回的 requestID 从键值缓存中检索请求,并使用返回的 userID 从数据库中检索通行证记录,将 JSON PublicKeyCredential、请求以及通行证记录传递给 RelyingParty.Login。应用程序负责将不透明、永久的、保护隐私的用户 ID 与每个用户关联;存储与用户关联的通行证记录;以及缓存由 RelyingParty.NewLogin 产生的请求挑战。该库提供的 JSON 值可以直接传递给 parseCr

赞助内容

NordVPN Next-gen Antivirus

本站免费、广告极少。如果觉得有帮助,可以请我们喝杯咖啡 —— 任何金额都对持续运营有实际帮助。

请我喝杯咖啡