问题描述
在使用 GPG 签名 Git 提交时,如果配置了子密钥(Subkey),但 Git 仍然使用主密钥或其他子密钥进行签名。如何解决这个问题?
解决方案
查看密钥结构
首先查看你的 GPG 密钥结构:
1 | gpg --list-secret-keys --keyid-format LONG |
输出示例:
1 | sec rsa4096/0x1234567890ABCDEF 2024-01-01 [SCA] |
其中 ssb 行显示的就是子密钥,记录其 Key ID(如 0xFEDCBA0987654321)。
强制指定子密钥
关键步骤:在密钥 ID 后添加叹号 ! 来强制 Git 使用指定的子密钥。
1 | # 配置 Git 使用指定的子密钥(注意叹号) |
为什么需要叹号?
根据 GitHub 官方文档和 GPG 的工作原理:
GPG 的自动选择机制:当不指定叹号时,GPG 会自动选择一个”合适”的密钥进行签名。通常情况下,GPG 会优先使用最新创建的子密钥,如果没有合适的子密钥,则使用主密钥。
叹号的作用:叹号
!告诉 GPG “精确使用这个密钥,不要自动选择”。这可以确保 Git 始终使用你明确指定的子密钥。实际场景:假设你有以下密钥结构:
1
2
3sec 4096R/0x1234567890ABCDEF [SCA] (主密钥)
ssb 4096R/0xAAAAAAAAAAAAAAAA [SEA] (子密钥 1,旧)
ssb 4096R/0xFEDCBA0987654321 [SEA] (子密钥 2,新)如果你想使用旧的子密钥 1(
0xAAAAAAAAAAAAAAAA),但不加叹号,GPG 很可能会使用新的子密钥 2。只有添加叹号才能强制使用指定的子密钥。
验证配置
1 | # 查看 Git 配置 |
在日志中,你应该看到类似这样的输出:
1 | commit abc123... |
显示的密钥 ID 应该与你配置的子密钥一致。
常见问题
Git 使用了错误的密钥
症状:尽管配置了子密钥,Git 仍然使用主密钥或其他密钥签名。
解决方案:
- 使用叹号强制指定:
1 | git config --global user.signingkey 0xFEDCBA0987654321! |
- 清除缓存配置:
1 | git config --global --unset user.signingkey |
- 检查 GPG Agent 缓存:
1 | gpgconf --kill gpg-agent |
GPG 提示”secret key not found”
症状:提交时 GPG 找不到指定的密钥。
解决方案:
- 确认子密钥存在且可用:
1 | gpg --list-secret-keys --keyid-format LONG |
- 如果子密钥在智能卡上,确保卡片已插入且被识别:
1 | gpg --card-status |
总结
配置 Git 使用指定的 GPG 子密钥的关键是:在密钥 ID 后添加叹号 !。
1 | git config --global user.signingkey 0xSUBKEY_ID! |
这样可以强制 Git 使用你指定的子密钥,而不是让 GPG 自动选择。