跳转至

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 添加认证子密钥

  1. 编辑现有密钥: bash gpg --edit-key <你的密钥ID>

  2. 在 GPG 交互界面中: gpg> addkey

  3. 选择 "(4) RSA (sign only)" 或 "(8) RSA (set your own capabilities)",然后启用认证功能

  4. 设置密钥长度(建议 4096)和过期时间

  5. 保存并退出: 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

  1. 复制生成的 SSH 公钥
  2. 登录 GitHub/GitLab
  3. 进入 "Settings" → "SSH and GPG keys"
  4. 点击 "New SSH key"
  5. 粘贴公钥并保存

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 统一身份认证方案,你可以:

  1. 简化密钥管理:用一套 GPG 密钥体系同时处理代码签名和 SSH 登录
  2. 提高安全性:利用 GPG 的子密钥机制,主密钥可以安全离线保存
  3. 增强可追溯性:所有操作都可以通过 GPG 密钥进行身份验证

这种方案特别适合需要同时进行代码开发和服务器管理的开发者,是一种现代化的身份认证解决方案。