GPG 签名 Git Commit 完全指南 | 提升代码安全性与身份验证
在协作开发中,确保代码提交的真实性和完整性至关重要。GPG(GNU Privacy Guard)签名为 Git commit 提供了强大的身份验证机制,防止他人伪造你的提交记录。通过 GPG 签名,GitHub、GitLab 等平台会显示绿色的 "Verified" 标识,证明该提交确实来自你。本文将详细介绍从零开始的完整配置流程。
为什么需要 GPG 签名?
核心优势
| 优势 | 说明 |
|---|---|
| 🔒 身份验证 | 证明提交确实来自你,防止身份伪造 |
| ✅ 完整性保护 | 确保提交内容未被篡改 |
| 🟢 可信标识 | GitHub/GitLab 显示 "Verified" 徽章 |
| 🛡️ 安全防护 | 防止中间人攻击和提交注入 |
| 📋 审计追踪 | 提供不可抵赖的提交记录 |
适用场景
- ✅ 开源项目贡献:证明你的贡献真实性
- ✅ 企业团队协作:确保内部代码来源可信
- ✅ 个人项目管理:提升代码库的专业度
- ✅ 合规要求:满足某些行业的安全审计需求
GPG 安装
brew install gpg
# or
brew cask install keybase不同平台安装方法
macOS
# 方法 1:Homebrew(推荐)
brew install gnupg
# 方法 2:MacGPG2(图形界面)
# 下载:https://gpgtools.org/
# 验证安装
gpg --versionLinux
# Ubuntu/Debian
sudo apt-get install gnupg2
# CentOS/RHEL
sudo yum install gnupg2
# Arch Linux
sudo pacman -S gnupg
# 验证安装
gpg2 --versionWindows
# 方法 1:Gpg4win(推荐)
# 下载:https://gpg4win.org/
# 方法 2:Chocolatey
choco install gpg4win
# 方法 3:Scoop
scoop install gpg
# 验证安装
gpg --version常用命令
$ gpg --gen-key
$ gpg --list-keys
$ gpg --list-secret-keys
$ gpg2 --list-keys
$ gpg2 --list-secret-keys
$ gpg2 --keyserver hkp://pool.sks-keyservers.net --send-keys C6EED57A
$ gpg2 --keyserver hkp://pool.sks-keyservers.net --recv-keys C6EED57A命令详解
| 命令 | 功能 | 说明 |
|---|---|---|
gpg --gen-key | 生成新密钥对 | 交互式向导 |
gpg --list-keys | 列出公钥 | 查看所有公钥 |
gpg --list-secret-keys | 列出私钥 | 查看可用于签名的密钥 |
gpg2 --list-keys | 列出公钥(v2) | GnuPG 2.x 版本 |
--send-keys | 上传公钥到服务器 | 分享公钥 |
--recv-keys | 从服务器下载公钥 | 获取他人公钥 |
生成 GPG key
gpg --gen-key具体步骤如下
$ gpg --gen-key
gpg (GnuPG) 2.2.15; Copyright (C) 2019 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
注意:使用 "gpg --full-generate-key" 以获得一个功能完整的密钥产生对话框。
GnuPG 需要构建用户标识以辨认您的密钥。
真实姓名: Theo
电子邮件地址: fanxiaobin422@gmail.com
您选定了此用户标识:
"Theo <fanxiaobin422@gmail.com>"
更改姓名(N)、注释(C)、电子邮件地址(E)或确定(O)/退出(Q)? o
我们需要生成大量的随机字节。在质数生成期间做些其他操作(敲打键盘
、移动鼠标、读写硬盘之类的)将会是一个不错的主意;这会让随机数
发生器有更好的机会获得足够的熵。
gpg: 密钥 8284896418BCC645 被标记为绝对信任
gpg: 目录'/Users/xiexianbin/.gnupg/openpgp-revocs.d'已创建
gpg: 吊销证书已被存储为'/Users/xiexianbin/.gnupg/openpgp-revocs.d/11518af49eaa27d86ea01b5c901487ea218aeb1a.rev'
公钥和私钥已经生成并被签名。
pub rsa2048 2019-05-16 [SC] [有效至:2021-05-15]
11518af49eaa27d86ea01b5c901487ea218aeb1a
uid xiexianbin <me@xiexianbin.cn>
sub rsa2048 2019-05-16 [E] [有效至:2021-05-15]详细配置说明
步骤 1:选择密钥类型
# 使用完整生成模式(推荐)
gpg --full-generate-key
# 选项说明:
# (1) RSA and RSA (default) - 推荐
# (2) DSA and Elgamal
# (3) DSA (sign only)
# (4) RSA (sign only)
# (14) Existing key from card步骤 2:选择密钥长度
# 推荐配置:
RSA 密钥长度应在 1024 位与 4096 位之间。
您想要用多大的密钥尺寸?(2048) 4096
# 建议:
# - 个人使用:2048 位(足够安全)
# - 企业/高安全:4096 位(更安全但稍慢)步骤 3:设置有效期
# 选项:
# 0 = 密钥永不过期
# <n> = 密钥在 n 天后过期
# <n>w = 密钥在 n 周后过期
# <n>m = 密钥在 n 月后过期
# <n>y = 密钥在 n 年后过期
# 推荐:
# - 个人项目:0(永不过期)
# - 企业环境:1y 或 2y(定期轮换)步骤 4:填写用户信息
真实姓名: Your Name
电子邮件地址: your.email@example.com
注释: GitHub Key(可选,用于区分多个密钥)
# 重要提示:
# ⚠️ 邮箱必须与 Git 配置的邮箱一致!
# ⚠️ 确认信息无误后再继续步骤 5:设置密码短语
# 输入保护私钥的密码
# 建议使用强密码(12+ 字符,包含大小写、数字、符号)
# 可以使用密码管理器保存
# 提示:
# - 密码不会显示在屏幕上
# - 需要输入两次确认
# - 忘记密码将无法恢复私钥!步骤 6:生成熵
# 系统需要收集随机数据来生成密钥
# 在此期间可以:
# - 敲击键盘
# - 移动鼠标
# - 打开/关闭程序
# - 读写文件
# 等待直到显示:
# "公钥和私钥已经生成并被签名"查看 GPG key
gpg --list-keys
gpg --list-secret-keys示例
$ gpg --list-keys
/Users/xiexianbin/.gnupg/pubring.kbx
------------------------------------
pub rsa2048 2019-05-16 [SC] [有效至:2021-05-15]
11518af49eaa27d86ea01b5c901487ea218aeb1a
uid [ 绝对 ] xiexianbin <me@xiexianbin.cn>
sub rsa2048 2019-05-16 [E] [有效至:2021-05-15]输出解读
pub rsa2048 2019-05-16 [SC] [有效至:2021-05-15]
11518af49eaa27d86ea01b5c901487ea218aeb1a
uid [ 绝对 ] xiexianbin <me@xiexianbin.cn>
sub rsa2048 2019-05-16 [E] [有效至:2021-05-15]
# 字段说明:
# pub - 公钥(Public Key)
# sub - 私钥(Subkey,用于加密)
# rsa2048 - 算法和密钥长度
# 2019-05-16 - 创建日期
# [SC] - 用途:S=签名(Sign), C=认证(Certify)
# [E] - 用途:加密(Encrypt)
# 11518af4... - 密钥指纹(Key ID)
# [ 绝对 ] - 信任级别密钥
pub:公钥sub:私钥11518af49eaa27d86ea01b5c901487ea218aeb1a是 pub GPG key ID
导出公钥
gpg --armor --export <pub GPG key ID>示例:
gpg --armor --export 11518af49eaa27d86ea01b5c901487ea218aeb1aGPG key 格式
-----BEGIN PGP PUBLIC KEY BLOCK-----
mQINBFz...(Base64 编码的密钥数据)
...
-----END PGP PUBLIC KEY BLOCK-----导出到文件:
# 导出到文件
gpg --armor --export your@email.com > gpg_public_key.asc
# 或直接复制终端输出
gpg --armor --export your@email.com删除GPG key
gpg --delete-keys <pub GPG key ID>
gpg --delete-secret-keys <pub GPG key ID>完整删除流程:
# 1. 先删除私钥(必须)
gpg --delete-secret-keys 11518af49eaa27d86ea01b5c901487ea218aeb1a
# 2. 再删除公钥
gpg --delete-keys 11518af49eaa27d86ea01b5c901487ea218aeb1a
# 3. 验证删除
gpg --list-keys
gpg --list-secret-keys⚠️ 警告:删除密钥后无法恢复,请谨慎操作!
Github 配置 GPG
配置 GPG 公钥到仓库
Github Setting -> SSH and GPG keys -> New GPG Key 导入即可
详细步骤
步骤 1:获取公钥
# 方法 1:导出到剪贴板(macOS)
gpg --armor --export your@email.com | pbcopy
# 方法 2:导出到文件
gpg --armor --export your@email.com > ~/gpg_key.asc
# 然后用文本编辑器打开复制
# 方法 3:直接查看
gpg --armor --export your@email.com
# 选中并复制全部内容(包括 BEGIN 和 END 行)步骤 2:添加到 GitHub
- 登录 GitHub
- 点击右上角头像 →【Settings】
- 左侧菜单选择【SSH and GPG keys】
- 点击【New GPG key】
- 粘贴公钥内容
- 点击【Add GPG key】
- 输入 GitHub 密码确认
步骤 3:验证添加
- 公钥会显示在列表中
- 显示创建日期和密钥 ID
- 状态为活跃
本地代码仓库启用GPG Sign
通过 gpg --list-keys 查看 pub GPG key ID,后设置 git签名 时用的 key
全局设置
# 配置已经生成的GPG Key ID
git config --global user.signingkey <pub GPG key ID>
# 配置启用GPG签名
git config --global commit.gpgsign true示例:
git config --global user.signingkey 11518af49eaa27d86ea01b5c901487ea218aeb1a
git config --global commit.gpgsign true指定仓库设置,需要进入代码目录:
# 配置已经生成的GPG Key ID
git config --local user.signingkey <pub GPG key ID>
# 配置启用GPG签名
git config --local commit.gpgsign true验证配置:
# 查看全局配置
git config --global --list | grep gpg
# 查看当前仓库配置
git config --local --list | grep gpg
# 预期输出:
# user.signingkey=11518af49eaa27d86ea01b5c901487ea218aeb1a
# commit.gpgsign=true配置说明:
| 配置项 | 作用 | 推荐 |
|---|---|---|
user.signingkey | 指定用于签名的密钥 ID | 必填 |
commit.gpgsign | 自动为所有 commit 签名 | 推荐 true |
tag.gpgSign | 自动为 tag 签名 | 可选 |
gpg.program | 指定 GPG 程序路径 | 默认即可 |
重启 gpg-agent
gpgconf –kill gpg-agent为什么需要重启?
- 清除缓存的密钥信息
- 重新加载配置
- 解决签名失败问题
其他相关命令:
# 查看 gpg-agent 状态
gpgconf --list-dirs
# 重启特定组件
gpgconf --kill gpg-agent
gpgconf --launch gpg-agent
# 查看日志
tail -f ~/.gnupg/S.gpg-agent上述示例
~ xiexianbin$ git config --global user.signingkey 11518af49eaa27d86ea01b5c901487ea218aeb1a
~ xiexianbin$ git config --global commit.gpgsign true
~ xiexianbin$ gpgconf –kill gpg-agent
gpg:OpenPGP:/usr/local/Cellar/gnupg/2.2.15/bin/gpg
gpg-agent:私钥:/usr/local/Cellar/gnupg/2.2.15/bin/gpg-agent
scdaemon:智能卡:/usr/local/Cellar/gnupg/2.2.15/libexec/scdaemon
gpgsm:S/MIME:/usr/local/Cellar/gnupg/2.2.15/bin/gpgsm
dirmngr:网络:/usr/local/Cellar/gnupg/2.2.15/bin/dirmngr
pinentry:密码条目:/usr/local/opt/pinentry/bin/pinentry
~ xiexianbin$git 使用
提交
git commit -am "feature: something"
git push origin develop然后我们可以在 git 中看到 Verified 的标识。
如果不设置 git config --global commit.gpgsign true,提交的时候加上一个 -S 参数就可以为提交签名:
git commit -S -m `your commit message`签名提交流程
自动签名(推荐):
# 已配置 commit.gpgsign=true
git add .
git commit -m "feat: add new feature"
# 自动弹出密码输入框
# 提交成功后显示 Verified 标识手动签名:
# 未配置自动签名时
git commit -S -m "feat: add new feature"
# 指定密钥
git commit -S<key-id> -m "feat: add new feature"批量提交签名:
# 修改多个文件后
git add file1.js file2.js file3.js
git commit -S -m "refactor: update multiple files"提交 tag 时签名
git tag -s ...详细用法:
# 创建带签名的 tag
git tag -s v1.0.0 -m "Release version 1.0.0"
# 签署已有的 tag
git tag -s v1.0.0 HEAD -f
# 验证 tag 签名
git tag -v v1.0.0
# 推送签名 tag
git push origin v1.0.0查看日志
git log --show-signature -1更多查看方式:
# 查看最近一次提交的签名
git log --show-signature -1
# 查看所有提交的签名状态
git log --pretty=format:"%h %G? %aN %s"
# 仅显示已验证的提交
git log --pretty=format:"%h %G? %aN %s" | grep "^.* G .*"
# 图形化查看
git log --graph --oneline --show-signature签名状态标识:
G - good signature(良好签名)
B - bad signature(错误签名)
U - good signature, unknown validity(未知有效性)
X - good signature, expired key(密钥已过期)
R - good signature, revoked key(密钥已撤销)
E - cannot check (no public key)(无公钥)
N - no signature(无签名)高级配置
1. 配置 GPG Agent
编辑配置文件:
# macOS/Linux
nano ~/.gnupg/gpg-agent.conf
# 添加以下内容
default-cache-ttl 600
max-cache-ttl 7200
allow-preset-passphrase配置说明:
default-cache-ttl 600 # 密码缓存时间(秒)
max-cache-ttl 7200 # 最大缓存时间(秒)
allow-preset-passphrase # 允许预设密码(脚本自动化)重启生效:
gpgconf --kill gpg-agent
gpgconf --launch gpg-agent2. 配置 Pinentry
macOS 用户:
# 使用 macOS 原生密码输入框
echo "pinentry-program /usr/local/bin/pinentry-mac" >> ~/.gnupg/gpg-agent.conf
# 安装 pinentry-mac
brew install pinentry-macLinux 用户:
# 使用 GTK 界面
echo "pinentry-program /usr/bin/pinentry-gtk-2" >> ~/.gnupg/gpg-agent.conf
# 或使用命令行
echo "pinentry-program /usr/bin/pinentry-curses" >> ~/.gnupg/gpg-agent.confWindows 用户:
# Gpg4win 自带 pinentry,通常无需配置3. 多密钥管理
列出所有密钥:
gpg --list-keys --keyid-format long切换默认密钥:
# 查看当前配置
git config --global user.signingkey
# 修改为其他密钥
git config --global user.signingkey NEW_KEY_ID为不同项目使用不同密钥:
# 全局使用密钥 A
git config --global user.signingkey KEY_A
# 特定项目使用密钥 B
cd /path/to/project
git config --local user.signingkey KEY_B常见问题
$ GIT_TRACE=1 git commit -m "xxx"
22:03:55.417251 git.c:455 trace: built-in: git commit -m 'feature: jwt support'
22:03:55.424110 run-command.c:667 trace: run_command: gpg --status-fd=2 -bsau B5A1B728A2FD170FE0E6C4E2D6B71988603A67D2
error: gpg failed to sign the data
fatal: failed to write commit object
或
error: gpg 无法为数据签名
fatal: 写提交对象失败解决办法
echo export GPG_TTY=$(tty) >> ~/.bash_profile
export GPG_TTY=$(tty)重新执行,发现会弹出一个密码输入界面。
如果没有解决,执行如下命令
$ gpg --status-fd=2 -bsau B5A1B728A2FD170FE0E6C4E2D6B71988603A67D2
# 如果卡住,执行
killall gpg-agent常见问题完整解决方案
问题 1:gpg failed to sign the data
症状:
error: gpg failed to sign the data
fatal: failed to write commit object解决方案:
# 方案 1:设置 GPG_TTY(最常见)
echo 'export GPG_TTY=$(tty)' >> ~/.bashrc # Linux
echo 'export GPG_TTY=$(tty)' >> ~/.zshrc # macOS
source ~/.zshrc
# 方案 2:重启 gpg-agent
gpgconf --kill gpg-agent
gpgconf --launch gpg-agent
# 方案 3:检查密钥是否存在
gpg --list-secret-keys
# 方案 4:验证 Git 配置
git config --global user.signingkey
git config --global commit.gpgsign
# 方案 5:测试手动签名
echo "test" | gpg --clearsign问题 2:No secret key
症状:
error: No secret key解决方案:
# 1. 检查私钥是否存在
gpg --list-secret-keys
# 2. 如果没有,导入私钥备份
gpg --import private_key_backup.asc
# 3. 或者重新生成密钥
gpg --full-generate-key
# 4. 更新 Git 配置
git config --global user.signingkey NEW_KEY_ID问题 3:Inappropriate ioctl for device
症状:
error: Inappropriate ioctl for device解决方案:
# macOS
brew install pinentry-mac
echo "pinentry-program /usr/local/bin/pinentry-mac" >> ~/.gnupg/gpg-agent.conf
gpgconf --kill gpg-agent
# Linux
sudo apt-get install pinentry-curses
echo "pinentry-program /usr/bin/pinentry-curses" >> ~/.gnupg/gpg-agent.conf
gpgconf --kill gpg-agent问题 4:密钥已过期
症状:
key has expired解决方案:
# 1. 延长密钥有效期
gpg --edit-key YOUR_KEY_ID
> expire
> save
# 2. 上传更新后的公钥
gpg --keyserver keyserver.ubuntu.com --send-keys YOUR_KEY_ID
# 3. 更新 GitHub 上的公钥
# 重新导出并替换 GitHub 上的公钥
gpg --armor --export YOUR_EMAIL | pbcopy问题 5:Unverified 标识
症状:
- Commit 显示 "Unverified" 而非 "Verified"
原因和解决:
# 原因 1:邮箱不匹配
# 检查 Git 邮箱
git config user.email
# 检查 GPG 密钥邮箱
gpg --list-keys
# 确保两者一致
# 原因 2:公钥未上传到 GitHub
# 重新导出并添加到 GitHub
gpg --armor --export your@email.com
# 原因 3:使用了错误的密钥
# 检查当前使用的密钥
git config user.signingkey
# 确保与 GitHub 上的公钥对应问题 6:密码每次都要输入
解决方案:
# 配置密码缓存
cat >> ~/.gnupg/gpg-agent.conf << EOF
default-cache-ttl 3600
max-cache-ttl 86400
EOF
# 重启 agent
gpgconf --kill gpg-agent
# macOS 用户使用 Keychain
brew install pinentry-mac
echo "pinentry-program /usr/local/bin/pinentry-mac" >> ~/.gnupg/gpg-agent.conf最佳实践
1. 密钥备份
# 导出私钥(重要!)
gpg --export-secret-keys --armor your@email.com > backup_private_key.asc
# 导出公钥
gpg --export --armor your@email.com > backup_public_key.asc
# 导出吊销证书
gpg --output revoke_cert.asc --gen-revoke your@email.com
# 安全存储
# - 保存到加密的 USB 驱动器
# - 打印纸质备份
# - 存储在密码管理器中2. 密钥轮换
# 建议轮换周期:
# - 个人使用:2-3 年
# - 企业环境:1 年
# - 高安全需求:6 个月
# 轮换步骤:
# 1. 生成新密钥
gpg --full-generate-key
# 2. 更新 Git 配置
git config --global user.signingkey NEW_KEY_ID
# 3. 上传新公钥到 GitHub
# 4. 保留旧密钥用于验证历史提交
# 5. 适时吊销旧密钥
gpg --edit-key OLD_KEY_ID
> revkey
> save3. 安全建议
# ✅ 应该做的:
# - 使用强密码保护私钥
# - 定期备份密钥
# - 使用 4096 位密钥(高安全场景)
# - 保持 GPG 软件更新
# - 验证他人公钥指纹
# ❌ 不应该做的:
# - 不要分享私钥
# - 不要在公共场合输入密码
# - 不要忽略密钥过期警告
# - 不要使用过时的 GPG 版本
# - 不要在不信任的机器上使用私钥总结
GPG 签名为 Git 提交提供了强大的安全保障:
- ✅ 身份验证:证明提交的真实性
- ✅ 完整性保护:防止内容篡改
- ✅ 可信标识:GitHub "Verified" 徽章
- ✅ 专业形象:提升代码库可信度
- ✅ 审计追踪:不可抵赖的记录
关键步骤回顾:
1. 安装 GPG
2. 生成密钥对
3. 导出公钥并添加到 GitHub
4. 配置 Git 使用 GPG 签名
5. 测试提交并验证下一步学习:
开始使用 GPG 签名,让你的代码提交更加安全可靠!🔐✨