每次在终端里敲 git push,然后被要求输入用户名和密码——准确说是输入用户名和 Personal Access Token,因为 GitHub 早就把账号密码方式给禁了——这种体验一次两次还能忍,天天来就非常烦。而 SSH key 就是解决这个问题的标准方案:配置好之后,push、pull、clone 全部免密,安全感还比口令强得多。我见过太多人在这一步卡住,要么是密钥算法选错、生成出来的 key 不兼容,要么是配好了 ssh-agent 却老是报错,或者把公钥粘到 GitHub 上之后依然 Permission denied。
这篇就围绕 GitHub SSH key 的完整配置链路来写:从算法选型、密钥生成、ssh-agent 管理,到注册进 GitHub 账户、最终验证连通性,把每一步的原理和实操都讲透,还会专门聊聊 Windows 上那个非常经典的 ssh-agent 服务错误 1058。无论你是第一次配置的新手,还是换了电脑重装系统后想重新配一遍的老手,都可以直接照着操作。
1. 为什么推荐用 SSH key 而不是 HTTPS 口令
1.1 HTTPS 方式的痛点
很多人的第一个 GitHub 仓库都是用 HTTPS 地址 clone 的,因为 GitHub 给的默认提示就是 HTTPS。这个方式本身能用,但日常体验确实不够顺。2021 年 8 月之后,GitHub 彻底不再接受账号密码作为 git 操作的认证方式,你必须使用 Personal Access Token 或者 SSH key。用 HTTPS 加 token 的操作模式是:clone 的时候要求输入用户名,密码位置粘贴 token。token 那一长串字符谁记得住?每次都得去翻笔记或者重新生成。
更要命的是 token 有有效期。GitHub 允许你自己设置过期时间,但无论设多久,到期之后你都得重新生成、再重新配置。如果你手上有三四台设备,每台设备都要维护一份 token,这个维护成本相当可观。有人可能会说“我用 credential manager 缓存了,不用每次输”,那只是把凭据存在本机,换一台新机器、换一个用户、或者清理了凭据管理器之后,一切照旧。
1.2 SSH key 的认证逻辑
SSH key 采用的是公钥加密、私钥签名的认证方式。有一个很直观的类比:公钥是一把锁,你可以把它复制无数份,随便放到服务器上、放到 GitHub 账户里;私钥是钥匙,只有你自己有,绝不出本机。当你执行 git push 的时候,远程服务器会拿着一串随机数据过来,你的 SSH 客户端用私钥对它签名,服务器用你留在账户里的公钥验证签名是否匹配。验证通过,连接建立,整个过程中私钥不会在网络上传输。
这个机制带来的好处很明显:私钥不需要记住、不需要输入、不会被钓鱼页面骗走(除非你主动泄露),公钥泄露的问题也不大,因为你可以在 GitHub 后台随时删除或更换。对于日常频繁操作 GitHub 的人来说,SSH key 相当于一次配置、长期免密,收益非常明确。
1.3 两种方式的核心差异
| 对比维度 | HTTPS + Token | SSH Key |
|---|---|---|
| 认证材料 | 用户名 + Personal Access Token | 公钥 + 私钥 |
| 是否需要记住凭据 | 需要,token 是一长串随机字符 | 不需要,私钥由 ssh-agent 管理 |
| 有效期 | token 可设置过期时间,会失效 | 理论上永久有效,可后台手动撤销 |
| 多设备维护 | 每台设备都要配置 token | 每台设备生成独立密钥对即可 |
| 日常操作 | 配置不当仍会频繁要求输入 | 配好之后完全静默 |
| 安全性风险 | token 有被截图、误粘贴的风险 | 私钥泄露风险主要来自本机安全 |
如果你只是偶尔 clone 一个公开仓库,用 HTTPS 倒没什么问题。但只要是正经做开发、每天要多次 push 的人,我建议一次性把 SSH key 配好,这个投入非常值。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 密钥算法选型:ed25519 为何是当前首选
2.1 GitHub 支持哪些算法
GitHub 的 SSH 服务端目前支持的公开密钥算法包括 ecdsa-sha2-nistp256、ssh-ed25519、ssh-rsa(需要 RSA 密钥长度不低于 2048 位)。老的 DSA 算法早在 GitHub 这边就已经被移除了,所以完全不用考虑。
很多老教程还在让你用 ssh-keygen -t rsa -b 4096,这套流程放在五六年前没问题,放在今天就不是最优解了。官方文档里推荐的生成命令是 ssh-keygen -t ed25519 -C "your_email@example.com",这个推荐是非常有道理的,不是随便写写。
2.2 ed25519 的实际优势
ed25519 是 EdDSA 签名算法的一种实例,基于 Curve25519 椭圆曲线。和 RSA 相比,它在同样安全强度下密钥长度短得多:RSA 至少要 2048 位,安全场景下建议 4096 位;ed25519 的密钥长度固定是 256 位。从实际使用体感来看,ed25519 的生成速度、签名速度都比 RSA 快一个量级,尤其是在树莓派这类性能有限的设备上,差别非常明显。
安全性方面,ed25519 的设计本身就是围绕“避免实现错误”来的,没有 RSA 里那些填充方式、素数选择之类的复杂环节,出错的概率天然更低。而且它生成的公钥字符串很短,粘到 GitHub 页面上也清爽很多。
2.3 RSA 还有存在的必要吗
虽然 ed25519 是首选,但 RSA 并没有完全退出历史舞台。有些老旧的内部系统、旧版 Git 客户端、部分企业自建的 Git 服务,对 ed25519 的支持并不好,只认 RSA。如果你平时主要用 GitHub,那 ed25519 完全够用;如果你还要连公司内网的 Gerrit、GitLab 之类的老系统,建议额外生成一把 RSA 4096 的密钥专门给那些系统用。
我自己的做法是:GitHub 用 ed25519,公司内网用 RSA 4096,两把钥匙用 ~/.ssh/config 区分,互不干扰。后面会讲到具体配置。
2.4 算法对比速览
| 算法 | 推荐长度 | 公钥长度 | GitHub 支持 | 适用场景 |
|---|---|---|---|---|
| RSA | 2048 / 4096 位 | 较长 | 支持(不低于 2048) | 老旧系统、企业内网、兼容性优先 |
| ECDSA | 256 / 384 / 521 位 | 较短 | 支持(nistp256) | 兼容性较好但实现争议多 |
| Ed25519 | 固定 256 位 | 很短 | 支持 | GitHub 首选,新项目推荐 |
需要注意的是,ECDSA 依赖 NIST 曲线,历史上关于这些曲线是否存在后门的讨论一直没停过,虽然不是普通开发者需要操心的级别,但既然有 ed25519 这个更干净的选择,没必要在 ECDSA 上纠结。
3. 生成密钥:ssh-keygen 参数详解与多密钥管理
3.1 一条命令生成 ed25519 密钥
打开终端(macOS 或 Linux 直接开 Terminal,Windows 建议用 PowerShell 或 Windows Terminal),执行:
bash复制ssh-keygen -t ed25519 -C "your_email@example.com"
逐项解释一下:
-t ed25519:指定密钥算法类型,这里就是 ed25519。-C "your_email@example.com":指定注释。这个注释会出现在公钥文件的末尾,作用就是帮你记住这把钥匙是谁生成的、干什么用的。有人习惯填邮箱,有人习惯填“xxx-laptop”,都可以,不影响认证逻辑。
执行后终端会提示你选择保存路径:
code复制Generating public/private ed25519 key pair.
Enter file in which to save the key (/home/yourname/.ssh/id_ed25519):
这里直接回车使用默认路径就行。默认情况下,私钥文件是 ~/.ssh/id_ed25519,公钥文件是 ~/.ssh/id_ed25519.pub。
3.2 passphrase 到底要不要设
接下来终端会提示:
code复制Enter passphrase (empty for no passphrase):
很多人这里直接回车跳过,因为不想每次操作都输密码。但我建议设一个 passphrase。这里的 passphrase 相当于给私钥文件本身加了一层加密。即使你的私钥文件被拷贝走了,没有 passphrase 也解不开、用不了。设置了 passphrase 之后,配合 ssh-agent(下一节细讲),你只需要在开机后第一次使用时输入一次,之后 agent 会帮你记住解密后的私钥,后续操作依然免密。
如果你担心遗忘,passphrase 可以设得简单一点,但不要为空。这是一道非常关键的防线。
3.3 生成结果长什么样
生成完成后,用 ls -l ~/.ssh/ 查看,会看到两个文件:
id_ed25519:私钥文件,权限应该是600(仅当前用户可读写)。id_ed25519.pub:公钥文件,权限是644,内容可以公开。
用 cat ~/.ssh/id_ed25519.pub 查看公钥内容,会看到类似这样的一行:
code复制ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI... your_email@example.com
这一整行就是要粘到 GitHub 上去的内容。注意:千万不能把 id_ed25519(没有 .pub 后缀的那个)发给任何人。公钥是锁,私钥是钥匙,钥匙只有你自己能拿。
3.4 多密钥怎么管理
如果你除了 GitHub 还用 GitLab、公司内网、自己的云服务器,每一处都生成一个独立的密钥对是更稳妥的做法。生成时用 -f 参数指定文件名,比如:
bash复制ssh-keygen -t ed25519 -C "github-main" -f ~/.ssh/id_ed25519_github
ssh-keygen -t rsa -b 4096 -C "work-gerrit" -f ~/.ssh/id_rsa_work
生成完之后,在 ~/.ssh/ 目录下创建一个名为 config 的文件(没有扩展名),按下面的格式写:
code复制Host github.com
HostName github.com
User git
IdentityFile ~/.ssh/id_ed25519_github
Host work.example.com
HostName work.example.com
User git
IdentityFile ~/.ssh/id_rsa_work
这样 SSH 客户端在连接 github.com 时就会自动选择 id_ed25519_github 这把私钥,连接 work.example.com 时选择 id_rsa_work。这一步做好之后,多把钥匙完全可以共存,不需要每次手动切换。
3.5 目录权限别忽略
macOS 和 Linux 对 ~/.ssh 目录权限很敏感。如果权限太宽松,SSH 客户端会直接拒绝使用你的私钥。建议执行:
bash复制chmod 700 ~/.ssh
chmod 600 ~/.ssh/id_ed25519
chmod 644 ~/.ssh/id_ed25519.pub
Windows 上一般没有这个限制,但如果用 Git Bash 或 WSL 操作,最好也保持一致的习惯。
4. ssh-agent 原理、配置与 Windows 服务错误 1058 排查
4.1 ssh-agent 到底在干什么
很多人分不清 ssh-agent 和 SSH key 的关系。简单说,ssh-agent 是一个常驻后台的“钥匙保管员”。你把私钥交给它之后,每次 SSH 连接需要使用私钥签名时,agent 会替你完成签名操作,而不需要你重新输入私钥的 passphrase。
没有 ssh-agent 的情况下,如果你给私钥设置了 passphrase,那么每次 SSH 连接都会提示你输入 passphrase。有了 agent,你只需要在开机后把私钥添加一次,之后所有 SSH 操作都是静默的。这和多设备登录、自动化脚本的需求是天然匹配的。
4.2 基本操作命令
把私钥添加到 agent:
bash复制ssh-add ~/.ssh/id_ed25519
查看 agent 里当前有哪些私钥:
bash复制ssh-add -l
删除 agent 里的某个私钥:
bash复制ssh-add -d ~/.ssh/id_ed25519
清空所有私钥:
bash复制ssh-add -D
注意:ssh-add 添加的是私钥文件(不带 .pub 后缀的那个),不是公钥。
4.3 macOS 上的自动加载配置
macOS 的 OpenSSH 版本比较新,默认会尝试把密钥加载进系统钥匙串(Keychain)。为了让重启之后不用重新 ssh-add,可以在 ~/.ssh/config 里加上:
code复制Host *
AddKeysToAgent yes
UseKeychain yes
IdentityFile ~/.ssh/id_ed25519
AddKeysToAgent yes 的意思是:每次使用这把私钥时自动把它交给 agent 管理;UseKeychain yes 的意思是:passphrase 保存到 macOS 的 Keychain 里,重启后 agent 也能自动解锁。
4.4 Windows 上的 ssh-agent:那个经典的 error 1058
Windows 10 1809 之后,系统自带了 OpenSSH 客户端,也自带了 ssh-agent 服务。但很多人在 PowerShell 里执行 ssh-add 时会碰到这样的错误:
code复制unable to start ssh-agent service, error :1058
这个错误的含义是:服务无法启动,原因是服务被禁用(error 1058 对应的系统错误是 ERROR_SERVICE_DISABLED)。不是 SSH 没装好,而是 ssh-agent 服务的启动类型被设成了 Disabled,默认状态下根本没有运行。
解决办法是用管理员权限打开 PowerShell,执行:
powershell复制Set-Service -Name ssh-agent -StartupType Manual
Start-Service ssh-agent
第一条命令把启动类型改成手动,第二条命令立即启动服务。执行完之后再运行 ssh-add 就不会报这个错了。
为什么推荐改成 Manual 而不是 Automatic?ssh-agent 是按需启动的服务,需要的时候由 SSH 客户端自动拉起,没必要开机就常驻内存。改成 Manual 不仅够用,而且更干净。
如果你用的是旧版 Windows,可能系统里根本没有 ssh-agent 服务。这时候需要先去“设置” → “应用” → “可选功能”里确认 OpenSSH 客户端 是否已安装。Git for Windows 自带了一套 ssh-agent,但那是装在 Git Bash 环境里的,和 Windows 系统服务是两码事。如果你全程用 Git Bash,也可以不碰系统服务,直接在 Git Bash 里执行:
bash复制eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_ed25519
这种方式临时启动一个 agent 进程,缺点是每次新开 Git Bash 终端都要重新执行一遍,适合应急,不适合日常。
4.5 配置好 agent 之后的日常体感
配置完成后,我个人的使用感受是:系统重启之后第一次执行 git pull 或者 git push 时,终端会提示输入一次私钥 passphrase(如果设置了的话),输入之后 agent 就记住了,之后一整天都是静默的。如果你设置了 AddKeysToAgent yes,甚至连这次手动输入都可能省掉,因为首次使用私钥时 agent 会自动接管。
5. 公钥注册到 GitHub:完整流程与连通性验证
5.1 复制公钥内容
注册之前先确认公钥内容。执行:
bash复制cat ~/.ssh/id_ed25519.pub
复制输出的完整一行,从 ssh-ed25519 开始,到最后的注释结束,不要漏掉任何字符,也不要多余复制换行符。用鼠标选中复制的时候尤其小心。
5.2 GitHub 网页端操作步骤
- 登录 GitHub,点击右上角头像,选择
Settings。 - 在左侧边栏找到
SSH and GPG keys。 - 点击右上角的
New SSH key按钮。 Title字段随便填,建议填能识别设备的信息,比如ThinkPad-X1-2025、MacBook-Pro、company-desktop,方便以后知道哪台机器在用哪把钥匙。Key type保持默认的Authentication Key。注意别选成Signing Key,那是给 Git commit 签名用的,和认证不是一回事。- 把之前复制的公钥内容粘贴到
Key输入框。 - 点击
Add SSH key。
GitHub 会要求你输入账户密码确认一次,输入后公钥就注册成功了。
5.3 验证:ssh -T 是唯一标准
注册完成后,在终端执行:
bash复制ssh -T git@github.com
第一次连接时终端会提示确认远程主机的指纹,输入 yes 回车。接下来如果看到:
code复制Hi your-username! You've successfully authenticated, but GitHub does not provide shell access.
说明认证成功。这里的 your-username 是你 GitHub 账户名,如果是别人的名字,说明你用的私钥对应的是另一个账户的公钥。如果提示:
code复制Permission denied (publickey).
说明 GitHub 没有识别到有效的私钥,需要排查。大多数情况下,问题出在 ssh-agent 里没有加载对应的私钥,或者 ~/.ssh/config 里 IdentityFile 指向了错误的文件。依次检查:
bash复制ssh-add -l
确认列表里有 id_ed25519。如果没有,执行 ssh-add ~/.ssh/id_ed25519 添加后再验证。
5.4 原有仓库如何从 HTTPS 切换到 SSH
如果你之前是用 HTTPS 地址 clone 的仓库,现在配好了 SSH key,想切换过去,在仓库目录里执行:
bash复制git remote set-url origin git@github.com:your-username/your-repo.git
执行完再 git push,应该就直接走 SSH 通道了。可以用 git remote -v 确认修改结果。
5.5 公钥可以挂多台设备吗
可以。GitHub 允许一个账户添加多把公钥,没有数量上限(实际上有很大余量)。你可以在笔记本、台式机、服务器上分别生成不同的密钥对,把各自公钥都加到同一个 GitHub 账户下。这样的好处是,当某台设备丢失或不再使用时,可以单独删除那台设备的公钥,不影响其他设备;如果所有设备共用同一把私钥,一旦出现泄露风险,你就得在所有设备上重新配置。
6. 多账户、多设备场景下的几个补充心得
6.1 不要把私钥拷贝到多台设备
很多人的第一反应是:我在家里生成了一对密钥,直接把 id_ed25519 和 id_ed25519.pub 拷贝到公司电脑上,省得再生成一次。这个做法我不推荐。倒不是说一定会出问题,而是私钥文件一旦被拷贝,就多了一份泄露面;而且如果你在公司电脑上提交代码,Git 的 author 信息和 SSH key 之间没有绑定关系,排查问题时会多一层干扰。
正确做法是:每台设备独立生成密钥对,把各自的公钥注册到同一个 GitHub 账户。成本很低,管理却清晰很多。
6.2 多账户怎么验证各自有没有配错
如果你在 ~/.ssh/config 里配置了多个 Host,可以用 ssh -T 分别验证,比如:
bash复制ssh -T git@github.com
ssh -T git@gitlab.com
ssh -T git@work.example.com
如果每次都显示正确的用户名,说明 IdentityFile 的对应关系没问题。如果某个 Host 返回了错误的用户名,多半是 SSH 客户端用了默认的 id_ed25519 而没有按 config 里的指定文件走。这时候检查 config 文件的权限和格式,确认 Host 名称写的是你实际连接时用的域名。
6.3 公钥泄露了怎么办
公钥本身不算敏感信息,它本来就是公开给服务器验证用的。但如果你怀疑公钥匹配的私钥已经泄露(比如电脑丢失、私钥文件被拷贝),那就去 GitHub 后台把对应的公钥删除,然后重新生成一对新密钥,把新公钥注册上去。
这一步操作很简单,不需要惊慌。真正需要保护的是私钥文件,而不是公钥。
6.4 一个实用的小技巧:给私钥加注释
生成密钥时 -C 参数后面写的内容,会一直带在公钥末尾。很多人习惯在这里填邮箱,但我更建议填“用途+设备”,比如:
bash复制ssh-keygen -t ed25519 -C "github-desktop-2025"
这样在 GitHub 后台看到公钥列表时,一眼就能看出这把 key 是哪个设备的。虽然 Title 字段也能表达这个信息,但公钥内容末尾的注释是跟着密钥走的,拷贝到别的电脑上也看得出来历。
6.5 最终体验
全部配置完成之后,日常操作会非常顺畅:新 clone 一个仓库时直接用 git@github.com: 开头的 SSH 地址,后续所有 push 和 pull 都不会再问你密码;开了新终端、重启了电脑,ssh-agent 都会在后台替你处理好一切。唯一需要记住的是,私钥的 passphrase 不要忘记,它是你最后一道防线。
我在实际配置中最大的体会是:大部分人卡住的地方不在生成密钥、也不在 GitHub 网页操作,而是在 ssh-agent 这一环。尤其是 Windows 上那个 error 1058,服务禁用状态不解决,后面所有步骤都白搭。所以无论你用哪个系统,先把 agent 跑起来,再谈注册公钥,这个顺序是最省事的。
