mcpField
I
implementing-hardware-security-key-authentication

implementing-hardware-security-key-authentication

github.com/mukul975安全35.2k48 次安装8 周前更新
代码仓库

关于 implementing-hardware-security-key-authentication

面向开发者的实践指南,介绍如何用 WebAuthn 实现 FIDO2 硬件密钥和 Passkey 身份验证,涵盖注册、验证、迁移与恢复。

主要功能

  1. 01配置 WebAuthn 信赖方
  2. 02注册并验证凭据
  3. 03管理 YubiKey 生命周期
  4. 04规划 Passkey 迁移与恢复

适用场景

  1. 01为 Web 服务添加抗钓鱼 MFA
  2. 02支持免用户名 Passkey 登录
  3. 03登记主用及备用安全密钥

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/mukul975/anthropic-cybersecurity-skills --skill implementing-hardware-security-key-authentication

安装后在 Claude Code 中输入/implementing-hardware-security-key-authentication确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

LICENSE
references/
api-reference.md
scripts/
agent.py

详细介绍

实现硬件安全密钥认证

适用场景

  • 为高价值账户(管理员、开发者、特权用户)使用 FIDO2 硬件安全密钥部署抗钓鱼的多因素认证(MFA)
  • 构建同时支持漫游认证器(USB/NFC 安全密钥)和平台认证器(Windows Hello、Touch ID、Android 生物识别)的 WebAuthn 依赖方服务器
  • 将现有基于密码的认证系统迁移为支持通行密钥(可发现凭据)作为主认证因素或辅助认证因素
  • 为组织员工注册 YubiKey 设备,包括 PIN 设置、凭据注册和备用密钥配置
  • 实现符合 NIST SP 800-63B AAL3(认证器保证等级 3)要求的无密码认证流程

请勿在生产环境中不使用 HTTPS 的情况下使用(WebAuthn 要求安全来源),也不适用于用户无法物理接触 USB/NFC 端口的系统,或在没有丢失密钥恢复机制的情况下将其作为唯一的认证因素。

前置条件

  • Python 3.10+,并已安装 fido2(python-fido2 >= 2.0.0)、flask 和 cryptography 库
  • 启用 HTTPS 的 Web 服务器(WebAuthn API 要求安全上下文;开发环境下 localhost 可豁免)
  • 兼容 FIDO2 的硬件安全密钥(YubiKey 5 系列、SoloKeys、Titan Security Key)或平台认证器
  • 支持 WebAuthn API 的现代 Web 浏览器(Chrome 67+、Firefox 60+、Safari 14+、Edge 79+)
  • 了解公钥密码学、挑战-响应协议和 HTTP 会话管理

工作流

步骤 1:依赖方服务器配置

配置 WebAuthn 依赖方(RP)身份和服务器:

  • 定义 RP 身份:创建 PublicKeyCredentialRpEntity,包含依赖方名称(向用户显示的显示名称)和 RP ID(应用程序的有效域)。RP ID 必须是来源的可注册域后缀——例如,example.com 对 https://auth.example.com 有效,但 other.com 无效。
  • 初始化 Fido2Server:使用 RP 实体从 python-fido2 库实例化 Fido2Server 类。该服务器负责处理挑战生成、证明验证和断言校验。
  • 配置证明偏好:设置证明传递偏好,以控制服务器是否请求认证器身份证明:
    • none:不请求证明(最简单,推荐大多数部署使用)
    • indirect:可提供证明,但 CA 可能对其进行匿名化
    • direct:来自认证器制造商的完整证明链
    • enterprise:用于受管环境的设备标识证明
  • 会话管理:配置服务器端会话,以在注册/认证流程的开始阶段和完成阶段之间存储 WebAuthn 状态。使用安全的、httponly 的 Cookie,并设置 SameSite=Strict。
  • 凭据存储:设计数据库架构以存储凭据记录:credential_id(二进制)、public_key(COSE 密钥)、sign_count(用于克隆检测的 uint32)、user_id、created_at、last_used、display_name 和 transports(USB、NFC、BLE、internal)。
步骤 2:注册仪式(凭据创建)

实现 WebAuthn 注册流程以创建新凭据:

  • 开始注册:调用 server.register_begin(),传入用户实体(PublicKeyCredentialUserEntity,包含用户 ID、用户名和显示名称)、该用户已有凭据的列表(以防止重复注册),以及 user_verification 和 authenticator_attachment 的选项。
  • 认证器选择条件:
    • authenticator_attachment: cross-platform 限定为漫游认证器(USB/NFC 密钥)
    • authenticator_attachment: platform 限定为内置认证器(Touch ID、Windows Hello)
    • 省略此字段则允许两种类型
    • resident_key: required 强制创建存储在认证器上的可发现凭据(通行密钥)
    • user_verification: required 强制在认证器上进行 PIN 或生物识别验证
  • 客户端仪式:浏览器使用来自服务端的选项调用 navigator.credentials.create()。认证器生成新的密钥对,将私钥存储在其安全元件中,并返回公钥、凭据 ID、认证对象和客户端数据 JSON。
  • 完成注册:调用 server.register_complete(),传入已保存的状态和客户端响应。服务端验证认证签名,提取凭据公钥和 ID,并返回包含待存储凭据数据的 AuthenticatorData。
  • 存储凭据:将 credential_data(包含 credential_id、作为 COSE 密钥的 public_key,以及 sign_count)持久化到与该用户账户关联的数据库。
步骤 3:认证仪式(断言)

实现 WebAuthn 认证流程以验证凭据:

  • 开始认证:调用 server.authenticate_begin(),传入该用户已注册凭据的列表(对于由认证器识别用户的可发现凭据流程,可省略此参数)。根据所需保证级别设置 user_verification。
  • 客户端断言:浏览器使用服务端选项调用 navigator.credentials.get()。认证器定位匹配的凭据,如有需要则执行用户验证,递增签名计数器,并使用私钥对挑战进行签名。
  • 完成认证:调用 server.authenticate_complete(),传入已保存的状态、已注册凭据和客户端响应。服务端根据存储的公钥验证断言签名,并验证签名计数器已递增(克隆检测)。
  • 更新签名计数:认证成功后,更新该凭据存储的 sign_count。如果新的签名计数不大于存储的值,则该密钥可能已被克隆——将此标记为安全事件。
  • 可发现凭据流程:对于无密码认证,用户无需先输入用户名。认证器会展示该 RP ID 的所有可发现凭据,所选凭据的 userHandle 可识别用户。
步骤 4:YubiKey 注册与管理

实现组织级 YubiKey 配置工作流:

  • PIN 初始化:首次使用前,YubiKey 需要设置 FIDO2 PIN(最少 4 个字符,锁定前可重试 8 次)。通过 Yubico Authenticator 应用引导用户完成 PIN 设置,或通过 CTAP2 clientPin 命令以编程方式完成。
  • 主密钥注册:将用户的主 YubiKey 注册到其账户。使用便于识别的标签(例如 "USB-A YubiKey - Office")和认证器的 AAGUID 存储凭据,以便识别设备。
  • 备用密钥注册:要求用户至少注册两把安全密钥。备用密钥应单独存放(家中、保险箱)。两把密钥必须注册到同一账户,以便任意一把均可完成认证。
  • 密钥证明验证:对于企业部署,验证证明证书链以确认该密钥是来自 Yubico 的正品 YubiKey。将 AAGUID 与 Yubico 公布的值进行比对,以识别确切型号。
  • 密钥生命周期管理:实现管理功能,用于列出用户已注册的密钥、吊销已泄露的密钥、强制重新注册,以及审计密钥使用模式(最后认证时间、认证总次数)。
步骤 5:Passkey 迁移策略

规划并执行从密码到 passkey 的迁移:

  • 分阶段推出:先从自愿注册 passkey 开始,同时保留现有密码认证。跟踪采用指标(拥有 passkey 的用户百分比、使用 passkey 与密码登录的百分比)。
  • 凭据升级流程:当用户使用密码认证时,提示其注册 passkey。在密码登录成功后立即显示 WebAuthn 注册对话框,以尽量减少阻力。
  • 跨设备 passkey:为没有硬件安全密钥的用户支持同步 passkey(存储在平台凭据管理器中的 passkey,如 iCloud Keychain、Google Password Manager 或 1Password)。这些 passkey 无需专用硬件即可提供防钓鱼能力。
  • 账户恢复:为丢失所有安全密钥的用户设计恢复流程:
    • 在注册时生成的恢复代码(打印出来,存储在密码管理器中)
    • 身份验证后由管理员监督重新注册
    • 临时限时密码登录,并强制重新注册密钥
    • 绝不允许仅通过电子邮件或短信进行恢复,因为这会破坏防钓鱼能力
  • 密码弃用时间表:在 passkey 采用率超过目标阈值后,先对高权限账户强制实施仅 passkey 认证,然后扩展到所有账户。在过渡窗口期内保留密码作为后备方案。
  • 监控与指标:跟踪注册成功率、认证失败率(密钥错误、超时、取消)、平均认证时间,以及 passkey 与密码登录的比率。

关键概念

术语定义
FIDO2W3C WebAuthn API 与 FIDO Alliance CTAP2 协议组合的统称,利用公钥密码学实现无密码且抗钓鱼的身份验证
WebAuthnW3C Web Authentication API,允许 Web 应用通过 navigator.credentials.create()(注册)和 navigator.credentials.get()(身份验证)创建并使用公钥凭据
CTAP2Client to Authenticator Protocol 版本 2;浏览器(客户端)通过 USB、NFC 或 BLE 与外部验证器通信所使用的协议
依赖方(RP)请求身份验证的 Web 应用或服务;通过其 RP ID(域名)和 RP 名称(显示字符串)标识
可发现凭据(Passkey)存储在验证器上的凭据,无需 RP 提供凭据 ID 即可枚举,从而支持无用户名身份验证流程
认证声明(Attestation)验证器就其身份和属性提供的密码学证明;RP 使用它来验证验证器型号和制造商
AAGUIDAuthenticator Attestation Globally Unique Identifier;标识验证器型号的 128 位值(例如,所有 YubiKey 5 NFC 设备共享同一 AAGUID)
签名计数器(Sign Count)由验证器维护并包含在每次断言中的单调递增计数器;RP 使用它来检测被克隆的验证器
用户验证(UV)在验证器本身上进行的本地身份验证(PIN、指纹、人脸识别),用于证明持有验证器的人就是合法所有者

工具与系统

  • python-fido2:Yubico 官方 Python 库(v2.0+),提供用于依赖方实现的 Fido2Server,以及用于通过 USB 与验证器直接通信的 CtapHidDevice/Fido2Client
  • YubiKey 5 系列:Yubico 硬件安全密钥,支持 FIDO2/CTAP2、U2F、PIV、OpenPGP 和 OTP;提供 USB-A、USB-C、NFC 和 Nano 外形规格
  • py_webauthn:Duo Labs 的 Python WebAuthn 库,提供 generate_registration_options()、verify_registration_response()、generate_authentication_options() 和 verify_authentication_response() 函数
  • Yubico Authenticator:用于管理 YubiKey FIDO2 凭据、设置 PIN 和查看已注册账户的桌面和移动应用
  • WebAuthn.io / demo.yubico.com:用于针对真实验证器验证 WebAuthn 注册和身份验证流程的在线测试工具

常见场景

场景:为开发团队部署 FIDO2 MFA

背景:一家软件公司希望为其 50 人的开发团队用硬件安全密钥替换基于 TOTP 的 MFA。开发人员拥有生产基础设施的 root 访问权限,是网络钓鱼攻击的高价值目标。该公司已统一采用 YubiKey 5 NFC。

方法:

  1. 配置 YubiKey 5 NFC 密钥(每位开发人员 2 个:主密钥 + 备用密钥),并使用防篡改包装分发,附上初始 PIN 设置说明
  2. 部署与公司 SSO(OAuth 2.0 / OpenID Connect)提供商集成的 WebAuthn 依赖方服务器,配置 authenticator_attachment: cross-platform 和 user_verification: required
  3. 运行注册会话,让每位开发人员将两个密钥注册到其账户,并通过 attestation 验证确认真实的 YubiKey 5 NFC AAGUID
  4. 配置 SSO 提供商,要求所有开发人员账户将 FIDO2 作为第二因素,并提供 30 天宽限期,在此期间 TOTP 仍可用
  5. 实现密钥管理的自助门户:查看已注册密钥、注册替换密钥,以及报告丢失/被盗密钥(触发立即吊销凭证并重新注册)
  6. 宽限期结束后,为开发人员账户禁用 TOTP。监控认证日志中的任何回退尝试,并为剩余的未迁移人员提供 1:1 支持
  7. 实现开发团队 100% 采用 FIDO2,将生产基础设施访问的网络钓鱼风险降至接近零

陷阱:

  • 未要求注册备用密钥,导致单个密钥丢失时账户被锁定
  • 设置 user_verification: discouraged,允许任何实际持有密钥的人无需 PIN 即可认证
  • 忘记验证签名计数器,错过克隆密钥攻击
  • 不支持 NFC,影响主要使用平板电脑或手机工作的开发人员
  • 允许 TOTP 作为永久回退方式,削弱 FIDO2 部署的抗网络钓鱼能力
场景:为客户面向的应用程序实现无密码登录

背景:一个电子商务平台希望为其 200 万用户提供基于 passkey 的无密码登录,作为密码的替代方案,以减少凭据填充和网络钓鱼导致的账户接管。

方法:

  1. 使用 resident_key: required 实现 WebAuthn,创建可发现的凭证,实现无需用户名的登录
  2. 通过省略 authenticator_attachment,同时支持平台认证器(Touch ID、Windows Hello、Android 生物识别)和漫游认证器(安全密钥)
  3. 在登录页面添加"使用 passkey 登录"按钮,触发带有空 allowCredentials 列表的 navigator.credentials.get(),提示认证器提供可用的 passkey
  4. 成功创建 passkey 后,提示用户在第二台设备上创建 passkey 以实现冗余
  5. 在推广期间保留密码登录作为回退方式,并在每次密码登录后持续提示用户设置 passkey
  6. 跟踪指标:passkey 注册率(第一季度目标 30%)、passkey 与密码登录比例、认证失败率以及账户接管事件
  7. 6 个月后,为切换到仅使用 passkey 认证的用户提供激励(延长会话时长、减少 CAPTCHA)

陷阱:

  • 未处理用户的平台认证器(例如笔记本电脑 Touch ID)不可用、需要通过二维码进行跨设备认证的情况
  • 假设所有用户都有支持生物识别的设备;有些用户需要回退到基于 PIN 的验证
  • 未为丢失所有已注册 passkey 访问权限的用户实现适当的账户恢复
  • 忽视浏览器兼容性差距,尤其是 iOS 上较旧版本的 Safari

输出格式

## FIDO2 Deployment Report

**Application**: auth.example.com
**RP ID**: example.com
**Date**: 2026-03-19

### Enrollment Summary
- **Total Users**: 50
- **Users with Primary Key**: 50 (100%)
- **Users with Backup Key**: 47 (94%)
- **Authenticator Models**: YubiKey 5 NFC (48), YubiKey 5C NFC (2)

### Authentication Metrics (Last 30 Days)
- **Total Authentications**: 12,847
- **FIDO2 Authentications**: 12,203 (95.0%)
- **TOTP Fallback**: 644 (5.0%) -- grace period active
- **Mean Authentication Time**: 2.3 seconds
- **Authentication Failures**: 127 (0.99%)
  - User cancelled: 89
  - Timeout: 23
  - Invalid signature: 12
  - Sign count regression (possible clone): 3

### Security Events
- **Lost Key Reports**: 2
  - User A: primary key lost 2026-03-12, revoked, backup promoted, new backup enrolled
  - User B: backup key damaged 2026-03-15, revoked, replacement enrolled

### Credential Details
| User | Key Label | AAGUID | Registered | Last Used | Sign Count |
|------|-----------|--------|------------|-----------|------------|
| alice | YubiKey Primary | 2fc0579f... | 2026-02-15 | 2026-03-19 | 847 |
| alice | YubiKey Backup | 2fc0579f... | 2026-02-15 | 2026-03-01 | 12 |
| bob | YubiKey Primary | 2fc0579f... | 2026-02-16 | 2026-03-19 | 631 |

评论

支持 Markdown