前言
之前 Cloudflare 推出的 Yubikey 促销 掀起了一波小小的硬件密钥热潮, 很多人都通过国际转运低价购入了 Yubikey. 不过转眼过去了两年, 之后再没有过类似的优惠, 国内现货的价格也一直居高不下 (目前为 ~500RMB).
同时由于 Yubikey 固件完全无法升级, 从非官方渠道购买旧的 Yubikey 并不是一个好主意, 旧的密钥无法享受最新的安全和功能更新 - 事实上两年前的那批 Yubikey 已经有被发现的安全问题, 但用户除了掏钱重买以外, 没有其他修复的方法.
我一直以来使用的是 Windows Hello 的人脸/PIN 作为 WebAuthn 的认证方式, 并将 SSH 私钥存储在 TPM 中, 这些认证方式都是由 TPM 提供硬件安全支持, 理论上实现了和硬件 FIDO2 密钥类似的安全性.
不过我在上面这篇文章中提到的优点 - 无需额外携带硬件密钥现在成了缺点: TPM 和笔记本电脑绑定, 而我最近产生了移动办公需求, 不想带笔记本想要只带着密钥走.
所以就有了本文: 找下市面上 Yubikey 的替代品, 给我自己搞个易于购买且低价的独立硬件密钥.
硬件选择
硬件密钥的功能其实大同小异(都支持 FIDO2 协议), 这里主要考察其安全性(即存储的密钥是否可被提取). 除了最出名(也最贵)的 Yubikey 外, 我一开始搜到了 Google 开源的 OpenSK 和清华开源的 CanoKeys.
OpenSK
OpenSK 使用的是 nRF52840 方案, 淘宝上可以搜索到 nRF52840-MDK USB Dongle
相关硬件, 但谷歌文档中不推荐将 OpenSK 作为日用设备, 我没有找到有关其安全性的更多信息 (例如是否可以防止在物理接触时被提取密钥).
CanoKeys
CanoKeys 虽然有 nRF 和 STM32 的方案, 但官方已经表明任何接触到设备的人可以获取明文密钥, 不适合日用. 官方在淘宝有售卖使用 HED CIU98320B
的安全版本 CanoKey Pigeon
和 CanoKey Canary
.
Pico Keys
以上两个选择的成本都至少在 100 元以上, 我随后又在 GitHub 上搜索到的 Pico Keys 项目 成为了本文的主角. 目前这个项目支持 ESP32S3
RP2040
和 RP2350
这几款芯片的一些开发板. (这两款 RP 打头的芯片其实分别是树莓派推出的 Raspberry Pi Pico
和 Raspberry Pi Pico 2
使用的芯片.)
除了树莓派的芯片开发板选择多, 流行度高国内易于买到, 且价格很低 (~30RMB) 外, 我在搜索时看到了 RP2350 Hacking Challenge 这篇文章: Raspberry Pi 官方为 RP2350
举行了一场破解比赛, 用 $20000 奖金奖励能绕过芯片 Secure Boot 和其他保护机制从芯片内的 OTP(One-Time-Programmable) 区域读取数据的人, 最终四份成功的破解都用了很不 trivial 的手段, 并都得到了奖金.
我很认同 Raspberry Pi 这篇博客的结尾:
All vendors have security vulnerabilities in their chips. We are unusual because we talk about them, and aim to fix them, rather than brushing them under the carpet. Security through transparency is here to stay.
而恰好, 本次的 Pico Keys 项目就用到了 RP2350
这款芯片的 Secure Boot 和 OTP 功能用于保护保存的密钥在物理接触时不被提取或复制, 所以我更相信它的安全性.
硬件购置和刷 Firmware
RP2350
只是芯片型号, 有很多搭载该芯片的开发板, 我经过挑选后选择了形态比较小巧易于携带的 Waveshare(微雪) RP2350-One
. 这款芯片可以非常轻松的在淘宝上以 30 元左右的价格包邮买到. Pico Keys 还支持其他各式各样的开发板, 可以自行选择最容易购买到或者最便宜的.
购买到的 Waveshare RP2350-One, 实际大小近似一个较小的 U 盘, 裸露的电路板后续可以用透明热缩套或者保鲜膜(?)保护下
RP2350
刷入固件非常简单, 只需要按住 Boot 键时插入电脑, 它就会被识别成一个 U 盘, 直接把需要刷入的 uf2 格式固件复制到这个 U 盘里, 它会自动刷入并重启, 全程丝滑无需任何驱动或专有工具~
Waveshare RP2350-One
暂时没加入官方支持的支持固件, 应该近几个月内会加入. 不过根据我的测试 Raspberry Pico 2
的固件可以在这款 RP2350-One
上正常工作, 除了 LED 不会亮, 不影响功能. 下载对应 uf2
刷入即可.
刷入固件完成后可以在作者提供的在线配置工具 Pico Commissioner 上启动 Secure Boot
和 Secure Lock
功能. 这样做的代价是这个硬件以后就只能运行 Pico Keys 的官方固件, 好处是提供了上述的安全性, 在正式投入使用前还是建议开启的. (如果你又想 DIY 又想安全的话可以尝试自签.)
我还顺便在上面将这个 Key 的 Vendor 伪装成了 Yubikey 4/5
, 同时将 Product Name 设置为 yubico yubikey
, 这样就可以使用 Yubico 官方推出的 ykman
管理工具.
还有个小题外话: 作者提供了一个清除所有数据使用的固件, 当需要清空所有 Key 恢复出厂设置时可以使用.
功能测试
来测试一下这把 DIY 密钥的功能.
FIDO2
可以通过 WebAuthn 进行认证, 作为无密码登录的 Passkey 或者作为 2FA 的 second factor 都可.
搜索 FIDO2 Test 有很多测试网站可以在线测试, 第一次注册时需要设置一个 PIN 码
通过 ykman
工具可以查询密钥的状态:
1 | PS C:\> ykman list |
默认情况下 PIN 只能尝试 8 次: 每尝试 3 次会临时 BLOCK 密钥, 需要重新插拔后才能继续尝试, 总计试满 8 次后密钥永久被 BLOCK, 此时只能重置, 重置会丢失所有存储的密钥. (硬件本身还是可以继续正常使用的)
FIDO2 也可以用于 SSH 私钥:
1 | lyc8503@Laptop MINGW64 ~ |
通过 ssh-keygen -t ed25519-sk
生成的密钥对必须要硬件密钥和 id_ed25519_sk
同时存在才能使用, 也能提高了安全性. 单独有硬件密钥或者单独有私钥文件都是无法 SSH 的.
如果你想实现只带着密钥就能作为 ssh 私钥使用的话, 可以使用 ssh-keygen -t ed25519-sk -O resident
生成一个 resident 的密钥. 此时你可以在任何一台电脑上运行 ssh-keygen -K
取回公私钥对. (在 Windows 执行这个命令可能需要管理员权限)
(题外话 p.s. 不过 hardware-backed 的 SSH 方法也不止这一种, 所以你可能也会看到别的配置方法, 但都相对麻烦一些)
OATH
用最常见的 TOTP 测试, 你可以将 TOTP Secret 存入硬件密钥, 并用其生成 6 位数的验证码:
1 | PS C:\> ykman oath info |
存入的 TOTP Secret 就不再能读取, 但可以安全的生成 code, 需要更加安全的话可以为 OATH 单独设置密码, 每次生成 code 需要再输入次密码. (与上面的 FIDO PIN 相互独立.)
1 | PS C:\> ykman oath access change |
PIV & OpenGPG
官方的 Yubikey 是在一把密钥里支持了所有功能, 但 Pico Keys 的作者将其分为了多个部分, 如果需要的话要单独刷入 pico-opengpg, 我暂时用不到, 所以在本文就不再深究了…
小结
于是, 我们就拥有了一把开源且安全, 固件可更新, 而且很便宜的硬件密钥🎉
本文采用 CC BY-NC-SA 4.0 许可协议发布.
作者: lyc8503, 文章链接: https://blog.lyc8503.net/post/diy-fido-key/
如果本文给你带来了帮助或让你觉得有趣, 可以考虑赞助我¬_¬