Git 提交签名完整指南:GPG 与 SSH 签名详解

139 阅读5分钟

Git 提交签名完整指南:GPG 与 SSH 签名详解

🚀 AI 使用技巧 (Pro-Tip):

这篇文章已为 AI 进行了特别优化。你可以直接复制全文或你需要的任何部分,将其作为高质量的提示词(Prompt)粘贴到你的 AI 编程助手(如 Cursor、Claude、Copilot Chat 等)中,以快速获得精准的代码、解释或解决方案。

在现代软件开发中,确保代码提交的真实性和完整性变得越来越重要。Git 提供了强大的数字签名功能,让开发者可以对自己的提交进行加密签名,确保代码来源的可信度。本文将详细介绍如何配置和使用 GPG 签名,以及新兴的 SSH 签名方式。

为什么需要提交签名?

提交签名能够:

  • 验证身份:证明提交确实来自声称的作者
  • 防止篡改:确保提交内容在传输过程中未被修改
  • 增强信任:在开源项目中建立代码贡献的可信度
  • 合规要求:满足某些企业或项目的安全规范

在 GitHub 上,已签名的提交会显示绿色的 "Verified" 标记,未签名或签名无效的提交则不会有此标记。

GPG 签名详解

GPG 基础概念

GPG (GNU Privacy Guard) 是一个完整的加密和数字签名解决方案,基于 OpenPGP 标准。它使用非对称加密算法,包含一对密钥:

  • 私钥:用于签名和解密,必须严格保密
  • 公钥:用于验证签名和加密,可以公开分享

安装 GPG

Linux (Ubuntu/Debian):

sudo apt update
sudo apt install gnupg

macOS:

brew install gnupg

Windows: 下载并安装 Gpg4win

生成 GPG 密钥对

# 生成新的密钥对
gpg --gen-key

按提示依次输入:

  • 真实姓名
  • 邮箱地址(必须与 Git 配置的邮箱一致)
  • 密钥密码(强密码保护私钥)

管理 GPG 密钥

查看密钥
# 查看所有公钥
gpg --list-keys

# 查看私钥(包含密钥 ID)
gpg --list-secret-keys --keyid-format LONG
导出公钥
# 导出 ASCII 格式的公钥
gpg --armor --export 你的邮箱地址

# 导出到文件
gpg --armor --export 你的邮箱地址 > public_key.asc
备份和恢复
# 备份私钥(重要!)
gpg --armor --export-secret-keys 你的邮箱地址 > private_key.asc

# 导入密钥
gpg --import private_key.asc

配置 Git 使用 GPG 签名

基本配置
# 设置用户信息(邮箱必须与 GPG 密钥匹配)
git config --global user.name "Your Name"
git config --global user.email "your_email@example.com"

# 获取密钥 ID(从 gpg --list-secret-keys 输出中获取)
gpg --list-secret-keys --keyid-format LONG

# 配置签名密钥
git config --global user.signingkey 你的密钥ID

# 启用自动签名
git config --global commit.gpgsign true
git config --global tag.gpgsign true
环境配置
# 设置 GPG TTY(解决签名时的输入问题)
export GPG_TTY=$(tty)

# 永久添加到 shell 配置
echo 'export GPG_TTY=$(tty)' >> ~/.bashrc
# 或者对于 zsh 用户
echo 'export GPG_TTY=$(tty)' >> ~/.zshrc
macOS 特殊配置
# 安装 pinentry-mac(更好的密码输入体验)
brew install pinentry-mac

# 配置 gpg-agent
echo "pinentry-program /opt/homebrew/bin/pinentry-mac" >> ~/.gnupg/gpg-agent.conf

# 重启 gpg-agent
gpg-connect-agent reloadagent /bye

在 GitHub 上配置 GPG 公钥

  1. 导出你的 GPG 公钥:
gpg --armor --export 你的密钥ID
  1. 复制输出的全部内容(包括 -----BEGIN PGP PUBLIC KEY BLOCK----------END PGP PUBLIC KEY BLOCK-----

  2. 在 GitHub 上添加:

    • 进入 Settings → SSH and GPG keys
    • 点击 "New GPG key"
    • 粘贴公钥内容
    • 点击 "Add GPG key"

使用 GPG 签名

自动签名

配置完成后,每次提交都会自动签名:

git add .
git commit -m "Your commit message"
# 会自动使用 GPG 签名
手动控制签名
# 强制签名单次提交
git commit -S -m "Signed commit"

# 禁用单次提交的签名
git commit --no-gpg-sign -m "Unsigned commit"

# 签名标签
git tag -s v1.0 -m "Signed tag"

验证签名

本地验证
# 查看最近提交的签名信息
git log --show-signature -1

# 查看多个提交的签名状态
git log --pretty="format:%h %G? %an %s" -5

签名状态标识:

  • G = 有效签名 (Good signature)
  • B = 无效签名 (Bad signature)
  • U = 签名有效但密钥不受信任 (Untrusted)
  • X = 签名已过期 (eXpired)
  • Y = 签名由过期密钥创建 (expired keY)
  • R = 签名由吊销密钥创建 (Revoked)
  • E = 签名验证错误 (Error)
  • N = 无签名 (No signature)
GitHub 验证

在 GitHub 上,正确配置的签名提交会显示:

  • Verified - 签名有效且公钥已添加
  • Unverified - 签名无效或公钥未添加
  • 无标记 - 提交未签名

SSH 签名:现代化的替代方案

从 Git 2.34 版本开始,Git 支持使用 SSH 密钥进行签名,这为已经熟悉 SSH 的开发者提供了更简单的选择。

SSH 签名的优势

  • 简化配置:复用现有的 SSH 密钥
  • 统一管理:一套密钥解决认证和签名
  • 减少复杂性:避免 GPG 的环境配置问题

配置 SSH 签名

生成 SSH 密钥(如果还没有)
# 生成 ed25519 密钥(推荐)
ssh-keygen -t ed25519 -C "your_email@example.com"

# 或生成 RSA 密钥
ssh-keygen -t rsa -b 4096 -C "your_email@example.com"
配置 Git 使用 SSH 签名
# 设置签名格式为 SSH
git config --global gpg.format ssh

# 设置 SSH 签名密钥(使用公钥文件路径)
git config --global user.signingkey ~/.ssh/id_ed25519.pub

# 启用自动签名
git config --global commit.gpgsign true
在 GitHub 上添加 SSH 签名密钥
  1. 复制你的 SSH 公钥:
cat ~/.ssh/id_ed25519.pub
  1. 在 GitHub 上添加:
    • 进入 Settings → SSH and GPG keys
    • 点击 "New SSH key"
    • Key type 选择 "Signing Key"(注意不是 Authentication Key)
    • 粘贴公钥内容

SSH vs GPG 签名对比

特性SSH 签名GPG 签名
配置复杂度简单复杂
密钥管理复用现有 SSH 密钥需要专门的 GPG 密钥
生态支持较新,支持有限成熟,广泛支持
密钥格式SSH 公钥文件路径GPG 密钥 ID
适用场景个人项目,简化配置企业项目,严格安全要求

常见问题与解决方案

GPG 签名失败

问题:gpg: signing failed: Inappropriate ioctl for device
# 解决方案:设置 GPG TTY
export GPG_TTY=$(tty)
问题:gpg: signing failed: No secret key
# 检查密钥是否存在
gpg --list-secret-keys

# 检查 Git 配置的密钥 ID 是否正确
git config user.signingkey
问题:密码输入界面无法显示(macOS)
# 安装并配置 pinentry-mac
brew install pinentry-mac
echo "pinentry-program /opt/homebrew/bin/pinentry-mac" >> ~/.gnupg/gpg-agent.conf
gpg-connect-agent reloadagent /bye

签名验证问题

GitHub 上显示 "Unverified"
  1. 确认邮箱匹配:
git config user.email
gpg --list-keys
  1. 确认公钥已添加到 GitHub
  2. 确认密钥未过期
签名状态显示 "U" (Untrusted)
# 信任自己的密钥
gpg --edit-key 你的密钥ID
# 在交互界面中输入 trust,选择信任级别

性能优化

缓存 GPG 密码

编辑 ~/.gnupg/gpg-agent.conf

default-cache-ttl 3600
max-cache-ttl 86400
禁用特定仓库的签名
# 在特定项目中禁用签名
git config commit.gpgsign false

最佳实践

密钥管理

  1. 定期备份私钥:将私钥导出并安全存储
  2. 设置密钥过期时间:建议 2-4 年,到期前续期
  3. 使用强密码:保护私钥的密码应该足够复杂
  4. 撤销泄露密钥:如果私钥泄露,立即撤销并生成新密钥

团队协作

  1. 统一签名策略:团队应该统一使用 GPG 或 SSH 签名
  2. 密钥服务器:考虑使用企业密钥服务器管理团队密钥
  3. CI/CD 集成:配置自动化流程验证提交签名

安全考虑

  1. 密钥轮换:定期更新签名密钥
  2. 多设备同步:安全地在多个设备间同步密钥
  3. 审计日志:记录密钥使用和签名活动

完整配置示例

GPG 签名完整配置

# 1. 安装 GPG
brew install gnupg  # macOS

# 2. 生成密钥
gpg --gen-key

# 3. 获取密钥 ID
KEY_ID=$(gpg --list-secret-keys --keyid-format LONG | grep '^sec' | awk '{print $2}' | cut -d'/' -f2)

# 4. 配置 Git
git config --global user.name "Your Name"
git config --global user.email "your_email@example.com"
git config --global user.signingkey $KEY_ID
git config --global commit.gpgsign true

# 5. 设置环境
echo 'export GPG_TTY=$(tty)' >> ~/.zshrc

# 6. 导出公钥
gpg --armor --export $KEY_ID

SSH 签名完整配置

# 1. 生成 SSH 密钥(如果没有)
ssh-keygen -t ed25519 -C "your_email@example.com"

# 2. 配置 Git
git config --global gpg.format ssh
git config --global user.signingkey ~/.ssh/id_ed25519.pub
git config --global commit.gpgsign true

# 3. 显示公钥用于添加到 GitHub
cat ~/.ssh/id_ed25519.pub

结论

Git 提交签名是现代软件开发中的重要安全实践。GPG 签名提供了成熟、全面的解决方案,适合对安全有严格要求的项目;而 SSH 签名则为个人开发者和小团队提供了更简化的选择。

选择哪种签名方式主要取决于:

  • 项目需求:企业项目通常偏好 GPG,个人项目可以选择 SSH
  • 团队规模:大团队建议统一使用 GPG,小团队可以考虑 SSH
  • 技术背景:熟悉 SSH 的团队可能更容易接受 SSH 签名

无论选择哪种方式,重要的是建立一致的签名策略,确保代码的完整性和可信度。通过本文的详细指南,你应该能够成功配置并使用 Git 提交签名,为你的项目添加一层重要的安全保障。