使用 FIDO2 实现 LUKS 磁盘加密的技术解析
LUKS 磁盘加密与 FIDO2
FIDO2 安全密钥提供多种用户认证方式。在 ph0wn 研讨会上我们探讨了部分应用场景,本文深入介绍如何使用安全密钥保护 LUKS 磁盘加密,并解析底层机制与常见陷阱。
LUKS 磁盘加密基础
LUKS 是 Linux 生态中加密块设备(如固态硬盘)的通用方案。其工作原理是在加密设备前保留未加密的头部,包含解密所需的所有信息。头部包含用于解密二进制密钥槽区域的密钥派生信息,而密钥槽中的主密钥则用于加解密整个设备。
管理加密设备的常用工具是 cryptsetup。例如使用 luksFormat 子命令创建 LUKS 设备:
该命令会请求用于设备加解密的密码,随后完成磁盘格式化与加密。可通过 open 命令解锁设备:
FIDO2 hmac-secret 扩展加密
FIDO2 采用标准化通信协议 CTAP(客户端到认证器协议),定义安全密钥与操作系统/浏览器的信息交换。当前版本为 2.1,2.2 版已发布评审草案。
对于 LUKS 加密,使用名为"hmac-secret"的 CTAP 扩展。该扩展通过 authenticatorMakeCredential 和 authenticatorGetAssertion 命令获取 LUKS 密钥槽解密的对称密钥。可通过 Yubico python-fido2 库的 get_info.py 脚本验证认证器是否支持此扩展:
输出显示设备支持 CTAP 2.0 标准及 hmac-secret 扩展。
在 CTAP authenticatorMakeCredential 命令中,若存在 hmac-secret 参数,认证器会创建凭证 ID 并生成 32 字节随机数 CredRandom。systemd 提供的 systemd-cryptenroll 工具可便捷地注册认证器:
注册后查看 LUKS 头部可见关联密钥槽的令牌,其中包含 fido2-credential(凭证 ID)和 fido2-salt(盐值)。
密钥生成使用 CTAP authenticatorGetAssertion 命令。通过 Diffie-Hellman 密钥协商获得共享密钥,用于加密和验证主机选择的盐值。认证器生成 CredRandom 与盐值的 HMAC-SHA-256 输出:
该加密输出返回主机后用于解密关联密钥槽。解密时需要认证器和 PIN 码:
由于 CredRandom 仅能由安全密钥恢复,缺少认证器无法解密设备。
PIN 码管理问题
CTAP 在凭证创建时使用 clientPin 参数。若未设置 PIN 码即注册安全密钥,后续即使配置 PIN 码也不会要求输入,这可能导致设备与认证器同时被盗时数据泄露。
实验发现,某些认证器(如固件 v3.0.0 的 Solo key)在修改 LUKS 头部 fido2-clientPin-required 为 false 后,仍可不需 PIN 码解密设备。但 Yubikey 5.1.1 等设备则拒绝此类请求。
CTAP 协议更新
CTAP 2.1 及以上版本修复了该缺陷。认证器在 authenticatorMakeCredential 命令中生成两个独立密钥:CredRandomWithUV 和 CredRandomWithoutUV。根据用户验证状态选择相应密钥。
测试支持 CTAP 2.1 的 YubiKey 5 NFC 时发现,修改头部参数后解密尝试因密钥验证失败而拒绝访问,这与使用不同 CredRandom 值导致密钥生成差异的原理一致。
该更新已实现在最新 Solo key 固件中,但部分认证器可能无法升级,因此设置磁盘加密前需确认设备支持的 CTAP 版本。
结论
FIDO2 安全密钥为 LUKS 加密磁盘提供了便捷安全的解锁方案,但必须理解底层机制和潜在风险。为确保最佳保护,应使用支持最新 CTAP 版本的安全密钥,并正确执行凭证创建流程(包括用户验证)。更多精彩内容 请关注我的个人公众号 公众号(办公 AI 智能小助手)公众号二维码

评论