资讯动态

GitHub SSH Key配置与排查:从密钥生成到多账号管理

发布时间:2026/10/19 15:01:48 来源:尧图企业网站定制
最近帮一位同事排查GitHub连不上的问题折腾了半个多小时最后发现是SSH key的权限多了一位。这事让我想写一篇关于GitHub SSH key的完整实操记录。很多刚开始用Git的朋友在配置密钥时要么照着一篇老教程复制粘贴要么连公钥和私钥的关系都没搞清楚导致换台电脑、换个账号就原地爆炸。这篇内容我会从为什么需要用SSH key讲起把本地生成密钥、添加公钥到GitHub、配置多账号、排查常见问题这几个环节全部走一遍并附上我实际踩过的坑和解决办法无论你是刚接触Git的新手还是被Permission denied折磨过的老手都能找到可复现的操作步骤和排查思路。1. SSH Key是什么为什么GitHub要用它1.1 HTTP与SSH两种连接方式的区别从GitHub克隆仓库时通常会看到两种地址HTTPS地址和SSH地址。HTTPS地址长这样https://github.com/用户名/仓库名.gitSSH地址长这样gitgithub.com:用户名/仓库名.git。很多初学者都会疑惑既然HTTPS直接输用户名密码就能用为什么还要费劲配置SSH key关键区别在于鉴权方式的差异。HTTPS方式在每次push、pull时都需要验证身份。虽然现在GitHub支持用personal access token替代密码但token同样属于“每次都要带上的凭证”而且token有过期时间一旦过期就又得重新生成。SSH方式则是一次配置、长期有效。你的电脑上保存一把私钥GitHub服务器上保存对应的公钥推送代码时客户端会用私钥签名服务器用公钥验签整个过程不需要输入任何账号密码体验上要顺畅得多。另外从安全性角度看SSH key的私钥只存在于本地不会在网络中传输而HTTPS方式在传输过程中虽然也有加密但每次都要处理凭证总会增加被截获或泄露的风险。所以我个人是强烈建议使用SSH方式管理GitHub仓库的尤其是每天频繁推送代码的人省下的时间积少成多。1.2 公钥与私钥的对应关系这里我尽量用生活化的方式解释。可以把公钥想象成一把锁私钥是唯一的钥匙。你把锁公钥交给GitHub钥匙私钥留在家本地电脑里。当你要打开GitHub这扇门时门会要求你用钥匙证明“我就是那把锁的主人”。由于钥匙没有离开过你所以别人即使捡到你的锁也开不了门。用更严谨一点的说法SSH使用非对称加密算法。私钥能生成一个签名公钥能验证这个签名是否由对应的私钥产生。GitHub在收到你的连接请求时会发送一个随机挑战你的SSH客户端用私钥对挑战签名GitHub用你上传的公钥验证签名。验证通过就认定你是合法的仓库访问者。整个过程私钥没有被传输因此即使网络被人监听也无法窃取你的私钥。这也是为什么公钥可以公开甚至可以上传到任意代码托管平台而私钥必须严格保密一旦泄露就等于把家门钥匙给了别人。很多人喜欢把id_rsa文件直接上传到某个网盘备份这是非常危险的操作。1.3 为什么推荐Ed25519而不是RSA老教程里最常见的生成命令是ssh-keygen -t rsa -b 4096 -C youexample.com生成id_rsa和id_rsa.pub。这在几年前确实没毛病但现在已经有了更好的选择ed25519。Ed25519是爱德华曲线数字签名算法的一种实现它的密钥长度更短公钥约68字节而RSA 4096的公钥有几百字节生成速度快安全性也更高。更关键的是GitHub早已支持Ed25519格式的SSH key主流操作系统和OpenSSH版本也都原生支持。用ssh-keygen -t ed25519生成出来的是id_ed25519和id_ed25519.pub命名本身就比id_rsa更有辨识度。可能有人担心Ed25519会不会还不被某些老系统支持。根据OpenSSH 6.52014年发布开始就支持该算法来看只要是过去十年内更新过系统的机器基本都没问题。所以除非你的环境非常陈旧否则建议直接上Ed25519。当然如果你需要兼容一些特别老旧的内部系统保留RSA 4096也无可厚非但日常个人使用完全没必要再选RSA。2. 本地生成密钥的完整实操2.1 检查是否已有SSH key在开始生成之前先要确认你的电脑上是否已经存在密钥避免覆盖掉原来正在使用的密钥。不同操作系统命令略有差异但检查的都是同一个目录~/.ssh。在Linux或macOS上ls -la ~/.ssh在Windows上如果用的是Git Bash或PowerShell同样可以执行ls ~/.sshGit Bash或Get-ChildItem ~/.sshPowerShell。如果该目录下已经有id_ed25519或id_rsa这类文件说明以前生成过密钥。此时不要急着覆盖先确认这些密钥是否还在使用。你可以执行ssh -T gitgithub.com测试一下如果返回Hi 用户名! Youve successfully authenticated...说明这个密钥已经在用了就不需要重新生成。如果返回的是Permission denied (publickey)则可能需要把当前公钥加到GitHub或者这个密钥已经失效。很多人在新电脑上一顿操作猛如虎直接执行生成命令结果把旧密钥覆盖了旧电脑上的Git操作全部失效这就是没做检查的后果。我建议的做法是如果~/.ssh下有旧密钥但你不确定它的用途可以先把整个目录备份一份cp -r ~/.ssh ~/.ssh_backup。然后再决定是否生成新密钥这样最稳妥。提示~/.ssh目录下的文件权限也很重要后面会专门讲但这里至少记住一点私钥文件不能被其他用户读取否则SSH客户端会拒绝使用它。2.2 生成新密钥的详细命令与参数说明确认好没有旧密钥或已备份后就可以生成新密钥了。推荐使用Ed25519算法ssh-keygen -t ed25519 -C your_emailexample.com -f ~/.ssh/id_ed25519参数说明-t ed25519指定密钥类型为Ed25519。-C your_emailexample.com添加注释。这个邮箱不需要一定是GitHub注册邮箱只起备注作用方便你日后识别这把密钥是谁生成的。很多人习惯填GitHub登录邮箱这没问题但我更推荐填一个你能看懂的标识比如work-laptop-2024。-f ~/.ssh/id_ed25519指定密钥文件的保存路径和文件名。如果你不指定-f它会默认保存为~/.ssh/id_ed25519然后交互式问你一些问题也足够方便。如果你因为某些原因必须用RSA可以用ssh-keygen -t rsa -b 4096 -C your_emailexample.com -f ~/.ssh/id_rsa执行后终端会提示Generating public/private ed25519 key pair. Enter file in which to save the key (/home/you/.ssh/id_ed25519): Enter passphrase (empty for no passphrase):passphrase这一步是设置私钥的密码短语。很多人为了图省事直接回车跳过。这里我强烈建议设置一个密码短语哪怕只是几个单词或一句话。它的作用是即使你的私钥文件被偷走攻击者也无法直接使用因为每次用私钥时都要输入密码短语。代价是你每次连接GitHub时都会被要求输入一次不过配合后面的ssh-agent只需要在把密钥加入agent时输入一次后续就不用重复输入了。设置好passphrase后会在~/.ssh下生成两个文件id_ed25519私钥和id_ed25519.pub公钥。注意id_ed25519.pub才是要上传到GitHub的内容私钥永远不要给任何人。2.3 多电脑多账号场景下的密钥规划如果你同时使用个人电脑、公司电脑或者一个GitHub账号下要管理多个工作用途的密钥就需要从一开始就做好规划。我见过很多人把所有电脑都生成同一个默认的id_ed25519文件然后到处复制私钥最后密钥托管在某个云盘里一地鸡毛。这种做法非常危险也不便于撤销。正确的做法是每台设备生成独立的密钥并为每把密钥取一个有意义的名字。例如个人电脑~/.ssh/github_personal工作电脑~/.ssh/github_work某个项目专用~/.ssh/github_projectX生成时用-f指定文件名即可。这样如果某台电脑丢失或不再使用你只需要在GitHub后台删除对应的公钥其他设备不受任何影响。不同文件名的密钥还可以通过~/.ssh/config来配置不同账号或不同主机的使用规则关于这部分后面会详细展开。3. 把公钥添加到GitHub账户3.1 复制公钥时最容易踩的坑生成好密钥后打开公钥文件。很多人直接用cat ~/.ssh/id_ed25519.pub然后把输出复制到网页上这一步看似简单其实隐藏着不少问题。第一cat命令输出到终端时可能因为终端宽度限制自动换行复制的时候会把换行符一并复制进去导致粘贴到GitHub后变成多行密钥解析失败。第二某些终端会自动在行尾添加额外的空格或符号。第三如果公钥文件里包含多余的空行或注释也会导致校验失败。最稳妥的复制方式是用命令直接读取到剪贴板。在macOS上pbcopy ~/.ssh/id_ed25519.pub在Linux上需要安装xclipxclip -selection clipboard ~/.ssh/id_ed25519.pub在Windows Git Bash中clip ~/.ssh/id_ed25519.pub如果实在没有剪贴板命令也可以用cat输出后用鼠标从开头仔细选到结尾注意不要多选。粘贴到GitHub页面后检查输入框中显示的密钥是否以ssh-ed25519或ssh-rsa开头且是完整的一行结尾没有多余空行然后再保存。3.2 添加公钥的操作路径登录GitHub后点击右上角头像选择Settings然后进入左侧SSH and GPG keys页面。点击New SSH key按钮会出现两个字段Title和Key。Title是给这把密钥起一个备注名例如My MacBook Pro、Desktop-2024方便以后识别。Key粘贴刚才复制的公钥内容。保存后GitHub会弹出一个安全确认提示要求你输入GitHub账号密码或进行二次验证。输入后公钥就正式添加到账号中了。如果是在公司或团队中可能使用的是组织级的SSH证书或部署密钥那些属于更高阶的用法普通个人账号按照上面操作就行。另外如果你添加公钥后仍然无法连接先别急着怀疑GitHub多数情况下是本地ssh-agent或文件权限问题下面一节会讲验证方法。3.3 验证SSH连通性添加公钥后的第一件事就是测试连通性。在终端执行ssh -T gitgithub.com注意这里的用户名必须是git不是你的GitHub用户名。连接成功时会返回类似Hi yourusername! Youve successfully authenticated, but GitHub does not provide shell access.看到这行就说明SSH key已经生效。如果第一次连接终端可能会询问是否确认GitHub的指纹输入yes即可。这个指纹是GitHub服务器的主机密钥用来防止中间人攻击第一次看到时需要确认属于正常现象。有个小细节ssh -T并不会真正打开一个shell因为GitHub只允许GIT操作所以提示中那句“does not provide shell access”是正常的不要因此以为自己配置错了。4. SSH config与多密钥管理4.1 为什么需要~/.ssh/config如果你只有一把默认的id_ed25519密钥并且只连接GitHub一个平台其实不需要配置文件SSH会自动使用~/.ssh/id_ed25519。一旦你开始使用多把密钥、多个GitHub账号、或者同时使用GitHub和其他代码托管平台时SSH就无法自动判断该用哪把钥匙了。这时就需要~/.ssh/config来显式指定匹配规则。举个例子你有个人账号和工作账号两个GitHub账号分别想从同一台电脑上访问不同的仓库那么两把密钥不能都叫id_ed25519否则SSH只认默认的。你需要创建~/.ssh/config为不同Host指定不同的IdentityFile。SSH连接时会根据你给出的Host名称去匹配对应的配置项然后选用对应的私钥。我看过不少多账号翻车的案例明明两个账号都添加了公钥但clone时总是报Permission denied原因就是SSH选择密钥时选错了。配置文件就是解决这类问题的根本方案。4.2 配置文件语法与多账号示例~/.ssh/config的语法并不复杂核心就是按Host块组织配置。先看一个最常用的多账号示例# 个人账号默认使用 Host github.com HostName github.com User git IdentityFile ~/.ssh/id_ed25519_personal IdentitiesOnly yes # 工作账号通过别名连接 Host github-work HostName github.com User git IdentityFile ~/.ssh/id_ed25519_work IdentitiesOnly yes在这个配置中当你执行git clone gitgithub.com:your-name/repo.git时SSH会看到Host为github.com于是匹配第一个块使用id_ed25519_personal。当你执行git clone gitgithub-work:company/repo.git时SSH匹配第二个块但实际连接的主机仍然是github.com只是密钥换成了id_ed25519_work。注意仓库的远程地址里git后面的部分需要和Host字段匹配。比如工作账号的仓库地址要写成gitgithub-work:company/repo.git而不是原生的github.com。这个多出来的别名不会影响GitHub解析因为HostName字段已经指定了真实主机。IdentitiesOnly yes这个参数非常重要。它告诉SSH不要自动尝试~/.ssh目录下所有可用的密钥只使用配置中指定的IdentityFile。如果没有它SSH可能会先尝试其他默认密钥如果碰巧那把密钥也有效可能不会返回Permission denied但你会发现自己push到了错误的账号如果正好无效则可能先拿到一个错误提示耽误排查时间。加上它系统行为更可预期。4.3 多平台仓库的地址写法除了GitHub你可能还会用到其他代码托管平台这里不指名道姓比如GitLab、Bitbucket等。它们的SSH地址格式略有不同但同样可以在config中配置。例如把某gitlab.com主机配置为Host gitlab.com HostName gitlab.com User git IdentityFile ~/.ssh/id_ed25519_gitlab IdentitiesOnly yes克隆仓库时直接使用gitgitlab.com:group/repo.gitSSH自动匹配。如果某个平台要求在SSH连接时使用其他端口可以用Port 2222等参数。这类配置本质是一个套路学会一个平台的配置其他平台也就都会了。5. 常见问题与排查技巧实录5.1 Permission denied (publickey) 的排查路径这是GitHub SSH连接中最常见的错误几乎每个用SSH的人都遇到过。出现这个提示时先别慌按下面的顺序排查基本能定位问题第一确认公钥是否已添加到GitHub。登录GitHub网页进入Settings - SSH and GPG keys看列表里有没有你刚才添加的密钥。这个错误最常见的原因就是公钥根本没添加上或者添加到别的账号了。尤其是公司电脑上可能同时登录了多个GitHub账号浏览器记住的是A账号而你实际想添加的是B账号。第二确认本地ssh-agent是否正在使用正确的密钥。执行ssh-add -l这个命令会列出当前agent加载的密钥指纹。如果列表为空说明没有加载任何密钥执行ssh-add ~/.ssh/id_ed25519加载它。如果列出了多个密钥确认其中包含你预期的那个。第三确认密钥文件权限是否正确。SSH对私钥文件的权限非常敏感。在Linux/macOS上私钥文件权限应该是600即只有所有者可读写.ssh目录权限应该是700。如果权限过于宽松SSH会直接拒绝使用即使密钥内容正确。用以下命令修正chmod 600 ~/.ssh/id_ed25519 chmod 700 ~/.ssh在Windows上如果使用OpenSSH for Windows权限问题相对少见但如果你从别处拷贝过密钥文件也可能遇到“bad permissions”的错误需要右键文件属性设置仅当前用户完全控制。第四确认远程仓库地址是否为SSH格式。在某个仓库目录下执行git remote -v如果输出的是https://github.com/...那SSH密钥当然不会生效因为Git走的是HTTPS协议完全没用上SSH。此时要么改用gitgithub.com:...的地址要么继续使用HTTPS方式并配置token。第五用ssh -vT gitgithub.com查看详细日志。把-vverbose参数加上后SSH会输出大量调试信息包括尝试了哪些密钥、服务器接受或拒绝的状态。重点看日志中是否有“Offering public key”和“Authentications that can continue: publickey”这样的字样。如果看到“no such identity”说明指定的IdentityFile路径不对。这招比瞎猜效率高得多。5.2 密码短语passphrase忘记怎么办如果你生成密钥时设置了passphrase但忘记了这会让很多人崩溃。不过这里有个好消息只要你的私钥文件还在你就可以重新设置passphrase而不需要重新生成密钥。执行ssh-keygen -p -f ~/.ssh/id_ed25519命令会先要求输入旧passphrase。如果旧passphrase你也忘了那很遗憾这个私钥文件将无法再使用因为它一旦加密没有密码就解不开。但公钥并没有加密可以继续留在GitHub上只是没人能使用对应私钥相当于一把作废的锁。此时唯一的办法是生成一把新密钥把新公钥添加到GitHub并更新所有仓库的远程地址。旧公钥如果能确认已不再使用可以从GitHub上删除减少混乱。所以我再次强调passphrase一定要用自己记得住的或者干脆写在密码管理器里。虽然macOS钥匙串和Linux的gnome-keyring等工具可以在某种情况下缓存passphrase但那些依赖系统环境换台机器就又得重新输入。5.3 ssh-agent与密钥代理的坑ssh-agent是一个常驻内存的代理程序用于缓存私钥避免你每次用私钥时都输入passphrase。很多教程会让你执行eval $(ssh-agent -s)再ssh-add然后发现重启终端后又失效了。这里有个常见误解在Linux/Unix中ssh-agent的进程存活期和你启动它的shell相关如果在终端里手动运行关掉终端后agent就没了。要让ssh-agent在登录时自动启动macOS通常在钥匙串中自动管理而Linux发行版一般通过systemd用户服务来启动。对于普通用户来说最简单的方式是不要在每次会话都手动启用agent而是让系统在图形登录时统一启动。如果你用的是macOS执行一次ssh-add --apple-use-keychain ~/.ssh/id_ed25519可以将passphrase存入钥匙串之后无需重复输入。在Windows的OpenSSH中可以使用服务方式运行ssh-agent然后执行ssh-add一次性加载。我踩过的一个坑是在有多个密钥的情况下用ssh-add把两把密钥都加载了然后连接GitHub时SSH会依次尝试所有密钥而GitHub对于每一个已注册的公钥都会返回成功最终匹配到哪一把取决于尝试顺序。当你想把同一个账号下的不同密钥分配给不同仓库时就有点乱。这时就体现出前面讲的config里IdentitiesOnly yes的重要性了它能让密钥选择变得确定。5.4 添加密钥后仍要输入密码检查远程地址还有一种很常见的情况用户明明配好了SSH key但是git pull时依然提示输入用户名和密码。出现这种情况百分之九十九是克隆仓库时使用了HTTPS地址。因为HTTPS地址不会走SSH密钥而是要求输入凭证。你可以用git remote -v检查输出如果是origin https://github.com/username/repo.git (fetch) origin https://github.com/username/repo.git (push)这就是原因。解决办法有两种一是直接修改远程地址为SSH格式git remote set-url origin gitgithub.com:username/repo.git二是继续使用HTTPS但在Git for Windows中启用凭证管理器credential manager让它记住token也能达到类似效果。对于已经把SSH key配好的人我更推荐换成SSH地址一劳永逸。5.5 常见问题速查表为了方便以后排查我把常见情况汇总成一张表症状可能原因解决要点Permission denied (publickey)公钥未添加/密钥未加载/权限错误依次检查GitHub公钥、ssh-add、chmodBad owner or permissions on ~/.ssh/configconfig文件权限过宽chmod 600 ~/.ssh/configEnter passphrase every timessh-agent未缓存配置agent自动启动或使用系统钥匙串Still asks for password远程地址是HTTPSgit remote set-url换成SSH地址ssh: Could not resolve hostname github.comDNS或网络问题检查网络试ping github.comSign_and_send_pubkey: no mutual signature supported服务端不支持你的密钥算法换rsa或ed25519并更新ssh客户端Connection closed by remote host需要走代理或网络被限制此处不展开请自查网络环境6. 安全加固与日常维护心得6.1 定期轮换密钥的方法SSH key不是设置了就一劳永逸的。如果你在公网环境长期使用或者经常在多台设备之间复制文件就有必要定期轮换密钥。所谓轮换就是生成新密钥添加新公钥到GitHub验证新密钥可用后删除旧公钥并删除本地旧私钥文件。这样即使旧私钥曾经泄露也能在轮换后失效降低风险。轮换的具体步骤不复杂生成一把新密钥比如ssh-keygen -t ed25519 -C rollover-2025 -f ~/.ssh/id_ed25519_new。用ssh -T gitgithub.com测试新密钥是否能正常连接。可以通过ssh -i ~/.ssh/id_ed25519_new -T gitgithub.com指定密钥测试。确认正常后把新公钥添加到GitHub。在本地~/.ssh/config中把IdentityFile指向新私钥或者直接重命名覆盖旧的不建议直接覆盖应该先验证。在GitHub后台删除旧公钥。如果旧私钥文件已无用途可以在本地安全删除。Windows上有cipher /w或rmmacOS/Linux用shred或rm注意删除前确保新密钥工作正常。整个轮换过程大概十分钟相比密钥泄露后的损失这点时间很值得。6.2 密钥文件权限的意义前面反复提到权限这里我再多说一点。SSH之所以对~/.ssh目录和私钥文件权限这么敏感是为了防止其他本地用户读取你的私钥。在Linux系统中如果私钥文件是644其他用户可读SSH会警告并拒绝使用它的逻辑是不安全的环境下使用私钥比不用更危险。所以最好在一台新机器上配置好密钥后立即检查权限ls -la ~/.ssh正常输出中id_ed25519应该显示-rw-------id_ed25519.pub可以显示-rw-r--r--公钥本身不敏感所以其他用户可读也没事config和authorized_keys等如果有通常也建议600。如果不对就用chmod调整。Windows NTFS权限则相对复杂但本质上也是限制访问。6.3 我踩过的一个真实教训最后分享一个发生在我身上的真实案例。有段时间我在两台设备间频繁开发图省事就把~/.ssh整个目录用网盘同步了。结果有一天我的一台旧电脑丢了我立刻想到要删除GitHub上的旧公钥而当时网盘同步让两把密钥分散在好几台设备中我甚至搞不清楚哪个公钥对应哪台电脑。后来花了将近一小时挨个测试密钥、删除公钥才把所有权限收回来。从那以后我再也不跨设备同步~/.ssh目录了。每台设备单独生成密钥单独添加到GitHub并严格命名。走完这套流程哪怕某台设备真的丢了我只需在GitHub上删掉对应的公钥即可不影响其他设备。另外一个教训是如果你在~/.ssh/config中使用了HostName github.com要注意区分别名和真实域名。曾经有人把Host直接写成了github.com又把HostName写成了github.com这样反而没问题但如果把别名和HostName弄反会导致连接失败。写配置时最好每个字段都看清楚不要在细节上栽跟头。另外再给一个小技巧在~/.ssh/config中可以为每个Host加入AddKeysToAgent yes这样在首次使用密钥并输入passphrase后会自动加入agent后续不用重复输入。这比手动执行ssh-add更符合日常使用习惯。如果发现某些仓库的克隆总是推送失败优先检查git remote -v里的地址是不是还带别名或写错主机名。SSH key的配置本身并不复杂真正复杂的是各种边界情况。这篇文章从原理到实操再到排错基本覆盖了我在日常开发和团队协作中遇到的大部分场景。希望你看完能少走一些弯路尤其是不要等到被Permission denied折磨半天才开始认真对待密钥管理的细节。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑