Newsletter
Join the Community
Subscribe to our newsletter for the latest news and updates
2025/08/26
在现代软件开发中,确保代码提交的真实性和完整性变得越来越重要。Git 提供了强大的数字签名功能,让开发者可以对自己的提交进行加密签名,确保代码来源的可信度。本文将详细介绍如何配置和使用 GPG 签名,以及新兴的 SSH 签名方式。
提交签名能够:
在 GitHub 上,已签名的提交会显示绿色的 "Verified" 标记,未签名或签名无效的提交则不会有此标记。
GPG (GNU Privacy Guard) 是一个完整的加密和数字签名解决方案,基于 OpenPGP 标准。它使用非对称加密算法,包含一对密钥:
Linux (Ubuntu/Debian):
sudo apt update
sudo apt install gnupg
macOS:
brew install gnupg
Windows:
下载并安装 Gpg4win
# 生成新的密钥对
gpg --gen-key
按提示依次输入:
# 查看所有公钥
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
# 设置用户信息(邮箱必须与 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
# 安装 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
gpg --armor --export 你的密钥ID
-----BEGIN PGP PUBLIC KEY BLOCK-----
和 -----END PGP PUBLIC KEY BLOCK-----
)配置完成后,每次提交都会自动签名:
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 上,正确配置的签名提交会显示:
从 Git 2.34 版本开始,Git 支持使用 SSH 密钥进行签名,这为已经熟悉 SSH 的开发者提供了更简单的选择。
# 生成 ed25519 密钥(推荐)
ssh-keygen -t ed25519 -C "your_email@example.com"
# 或生成 RSA 密钥
ssh-keygen -t rsa -b 4096 -C "your_email@example.com"
# 设置签名格式为 SSH
git config --global gpg.format ssh
# 设置 SSH 签名密钥(使用公钥文件路径)
git config --global user.signingkey ~/.ssh/id_ed25519.pub
# 启用自动签名
git config --global commit.gpgsign true
cat ~/.ssh/id_ed25519.pub
特性 | SSH 签名 | GPG 签名 |
---|---|---|
配置复杂度 | 简单 | 复杂 |
密钥管理 | 复用现有 SSH 密钥 | 需要专门的 GPG 密钥 |
生态支持 | 较新,支持有限 | 成熟,广泛支持 |
密钥格式 | SSH 公钥文件路径 | GPG 密钥 ID |
适用场景 | 个人项目,简化配置 | 企业项目,严格安全要求 |
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
# 安装并配置 pinentry-mac
brew install pinentry-mac
echo "pinentry-program /opt/homebrew/bin/pinentry-mac" >> ~/.gnupg/gpg-agent.conf
gpg-connect-agent reloadagent /bye
git config user.email
gpg --list-keys
# 信任自己的密钥
gpg --edit-key 你的密钥ID
# 在交互界面中输入 trust,选择信任级别
编辑 ~/.gnupg/gpg-agent.conf
:
default-cache-ttl 3600
max-cache-ttl 86400
# 在特定项目中禁用签名
git config commit.gpgsign false
# 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
# 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 签名则为个人开发者和小团队提供了更简化的选择。
选择哪种签名方式主要取决于:
无论选择哪种方式,重要的是建立一致的签名策略,确保代码的完整性和可信