自从上次使用 Cloudflare Zero 的优惠买下两个 YubiKey 之后,这俩玩意被我搁置了一个学期。原因之一是学习成本不低,关于它们的文档、教程都充斥着不少不太了解的名词、概念,令人望而却步。于是经过查阅各种资料,在这篇博客中我将(用白话文)介绍我从零开始的 YubiKey 入门之旅。

Yubico 与 YubiKey

Yubico 是一家美国的公司,是 YubiKey 的制造商。(这家公司似乎对东亚某国有一定政治倾向。这一点我不了解也不评论。)

YubiKey 是这家公司生产的硬件安全密钥。这个东西有点像以前很多银行要用的「U 盾」,是硬件层面保障安全性的一个东西。

我购买的是 YubiKey 5 系列,包含一个 YubiKey 5 NFC 和一个 Yubikey 5C NFC(Type-C 接口)。本文只介绍这两个设备支持的功能。这个设备上有一个可以触摸的按钮和指示灯。

软件安装

官方有三个软件:

安装 YubiKey Manager 后,插入 YubiKey 它就可以识别到。可以看到支持的三个主要应用:OTP、FIDO2 和 PIV,这是三个相互独立的功能。在 Interfaces 里则可以控制各种功能的开关。

YubiKey Manager 的界面

设置前准备……

理论上,为了保证较高的安全性,接下来的操作都应该在一台全新安装的、断开网络连接的 USB 镜像(比如 Ubuntu Live)或者虚拟机中进行;所有生成的临时文件都应该放在重启后就消失的 tmpfs 里。如果确实有特殊的需求,可以配置这样的环境,不过对于个人而言应该没什么必要。

OTP

OTP 的全称是 One-Time Password,即一次性密码。这个功能是将 YubiKey 作为一个模拟键盘,在短按或长按硬件按钮后,可以在电脑上输入密码(并回车)。

刚拿到 YubiKey 还没有配置的情况下,插入电脑,触摸按键,会发现输入了一段长长的乱码。这就是默认配置的 Yubico OTP。(在 macOS Ventua 中,建议不要在中文输入法开启时按下……否则会卡死。)

短按和长按两个 slot 可以分别配置。每个 slot 有四种选项:

以上个人目前感觉最有用的就是 Static password,将它设置成自己常用的密码就可以免输入了。

个人认为安全领域的 challenge 这个词应该翻译成「质询」更加贴切,而不是「挑战」。

Slot

上面提到了 slot(插槽)的概念,OTP 这个功能中有两个 slot,下面的 PIV 则有 25 个 slot。可以将 slot 理解为存储单元,每个 slot 有一个地址,如这个文档中列出了 PIV 的 25 个 slot 以及各自的地址。

FIDO

FIDO 的全称是 Fast IDentity Online。Yubico 是标准化机构 FIDO Alliance 的一员,遵循后者制定的 FIDO 标准。

YubiKey 支持两种 FIDO 标准:FIDO U2F(Universal Second Factor)和 FIDO2。前者可以理解为第一代协议,后者是第二代。

设置 PIN

所谓 PIN 指的是 Personal Identification Number,这个概念在各种地方都有,比如 Windows 可能会让你设置登录 PIN(这样登录系统时无需输入密码,只需输入 PIN。许多人分不清这两个概念),早期本地化不好的 Android 手机里的锁屏密码也叫做 PIN。它和「password」这个概念的区别在于:一般 PIN 只包含四位或六位数字,更加简单,适用于需要更频繁输入的情况。

在使用 FIDO 之前,要先设置 FIDO PIN,默认是没有的。这个 PIN 需要至少四个字符。

WebAuthn(2FA)

FIDO 最常用的应用就是 WebAuthn。这个协议允许我们在浏览器中将硬件密钥作为 2FA 的手段。

所谓的 2FA 指的是 Two-Factor Authentication,即两步验证(双因素验证),也叫做 MFA(Multi-Factor Authentication)。因为纯粹「用户名 + 密码」的登录组合安全性太低,密码泄漏将等同于账号失窃。所以许多网络服务登录时在密码之外增加了一个验证因素,故名曰「双因素」。比如 QQ 的「设备锁」,在陌生设备上登录时,除了要求密码正确,还要输入收到的手机短信验证码,这就是一种 2FA。

一般来说,2FA 有这几种比较常用的形式:

VaultWarden 支持的各种 2FA 方式

上面提到的 WebAuthn 就是 FIDO 的一项功能。国外如 Google、Microsoft、Apple 等的应用基本都支持这个协议,可能由于 FIDO Alliance 在国内影响力有限,国内应用很少支持。可以在 https://webauthn.me 测试 WebAuthn 功能。

由于我使用的 BitWarden 本身支持设置 TOTP 作为各种 2FA 并且非常方便,我只有在自己 VaultWarden 实例的登录上使用了 YubiKey 作为 2FA。

SSH via FIDO

OpenSSH 从 8.2 版本开始,登录时也支持 FIDO 标准的 2FA。可以参阅:通过 FIDO2 加固 SSH。简单来说,只要:

ssh-keygen -t ed25519-sk

使用这样生成的密钥,在登录时会需要 YubiKey 二次验证。所以即使攻击者拿到了密钥,也无法登录。

但是相比之下,我更希望「不需要存储密钥」,通过 YubiKey 直接登录(也就是将密钥存储在 YubiKey 里)。这可以通过下面的 PIV 实现。

PIV

PIV 的全称是 Personal Identity Verification。这个功能允许我们在 YubiKey 里保存 GPG 密钥等。存储在其中的密钥文件不可导出,可以保障安全性。

YubiKey Manager 软件只支持管理四个 slot 里存放的证书。更多的功能可以使用命令行工具 yubico-piv-tool

PIN、PUK 与 Management Key

PIV 的 PIN 默认是 123456。PIN 要求 6~8 个字符,每个字符可以是任意 ASCII 字符。PIV PIN 只有三次尝试机会,如果三次都错误,PIN 将会被 block,这时候不能再输入。(注意,PIV PIN 和 FIDO PIN 无关)

PUK 即 PIN Unlock Key,用于在 PIN 锁定时解锁设备。默认是 12345678。PUK 实际上是一个 8 Byte 值,每个 Byte 允许 0x000xFF,所以不仅允许 ASCII 字符,也允许不可见字符。PUK 也只有三次尝试机会,如果三次都错误,PUK 也将被 block。此时 PIV 会彻底被锁定,只能重置 PIV 功能——也意味着其中的所有密钥永远消失。

Management Key 是一串长长的字符串,默认是 0x010203...,设置时可以生成一个新的值。在执行一些重要操作时需要输入。它没有尝试次数限制,不会被 block。

PIN、PUK 的尝试次数限制默认为 3,可以用高级工具配置这个值。如果 PIV 被锁定,对其他应用(OTP、FIDO2)没有影响。

这篇文档介绍了 PIN、PUK 与 Management Key。

PIN-only 模式

由于 Management Key 太长,PIV 提供 PIN-only 模式,即在所有操作中只需要 PIN 不需要 Management Key。具体来说,有两种模式:

PIN-derived 模式下,由于 Management Key 不会被 block,攻击者可以通过枚举 PIN 暴力破解,所以不建议使用此模式。

YubiKey Manager 软件中,在设置 Management Key 的时候,默认可以设置 PIN-protected 模式。

Certificates

进入 PIV 中 Certificates 的设置,可以看到可以存放四种证书:

每个 slot 都可以生成、导入、导出证书等。

对于 YubiKey 生成的证书,我们只能导出证书本身,至于对应的私钥文件是不能导出的。这确保了安全性。

SSH via PIV

理论上来说,将 SSH 的密钥存储在 YubiKey 里(是无法取出的),使用 ssh-agent 可以通过其连接 SSH。但是官方的教程非常陈旧,网上找的各种教程也都不适用于我的 M1 MacBook macOS。所以这项还在研究中,估计等这个系列的下一篇可以写。

参考