使用GPG签署Git提交

通过给Commit提交签名验证,可以在本地对标记和提交进行签名。 这些标记或提交在 GitHub 上标示为已验证,便于其他人信任更改来自可信的来源。如果提交或标记具有可加密验证的 GPG、SSH、 或 S/MIME 签名,GitHub 会将提交或标记标示为“已验证”或“部分验证”。

下面使用Windows 11 进行相关的操作

安装Gpg4win

前往官网下载并安装Gpg4win。

在安装的时候请留心安装目录,因为gpg的目录在gpg4win安装目录的上一层的另一个目录中。

生成 GPG 密钥对

运行以下命令生成 GPG 密钥对

gpg --full-generate-key

在提示时,指定要生成的密钥类型(例如 RSA),密钥长度(例如 4096 位),有效期限(例如一星期)。输入你的用户 ID 信息,确保输入的电子邮件地址与 GitHub 帐户的经过验证的电子邮件地址一致,如果Github的邮箱你是私密的状态,请将Github给你的私密的邮箱地址填写到用户ID里,还可以设置密钥的密码。

配置Git签名

首先列出你拥有的 GPG 密钥,使用以下命令列出你拥有的 GPG 密钥的长形式 ID:

gpg --list-secret-keys --keyid-format=long

然后输出如下:

C:\Users\maisui>gpg --list-secret-keys --keyid-format=long
gpg: checking the trustdb
gpg: next trustdb check due at 2030-06-30
[keyboxd]
---------
sec   rsa4096/1E88D3314CA59A8E 2024-05-06 [SC] [expires: 2027-05-07]
      9EF70557285F391963168CE31E88D3314CA59A8E
uid                 [ultimate] jack <[email protected]>
ssb   rsa4096/F11321972DB3D79A 2024-05-06 [E] [expires: 2027-05-07]

在这个输出中:

  1. sec 行:
    • sec 表示这是你的 主要密钥(Primary Key),通常用于签名和认证,可以将其看做私钥,请不要与他人分享这个秘钥。
    • rsa4096 表示使用 RSA 4096 位算法。
    • 1E88D3314CA59A8E 是你的 短密钥 ID。
    • 9EF70557285F391963168CE31E88D3314CA59A8E 是你的 长秘钥 ID / 指纹
    • [SC] 标记表示这个密钥用于签名(S)和认证(C)。
    • [expires: 2027-05-07] 表示密钥的过期日期。在这之后,你需要更新密钥
  2. 用户 ID(UID)行:
    • uid 表示用户 ID,包含了你的用户名和电子邮件地址。
    • [ultimate] 表示这是你的主要用户 ID。
    • <[email protected]> 是你的电子邮件地址。
  3. ssb 行:
    • ssb 表示这是你的 子密钥(Subkey),用于加密或其他特定功能,可以将其看做公钥。
    • rsa4096 表示使用 RSA 4096 位算法。
    • F11321972DB3D79A 是子密钥的 短密钥 ID。
    • [E] 标记表示这个子密钥用于加密。
    • [expires: 2027-05-07] 表示公钥的过期日期。在这之后,你需要更新密钥

然后从列表中复制你想要使用的 GPG 短指纹密钥ID。

使用以下命令将生成的 GPG 密钥 ID 添加到 Git 配置中:

git config --global user.signingkey <主要密钥的短密钥ID>

将<主要密钥的短密钥ID>替换为你生成的GPG主要密钥的短密钥ID,这个例子中为:1E88D3314CA59A8E。

验证签名设置

如果你只想当前仓库签名

git config commit.gpgsign true

如果所有仓库签名

git config --global commit.gpgsign true

关闭签名

git config commit.gpgsign false

然后我们创建一个新仓库测试签名效果,然而会发现报错了,并没有将commit签名成功,报No secret key。

C:\Users\maisui\GPG>git commit  -m "Modify"
gpg: skipped "1E88D3314CA59A8E": No secret key
gpg: signing failed: No secret key
error: gpg failed to sign the data
fatal: failed to write commit object

出现这个问题是因为git默认使那个gpg程序并不是我们安装好的那个,所以我们还得配置成使用我们新安装的gpg。这里的安装目录就是我们Gpg4win的上一级,比如安装在:C:\Program Files (x86)\Gpg4win 的话,则gpg的安装目录一般在:C:\Program Files (x86)\GnuPG。

git config --global gpg.program "<GnuPG的安装目录>\bin\gpg.exe"

然后重新commit,你就发现签名成功了。

Github部署公钥

到这一步, 如果我们直接将提交推送到GitHub上,提交上将会出现一个Unverified的标签, 这是因为, 虽然我们给提交签名了, 但是, GitHub还是不知道这个签名到底来自于谁。接下来,我们就要告诉GitHub: 我们这个用户所对于的公钥是哪个。

查看公钥ID

gpg --list-keys

导出我们的公钥将最后面的换成自己的公钥ID

gpg --armor --export 9EF70557285F391963168CE31E88D3314CA59A8E

复制以-----BEGIN PGP PUBLIC KEY BLOCK-----开头并以-----END PGP PUBLIC KEY BLOCK-----结尾的 GPG 密钥。然后打开github --->settings ---> SSH and GPG Keys
在 GPG keys栏中添加一个新的GPG key 将内容复制进去,然后输入密码。

配置密码缓存的时间

如果配置了GPG密钥的密码,在创建commit的时候经常会弹出一个窗口让我们输GPG的密码,怎么让这个窗口尽量的不要那么频繁的弹出呢,可以在我们打开Kleopatra主界面,并点击顶部的“设置“菜单中的”配置Kleopatra“,在弹出的窗口中点击左侧菜单中的GnuPG系统,在右侧的窗口中点击Private Keys选项卡,其中有一个选项是Expire cached PINs after N second,它默认的数值是600秒,即十分钟,设为0则每次都需要输入密码,个人建议是在私人电脑上设置86400秒,即一天一输。至此所有的配置都OK了。

推荐调整方案

如果希望在工作日全天保持免密状态,可以按以下数值修改:

设置空闲超时:将 expire cached PINs after N seconds 改为 28800(8小时)或 43200(12小时)。

设置最大超时:将 set maximum PIN cache lifetime to N seconds 改为 86400(24小时)或更高。

注:如果开启了 GPG 作为 SSH Agent 使用,下方两项对应的 SSH keys 相关时间也可以同步调大。

使配置即时生效

Kleopatra 保存后会自动更新 gpg-agent.conf,但已在后台运行的 Agent 进程可能需要重载才能读取新配置。

在终端(PowerShell 或 CMD)中执行以下命令重载守护进程:

gpgconf --reload gpg-agent

验证方法

进行一次 git commit -S 并输入密码,随后在数小时内再次提交,若不再弹出 Pinentry 密码输入框,即说明长效缓存已生效。

PGP常用命令

gpg --full-generate-key: #生成密钥对
gpg --list-secret-keys --keyid-format LONG: #查看私钥信息
gpg --list-keys:#查看公钥
gpg --delete-secret-key <key ID>: #删除私钥
gpg --delete-key <key ID>: #删除公钥
gpg --armor --export <email or key-id> > public_key.asc :#导出公钥
gpg --armor --export-secret-keys <email or key-id> > private_key.asc : #导出私钥
gpg -e -r <recipient email or key-id> <file name>: #加密文件
gpg -d <file name>.gpg :#解密文件

自动化配置脚本(PowerShell)

如果你已经生成好了 GPG 密钥,可以直接复制代码并在 PowerShell 窗口中粘贴回车运行。脚本会自动定位 GnuPG 完整程序目录、配置 Git 全局签名与程序路径、设置 24 小时免密缓存并重载守护进程,最后直接将公钥复制到剪贴板:

& {
    Write-Host "=== 正在检测环境与配置 GPG ===" -ForegroundColor Cyan

    # 1. 检测 GnuPG 路径
    $gpgPaths = @(
        "$env:ProgramFiles\GnuPG\bin\gpg.exe",
        "${env:ProgramFiles(x86)}\GnuPG\bin\gpg.exe"
    )

    $gpgExe = $gpgPaths | Where-Object { Test-Path $_ } | Select-Object -First 1

    if (-not $gpgExe) {
        $cmd = Get-Command gpg.exe -ErrorAction SilentlyContinue
        if ($cmd) { $gpgExe = $cmd.Source }
    }

    if (-not $gpgExe) {
        Write-Warning "未找到 GnuPG 路径,请确认是否已安装 Gpg4win 并重启终端。"
        return
    }

    $binDir = Split-Path -Parent $gpgExe
    $gpgconfExe = Join-Path $binDir "gpgconf.exe"
    Write-Host "检测到 GPG 程序: $gpgExe" -ForegroundColor Green

    # 2. 列出可用私钥
    Write-Host "`n当前计算机中的 GPG 私钥列表:" -ForegroundColor Cyan
    & $gpgExe --list-secret-keys --keyid-format=LONG

    # 3. 获取 Key ID
    $keyId = Read-Host "`n请输入要绑定的密钥 ID(主钥 sec 或签名子钥 ssb [S] 后的 16 位字符)"
    $keyId = $keyId.Trim()

    if ([string]::IsNullOrWhiteSpace($keyId)) {
        Write-Warning "未输入密钥 ID,配置终止。"
        return
    }

    # 4. 配置 Git 全局签名
    git config --global gpg.program "$gpgExe"
    git config --global user.signingkey "$keyId"
    git config --global commit.gpgsign true
    Write-Host "Git 签名与 GPG 路径配置完成!" -ForegroundColor Green

    # 5. 配置 gpg-agent 24 小时密码缓存 (86400秒)
    $agentConfDir = "$env:APPDATA\gnupg"
    if (-not (Test-Path $agentConfDir)) {
        New-Item -ItemType Directory -Path $agentConfDir -Force | Out-Null
    }
    $agentConfPath = Join-Path $agentConfDir "gpg-agent.conf"

    $cacheConfig = "`ndefault-cache-ttl 86400`nmax-cache-ttl 86400"
    if (Test-Path $agentConfPath) {
        $content = Get-Content $agentConfPath -Raw
        if ($content -notmatch "default-cache-ttl") {
            Add-Content -Path $agentConfPath -Value $cacheConfig
        }
    } else {
        Set-Content -Path $agentConfPath -Value $cacheConfig.TrimStart()
    }

    # 使用绝对路径重载守护进程
    if (Test-Path $gpgconfExe) {
        & $gpgconfExe --reload gpg-agent
        Write-Host "gpg-agent 缓存时间已设为 24 小时并已成功重载!" -ForegroundColor Green
    } else {
        Write-Host "gpg-agent 缓存时间已设为 24 小时!" -ForegroundColor Green
    }

    # 6. 导出公钥并直接写入系统剪贴板
    & $gpgExe --armor --export $keyId | Set-Clipboard
    Write-Host "`n公钥已自动复制到剪贴板!可直接前往 GitHub 后台粘贴(Settings -> SSH and GPG keys)。" -ForegroundColor Yellow
}

使用方式:复制整段代码粘贴到 PowerShell 终端回车,按提示输入你的 16 位密钥 ID 即可完成所有配置并导出公钥。

暂无评论

发送评论 编辑评论


				
上一篇
下一篇