一、为什么要使用 YubiKey 等硬件密钥
尽管主密钥离线保管、子密钥日常启用的管理方案已经提供了很好的安全防护
但是仍然存在一个核心风险:日常设备被入侵导致子密钥私钥被窃取
但将子密钥私钥迁移至硬件设备(如 YubiKey) ,可进一步强化防护:
- 私钥永久无法导出
- 签名、解密运算均在硬件内完成
- 即便主机被完全控制,攻击者也无法使用 GPG 进行任何加密以及签名
CAUTIONYubico 官方不建议先在外部生成密钥再导入 YubiKey,因为导入过程中密钥本体仍会被读取,存在泄露风险,并非仅依靠密码防护
若直接在 YubiKey 内创建密钥,私钥将永久无法导出。一旦 YubiKey 丢失或损坏,不仅会丢失整条信任链,也将彻底无法访问加密文件
因此,在本地使用强密码生成 GPG 密钥并做好离线备份后再导入 YubiKey,是兼顾安全与可恢复性的折中方案
二、YubiKey 的 OpenPGP 工作模式
YubiKey 原生集成 OpenPGP Card 标准协议,可直接作为硬件密钥卡使用,完全兼容主流 OpenPGP、GnuPG 密钥体系与软件
其 OpenPGP 模块内置三个独立密钥槽位,分别对应 OpenPGP 标准的三类子密钥分工:
- S (Sign) 签名槽:存放签名子密钥,用于 Git 签名、文件签名、邮件验签等场景
- E (Encrypt) 加密槽:存放加密子密钥,负责文件、邮件等数据的加解密运算
- A (Authenticate) 认证槽:存放认证子密钥,多用于 SSH 密钥登录、系统身份认证
三个槽位相互隔离、用途固定,同一时间每个槽位仅能存放一把对应类型的子密钥。密钥写入硬件后,私钥主体永久驻留设备内部,常规读取、导出操作均无法获取原始私钥
同时 YubiKey OpenPGP 模式支持自定义 PIN 码、管理 PIN 与重置码,可对硬件操作进行二次权限管控,进一步提升使用安全
三、stub key
3.1 什么是 stub key
当子密钥被移动到 YubiKey 后:
- 本地不再留存子密钥私钥
- GPG 仅在本地保留一份 stub key(占位引用)
- 所有签名、解密等操作,均通过 USB 与硬件设备交互完成
stub key 的作用是:
- 标识当前子密钥状态正常
- 指引 GPG 从对应的 OpenPGP 硬件卡(YubiKey)读取私钥执行操作
3.2 stub key 的安全特性
- 不包含任何可用于恢复私钥的材料
- 可跨设备安全复制、分发
- 仅丢失 stub key 不会造成私钥泄露,重新导入公钥并连接 YubiKey 即可恢复引用
四、将子密钥移动到 YubiKey
4.1 将 Yubikey 连接到设备
通过以下命令确认 GPG 程序可以读取到 Yubikey 信息
gpg --card-status4.2 移动子密钥
gpg --edit-key <KEY_ID> # 输入需要转移子密钥的密钥IDgpg> key <KEY_NUM> # 选中要移入硬件的子密钥(带 * 表示已选中)gpg> keytocard # 将子密钥写入 YubiKey移动时根据子密钥用途,选择对应 OpenPGP 槽位:
- Signature key(签名子密钥 → 存入签名槽)
- Encryption key(加密子密钥 → 存入加密槽)
- Authentication key(认证子密钥 → 存入认证槽)
根据提示输入 GPG 密钥的密码以及 Yubikey 的管理员密码
当出现是否保留本地私钥副本提示时,建议此时选择保留,不要删除本地密钥
选保留本地仍有完整私钥,不会自动删除本地私钥,使用时将优先使用本地私钥
选不保留本地仅保留 stub key,子密钥私钥仅保留在 YubiKey 硬件内,所有签名、解密、认证操作必须插入 YubiKey 并验证 PIN 才能执行
4.3 验证结果
执行以下命令查看 YubiKey 与子密钥绑定状态:
gpg --card-status正常状态下可验证到以下关键信息:
- 硬件序列号:Card Serial Number
- 已加载的子密钥:Signature / Encryption / Authentication key 启用状态
- 密钥归属:对应密钥持有者身份信息
- 卡片状态:正常启用
执行完成后,可确认子密钥已成功写入硬件,GPG 已正常识别 OpenPGP Card
五、在新设备使用 Yubikey
- 在在新设备中导入公钥文件
gpg --import <公钥文件路径>- 插入 YubiKey 生成 stub key
gpg --card-status- 验证测试 Yubikey 是否可用
# 测试生成签名并加密的文件echo "yubikey test" | gpg --sign --encrypt --recipient <自己邮箱或者密钥指纹ID> > test.gpg
# 验证并解密加密的文件gpg --decrypt test.gpg若 gpg --decrypt test.gpg 能成功输出明文test,则表示子密钥已完整的导入到 Yubikey 中
如果无法完成签名加密或者验证解密,则需要重新完成转移操作
六、本地私钥清理(仅保留 stub key)
当确认 Yubikey 中的子密钥可以使用后,此时我们应该删除设备中留存的私钥
NOTE前提条件:主密钥已完成离线备份;已确认子密钥成功写入 YubiKey
删除后:本地不再持有任何可用私钥;所有操作必须插入 YubiKey 才能完成
gpg --edit-key <KEY_ID>gpg> key <KEY_NUM> # 选中需要清理本地副本的子密钥gpg> delkey # 删除本地私钥gpg> save七、总结
当子密钥移动到 Yubikey 后,私钥将固化在硬件内无法导出,本地仅保留 stub 占位引用
日常签名、解密、认证等操作均由硬件完成,设备即使被入侵也无法窃取原始私钥,可以进一步提升安全性
非商业用途可以使用,但必须注明出处;
若有改编需采用相同许可协议发布。