1469 字
7 分钟
GPG 与 YubiKey:硬件托管子密钥完整配置教程

一、为什么要使用 YubiKey 等硬件密钥#

尽管主密钥离线保管、子密钥日常启用的管理方案已经提供了很好的安全防护
但是仍然存在一个核心风险:日常设备被入侵导致子密钥私钥被窃取

但将子密钥私钥迁移至硬件设备(如 YubiKey) ,可进一步强化防护:

  • 私钥永久无法导出
  • 签名、解密运算均在硬件内完成
  • 即便主机被完全控制,攻击者也无法使用 GPG 进行任何加密以及签名
CAUTION

Yubico 官方不建议先在外部生成密钥再导入 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 信息

Terminal window
gpg --card-status

4.2 移动子密钥#

Terminal window
gpg --edit-key <KEY_ID> # 输入需要转移子密钥的密钥ID
gpg> key <KEY_NUM> # 选中要移入硬件的子密钥(带 * 表示已选中)
gpg> keytocard # 将子密钥写入 YubiKey

移动时根据子密钥用途,选择对应 OpenPGP 槽位:

  • Signature key(签名子密钥 → 存入签名槽)
  • Encryption key(加密子密钥 → 存入加密槽)
  • Authentication key(认证子密钥 → 存入认证槽)

根据提示输入 GPG 密钥的密码以及 Yubikey 的管理员密码
当出现是否保留本地私钥副本提示时,建议此时选择保留,不要删除本地密钥

保留本地仍有完整私钥,不会自动删除本地私钥,使用时将优先使用本地私钥
不保留本地仅保留 stub key,子密钥私钥仅保留在 YubiKey 硬件内,所有签名、解密、认证操作必须插入 YubiKey 并验证 PIN 才能执行

4.3 验证结果#

执行以下命令查看 YubiKey 与子密钥绑定状态:

Terminal window
gpg --card-status

正常状态下可验证到以下关键信息:

  • 硬件序列号:Card Serial Number
  • 已加载的子密钥:Signature / Encryption / Authentication key 启用状态
  • 密钥归属:对应密钥持有者身份信息
  • 卡片状态:正常启用

执行完成后,可确认子密钥已成功写入硬件,GPG 已正常识别 OpenPGP Card

五、在新设备使用 Yubikey#

  1. 在在新设备中导入公钥文件
Terminal window
gpg --import <公钥文件路径>
  1. 插入 YubiKey 生成 stub key
Terminal window
gpg --card-status
  1. 验证测试 Yubikey 是否可用
Terminal window
# 测试生成签名并加密的文件
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 才能完成

Terminal window
gpg --edit-key <KEY_ID>
gpg> key <KEY_NUM> # 选中需要清理本地副本的子密钥
gpg> delkey # 删除本地私钥
gpg> save

七、总结#

当子密钥移动到 Yubikey 后,私钥将固化在硬件内无法导出,本地仅保留 stub 占位引用
日常签名、解密、认证等操作均由硬件完成,设备即使被入侵也无法窃取原始私钥,可以进一步提升安全性

GPG 与 YubiKey:硬件托管子密钥完整配置教程
https://www.self4m.com/posts/security-gpg-yubikey-subkeys/
✍️作者
Self4m
📅发布于
2025-09-03
©️许可协议
CC BY-NC-SA 4.0

商业用途必须事先获得作者授权;
非商业用途可以使用,但必须注明出处;
若有改编需采用相同许可协议发布。