用 1Password 管理 SSH 密钥:推送代码时由 1Password SSH 代理提供认证密钥,私钥不落盘;提交时用另一把 SSH 密钥签名,GitHub 上显示 Verified,本地也能用 allowed_signers 验证。
先看清成品
本机没有 1Password 桌面 App,所以用
ssh-keygen生成的测试密钥 + 系统 ssh-agent 代替 1Password 代理,在 Git 2.47.3 上实际跑通了 SSH 签名提交和本地验证(%G?为G),并复现了签名密钥写错时的报错。1Password SSH 代理、op-ssh-sign和 GitHub 上的 Verified 标记没有实际验证;配置写法来自 1Password 官方文档。
注意:1Password 是付费服务,计划和价格以官方价格页为准。不要共享个人账号或把主密码、Secret Key、服务账号令牌发给别人;团队共享请用共享保险库和权限设置。只管理你有权管理的凭据。
做完之后你会得到什么?
| 成果 | 说明 |
|---|---|
| 两把密钥 | 认证密钥、签名密钥,都存放在 1Password |
agent.toml |
控制代理提供哪些密钥、按什么顺序 |
~/.ssh/config |
GitHub 走 1Password 代理 |
| Git 签名配置 | gpg.format=ssh + allowed_signers |
| 检查脚本 | 打印签名配置来源并验证最近一次提交 |
需要准备哪些环境?
| 项目 | 要求 | 说明 |
|---|---|---|
| 1Password 桌面 App | Mac / Windows / Linux | 设置 → 开发者 → 打开 SSH 代理 |
| Git | 2.34 以上 | SSH 签名从 2.34 开始支持 |
| GitHub 账号 | 能添加 SSH 密钥 | 签名密钥的类型选 Signing key |
文件结构
23-1password-C-src/
├── agent.toml # 复制到 ~/.config/1Password/ssh/agent.toml
├── ssh_config # 追加到 ~/.ssh/config
└── check_signing.sh
第 1 步:生成两把密钥
在 1Password 里新建两个 SSH 密钥条目(类型 ed25519):GitHub 认证密钥、Git 签名密钥。认证和签名分开,任何一把出问题都可以单独轮换。
第 2 步:配置 SSH 代理
agent.toml:
# ~/.config/1Password/ssh/agent.toml
# 按顺序提供密钥,避免服务器默认 6 次尝试上限(MaxAuthTries)
[[ssh-keys]]
item = "GitHub 认证密钥"
vault = "Private"
[[ssh-keys]]
item = "Git 签名密钥"
vault = "Private"
[[ssh-keys]] 的顺序就是代理提供密钥的顺序。文件一旦存在就会覆盖默认行为,没写进来的密钥不会提供。
ssh_config:
# 追加到 ~/.ssh/config
# Linux 的代理套接字;macOS 为 "~/Library/Group Containers/2BUA8C4S2C.com.1password/t/agent.sock"
Host github.com
HostName github.com
User git
IdentityAgent ~/.1password/agent.sock
# 把公钥导出后指定,只提供这一把,避免逐把尝试
IdentityFile ~/.ssh/github_auth.pub
IdentitiesOnly yes
IdentityFile 指向公钥文件即可(在 1Password 中下载公钥),配合 IdentitiesOnly yes 只提供这一把。
ssh -T git@github.com
预期结果:1Password 弹窗请求授权,之后显示 Hi 用户名! You've successfully authenticated...。
第 3 步:配置提交签名
最省事的方法:在 1Password 中打开签名密钥 → Configure Commit Signing → Edit Automatically。它会写入:
[user]
signingkey = ssh-ed25519 AAAA...(你的签名公钥)
[gpg]
format = ssh
[gpg "ssh"]
program = (1Password 的 op-ssh-sign 路径,以 App 生成的片段为准)
[commit]
gpgsign = true
本地验证需要 allowed_signers 文件:
echo "你的提交邮箱 ssh-ed25519 AAAA...签名公钥" >> ~/.ssh/allowed_signers
git config --global gpg.ssh.allowedSignersFile ~/.ssh/allowed_signers
然后在 GitHub Settings → SSH and GPG keys → New SSH key,Key type 选 Signing key,粘贴签名公钥。
第 4 步:检查配置
check_signing.sh:
#!/usr/bin/env bash
# 在仓库目录运行,打印签名相关配置及来源,并验证最近一次提交的签名
set -u
for k in gpg.format user.signingkey user.email gpg.ssh.program commit.gpgsign gpg.ssh.allowedSignersFile; do
printf '%-28s %s\n' "$k" "$(git config --show-origin --get "$k" 2>/dev/null || echo '(未设置)')"
done
echo "---"
git log -1 --format='%h %G? %GS %s'
echo "(%G? 含义:G=有效签名,N=未签名,U=有效但签名者未在 allowed_signers 中,B=签名无效)"
本机演示(测试密钥代替 1Password,gpg.ssh.program 使用默认 ssh-keygen)实际输出:
gpg.format file:.git/config ssh
user.signingkey file:.git/config ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIp1zT1f... demo@example.com
user.email file:.git/config demo@example.com
gpg.ssh.program (未设置)
commit.gpgsign file:.git/config true
gpg.ssh.allowedSignersFile file:.git/config .git/allowed_signers
---
832ed9a G demo@example.com 第一次签名提交
--show-origin 能看出配置来自全局还是仓库,排查“明明配了却不生效”很有用。
调试示例
把 user.signingkey 写成不完整的公钥后提交,本机实际输出:
error: Couldn't load public key /tmp/.git_signing_key_tmptmsJhh: No such file or directory?
fatal: failed to write commit object
与 1Password 文档列出的错误一致,原因是 user.signingkey 不是有效公钥。用 git config --show-origin user.signingkey 找到是哪一层配置写错了。
另一个容易误会的点:本机演示中把 user.email 改成 other@example.com 后再提交,本地 %G? 仍是 G,因为本地验证按公钥在 allowed_signers 里找到了签名者。GitHub 还要求提交邮箱是你账号里已验证的邮箱,否则不会显示 Verified。
出错了怎么办?
| 现象 | 原因 | 解决 |
|---|---|---|
unsupported value for gpg.format: ssh |
Git 低于 2.34 | 升级 Git |
fatal: failed to write commit object |
signingkey 无效 | 见调试示例 |
gpg.ssh.allowedSignersFile needs to be configured |
没有 allowed_signers | 按第 3 步创建;不影响提交,只影响本地验证 |
| GitHub 显示 Unverified | 邮箱不匹配,或公钥加成了认证密钥 | 检查 git config user.email,重新以 Signing key 类型添加 |
Too many authentication failures |
代理提供的密钥太多 | 在 agent.toml 调整顺序,或用 IdentitiesOnly |
| 代理配置文件改了没反应 | 语法错误时代理会停止 | 在 App 的开发者设置里查看错误提示 |
模板规则
- 认证密钥和签名密钥分开。
- 提交邮箱与 GitHub 已验证邮箱一致。
- 用
--show-origin排查配置覆盖。
项目资源
| 用途 | 地址 |
|---|---|
| 1Password SSH 入门 | https://www.1password.dev/ssh/get-started |
| SSH 代理配置文件 | https://www.1password.dev/ssh/agent/config |
| 用 SSH 签名 Git 提交 | https://www.1password.dev/ssh/git-commit-signing |
| GitHub 提交签名验证 | https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification |
| git-config 文档 | https://git-scm.com/docs/git-config |
私钥放在 1Password 里,每次使用都要你确认,电脑丢了或被植入恶意程序,也没法直接把私钥拷走。签名则让别人能确认提交真的是你做的,两件事一次配好。