GPG + SSH 统一身份认证指南
本手册旨在指导如何利用 GPG 的 认证子密钥 (Authentication Subkey) 替代传统的 SSH Key,实现代码签名与服务器登录的身份统一。
1. 核心架构理解
GPG 密钥体系由主密钥和子密钥组成:
- 主密钥 [SC]:用于管理(签发、撤销)子密钥,应安全离线保存
- 子密钥 [S]:用于 Git Commit 签名
- 子密钥 [E]:用于加密文件
- 子密钥 [A]:用于 SSH 登录认证(核心功能)
2. 准备工作
2.1 安装必要工具
# Debian/Ubuntu
sudo apt update && sudo apt install gnupg2 pinentry-curses
# CentOS/RHEL
sudo yum install gnupg2 pinentry
# macOS
brew install gnupg pinentry-mac
2.2 检查 GPG 版本
gpg --version
3. 密钥管理
3.1 查看现有密钥
# 列出私钥并显示 Keygrip
gpg -K --with-keygrip
# 列出公钥
gpg -k
3.2 创建 GPG 密钥对
如果还没有 GPG 密钥,可以创建一个:
gpg --full-generate-key
按照提示选择密钥类型、密钥长度、过期时间等。
3.3 添加认证子密钥
-
编辑现有密钥:
bash gpg --edit-key <你的密钥ID> -
在 GPG 交互界面中:
gpg> addkey -
选择 "(4) RSA (sign only)" 或 "(8) RSA (set your own capabilities)",然后启用认证功能
-
设置密钥长度(建议 4096)和过期时间
-
保存并退出:
gpg> save
4. 配置 GPG SSH
4.1 配置 gpg-agent
编辑 ~/.gnupg/gpg-agent.conf 文件:
enable-ssh-support
pinentry-program /usr/bin/pinentry-curses # 根据系统调整路径
allow-loopback-pinentry
default-cache-ttl 28800 # 8小时
max-cache-ttl 86400 # 24小时
4.2 配置 sshcontrol
编辑 ~/.gnupg/sshcontrol 文件,添加认证子密钥的 Keygrip:
# 格式:Keygrip 缓存时间 备注名
F1E2D3C4B5A6978877665544332211AA00BBCCDD 0 sarto-github-auth
获取 Keygrip 的方法:
gpg -K --with-keygrip
4.3 配置环境变量
在 ~/.bashrc、~/.zshrc 或其他 shell 配置文件中添加:
# GPG SSH 配置
export SSH_AUTH_SOCK=$(gpgconf --list-dirs agent-ssh-socket)
export GPG_TTY=$(tty)
gpg-connect-agent updatestartuptty /bye > /dev/null
重新加载配置:
source ~/.bashrc # 或 source ~/.zshrc
5. 导出 SSH 公钥
5.1 生成 SSH 公钥
# 使用邮箱导出
gpg --export-ssh-key sarto@example.com
# 或使用密钥ID导出
gpg --export-ssh-key <你的密钥ID>
5.2 添加到 GitHub/GitLab
- 复制生成的 SSH 公钥
- 登录 GitHub/GitLab
- 进入 "Settings" → "SSH and GPG keys"
- 点击 "New SSH key"
- 粘贴公钥并保存
6. 测试配置
6.1 验证 Agent 状态
ssh-add -L
应该能看到你的 GPG 认证子密钥。
6.2 验证 GitHub 连通性
ssh -T git@github.com
如果成功,会看到类似 "Hi username! You've successfully authenticated..." 的消息。
6.3 测试 Git 操作
git clone git@github.com:username/repository.git
7. 故障排查
7.1 Agent 未启动
# 启动 gpg-agent
gpg-connect-agent /bye
# 检查状态
gpg-connect-agent "getinfo version" /bye
7.2 密钥未被识别
# 重新添加密钥到 sshcontrol
# 确保 Keygrip 正确
# 重启 gpg-agent
gpgconf --kill gpg-agent
gpg-connect-agent /bye
7.3 缓存问题
# 清除缓存
gpg-connect-agent "CLEARPGPINFO" /bye
# 重新加载
gpg-connect-agent updatestartuptty /bye
8. 最佳实践
8.1 密钥安全
- 主密钥:离线保存,最好存储在硬件密钥设备中
- 子密钥:定期轮换,设置合理的过期时间
- 备份:定期备份 GPG 密钥库
8.2 日常使用
- 避免频繁输入密码:合理设置缓存时间
- 多设备同步:在多台设备上使用相同的 GPG 密钥
- 代码签名:同时使用 [S] 子密钥进行 Git 提交签名
8.3 服务器配置
在服务器上,可以使用 authorized_keys 文件添加 GPG 生成的 SSH 公钥,与传统 SSH 密钥一样使用。
9. 总结
通过 GPG + SSH 统一身份认证方案,你可以:
- 简化密钥管理:用一套 GPG 密钥体系同时处理代码签名和 SSH 登录
- 提高安全性:利用 GPG 的子密钥机制,主密钥可以安全离线保存
- 增强可追溯性:所有操作都可以通过 GPG 密钥进行身份验证
这种方案特别适合需要同时进行代码开发和服务器管理的开发者,是一种现代化的身份认证解决方案。