SSH 密钥详解

SSH 密钥认证是一种无需密码登录服务器的方式:你的电脑不再输入一个服务器可以核对的秘密,而是对服务器发来的挑战进行签名,服务器再用它已存档的公钥验证签名。私钥从不经过网络,因此无物可截获、无物可钓取、无物可猜测。本文讲解密钥对的两半如何工作、2026 年该选择哪种密钥类型、指纹如何在首次连接时挡住中间人、如何保持 authorized_keys 与 known_hosts 整洁,以及密钥泄露时具体该做什么。要在浏览器中生成、检查或转换密钥,请使用SSH 密钥套件;要检查你仍在用的密码,请使用密码泄露检查。

什么是 SSH 密钥认证

每一次登录都是服务器提出的一个问题——你真的是你声称的那个人吗?——而密码的回答方式是把秘密本身交出去。这正是整个安排的弱点:秘密会流动、会被窃听、会被重放、会被一次次猜测,直到被攻破。SSH 密钥认证改变了回答方式。你的电脑不再发送秘密,而是用一个从不离开本机的私钥对服务器发来的随机挑战签名,服务器再用 authorized_keys 文件中存储的公钥核对签名。因为挑战是随机的,证明每次都是全新的;秘密从不出现在网络上,窃听者学不到任何可以重用的东西;而且根本没有密码可猜,因为整个过程完全不涉及密码。

这个想法比现代互联网还要古老——公钥密码学可以追溯到 20 世纪 70 年代——但 SSH 让它成为连接服务器的日常方式,此后协议一直沿用至今。当你运行 ssh user@server 时,客户端与服务器先建立会话,服务器针对你的账户发出挑战,你的 SSH 代理用私钥签名——通常是你先用口令解锁密钥之后。如果签名验证通过,你就进去了。整个交换不依赖服务器也知道的共享秘密,这就是为什么服务器被攻破也不会暴露你的凭据:服务器手里只有公钥,而公钥对登录毫无用处。这种不对称——服务器能验证却不能冒充——就是密钥的全部安全论据,也是为什么失去私钥一半的控制是唯一真正要命的失败。

公钥与私钥

密钥对的两半遵循相反的规则,而大多数 SSH 错误都来自把它们当成一回事。公钥就是用来到处复制的:粘贴进你使用的每一台服务器的 authorized_keys、Git 托管账户、任何接受 SSH 密钥的服务。它可以发表在公开仓库里、印在幻灯片上、发邮件给管理员,因为它能让别人做的只有验证签名。知道你的公钥不会给攻击者任何登录的手段,就像知道你的门牌号并不会给别人你家大门的钥匙一样。公钥这一半是锁,而不是钥匙,而锁本来就是给人看的。

私钥就是钥匙本身,它的规则恰恰相反:它从不离开你的电脑,只有你能读取,绝不能粘贴进聊天、工单、邮件、论坛帖子或共享文档——哪怕是问它是否安全。持有它的人就能以你的身份登录每一台信任对应公钥的服务器,中间没有任何密码提示,也没有任何第二因素——除非你自己配置过。在磁盘上它住在 ~/.ssh 里,靠文件权限保护——chmod 600,只有所有者可读写——理想情况下还要有口令保护,口令会加密文件,让被盗的副本在没有解锁口令的情况下依然无用。口令不是密钥的一部分;它是装着钥匙的盒子上的挂锁。盒子丢了,挂锁就是小偷与你的服务器之间唯一的屏障,这就是为什么没有口令的私钥绝不应该离开一台你完全掌控的机器。

Ed25519 与 ECDSA、RSA:2026 年该选哪一个

2026 年的默认答案是 Ed25519,这也是本站生成的默认类型。Ed25519 是 256 位的椭圆曲线密钥:不到一秒就能生成,签名很快,公钥只有短短一行。自 2014 年起 OpenSSH 就支持它,所有当前的服务器与客户端也都支持,它的安全性建立在一条公开设计、没有可疑常数的曲线上。除非你的环境迫使你另作选择,否则新密钥没有实际理由选别的。如果你只从本文带走一条建议,就是这一条:生成 Ed25519,设置口令,然后继续做事。

其他类型是为例外情况准备的。当政策要求 NIST 曲线时——某些受监管环境与较旧的硬件令牌有此规定——ECDSA 的 NIST P-256 或 P-384 曲线是正确选择;如果某个浏览器或设备无法生成 Ed25519,它也是可靠的替代。RSA 仍然是通用兜底:RSA 2048 是值得使用的下限,RSA 3072 或 4096 适用于对方完全无法使用椭圆曲线的情况,如今这主要指非常旧的系统和少数嵌入式设备。低于 RSA 2048 的任何密钥——RSA 1024、DSA、ssh-dss——都属于旧遗产,应当退役:SSH 密钥套件正是因此把它们标记为弱密钥。不过密钥长度不是全部:复制到你已不再拥有的笔记本上的 4096 位 RSA 密钥,比保管得当的 256 位 Ed25519 密钥更糟糕,因为 SSH 密钥的失败模式几乎从来不是数学,而是文件。

指纹与首次连接

第一次连接服务器时,SSH 会显示一串看起来随机的字符,并问你是否信任它:256 SHA256:M8zvXkwyrGfPUmaHSSdA1aFQkH8AVSRycOxaZHru7dQ。这串字符是服务器主机密钥的指纹——服务器公钥的哈希——也是你与中间人之间唯一的屏障。如果指纹与管理员公布的、或你通过其他渠道核实过的一致,那么回答你的机器就确实是你想连接的服务器。如果不一致,就停下:可能有人在拦截连接,也可能服务器重建后换了新密钥,无论哪种情况,安全的做法都是先核实再输入 yes。这个提示是 SSH 在做它最重要的工作,而出问题的人正是那些训练自己不看提示就输入 yes 的人。

你可以在连接之前就用 ssh-keygen -lf 核实指纹,它为每个密钥打印一行:位数、指纹、注释和方括号中的密钥类型,例如 256 SHA256:… [email protected] (ED25519)。SSH 密钥套件打印指纹的格式与它完全一致,因此你在浏览器里看到的值可以与服务器显示的值逐字比对。一旦你接受了某个主机密钥,SSH 会把它保存在 ~/.ssh/known_hosts 中,如果它将来发生变化,就会大声警告你——甚至拒绝连接。这个警告不是用某个参数绕过去的麻烦;它是正在响起的警报。唯一常规的例外是服务器确实重建过,这时管理员应当事先公布新指纹,而你应当在重新连接之前用 ssh-keygen -R hostname 删除旧条目。

authorized_keys 的日常维护与 known_hosts

服务器 authorized_keys 文件中的每一行都是一扇门,而这些门会在需要它的人离开很久之后依然开着。外包人员的笔记本、持续集成任务、在已被擦除的机器上生成的密钥、两年前换了团队的同事——每一行都仍然有效,每一行都是你不再盯着的凭据。审计很简单,每隔几个月做一次就值得:复制文件,粘贴进 SSH 密钥套件的「检查」选项卡,看看返回的结果。重复项——同一个公钥出现两次——意味着有人没有检查就又粘贴了一次,应当合并为一行。弱条目——低于 2048 的 RSA、DSA、ssh-dss——应当删除并替换。而任何注释中提到的人、机器或用途你已经认不出来的行,都应当当作一扇要关上的门,直到它的主人来认领。

known_hosts 也值得从另一面得到同样的关注。它记录着你连接过的每一台服务器的主机密钥,SSH 会对照它检查每一次新的连接。有些条目是经过哈希处理的——|1| 后面跟着 base64——这会隐藏主机名,是为可能丢失或被检查的笔记本准备的隐私功能;SSH 密钥套件会把这些条目报告为已哈希,而不是假装它们可读,因为已哈希的条目无法对照公布的指纹核实,只能当作已经被接受来信任。这个文件本身也是证据:满是早已不用的服务器的 known_hosts,就是你的凭据去过哪里的地图,而清理它不花任何代价。这两个文件合在一起,就是你的 SSH 信任在两个方向上的完整记录——谁可以以你的身份登录,以及你信任哪些机器就是它们自己——而如果没人去看,它们都会悄悄腐烂。

密钥泄露时该怎么办——以及口令说明

泄露的密钥不是先调查、后行动的谜题;它是要换掉的密钥,操作顺序很短。生成一对新密钥。从每一台服务器和每一个服务的 authorized_keys 中删除旧公钥——你的服务器、Git 托管、部署流水线,凡是安装过这把密钥的地方。然后检查旧密钥能触及什么,看看有没有异常:你没有添加过的 authorized_keys 新行、你没有工作的时间段里的登录、不熟悉的进程。如果发现任何异常,就把它当作一次入侵来对待,而不是虚惊一场,再从那里展开调查。千万不要做的事,是从自己的笔记本上删除旧私钥就以为大功告成:删除你自己的副本对已经泄露的副本毫无作用,而仍然躺在 authorized_keys 里的公钥依然是一扇能正常打开的门。

口令不会改变这份清单,但它会改变你执行清单的紧迫程度。泄露为文件的受口令保护的密钥仍然是个问题——攻击者可以离线、以机器速度猜测口令——但一个强口令能为你争取到在猜测成功之前完成轮换的时间。未加密的密钥则完全争取不到时间,这就是为什么本站对生成器产出的东西直言不讳:第 1 版生成的是未加密密钥,没有口令选项,因为 OpenSSH 加密私钥的 bcrypt KDF 属于第 2 版的范围。如果你在这里生成密钥,请用 chmod 600 保护文件,并在自己的电脑上用 ssh-keygen -p 添加口令——只需要十秒钟,原地转换文件,而且是整篇文章中价值最高的习惯。生成密钥,设置口令,只安装公开的那一半,每年审计两次文件,信任之前核实每一个指纹:这就是全部的纪律,写在一张索引卡上都绰绰有余。

来源与延伸阅读

常见问题

2026 年我该用哪种 SSH 密钥类型?

几乎所有情况都用 Ed25519:256 位,速度快,体积小,所有当前服务器与客户端都支持。只有当政策要求 NIST 曲线时才用 ECDSA P-256,只有当对方无法使用椭圆曲线时才用 RSA 3072 或 4096。低于 RSA 2048 的一律退役。

我怎么知道自己连接的是正确的服务器?

首次连接时,把 SSH 显示的主机密钥指纹与管理员公布的指纹比对,用 ssh-keygen -lf 或 SSH 密钥套件——两者打印指纹的格式相同。如果一致就接受;SSH 会把它保存在 known_hosts 中,一旦变化就会警告你。如果不一致,先停下核实,不要急着输入 yes。

我的私钥泄露了,我先做什么?

生成一对新密钥,然后从每一台服务器与服务的 authorized_keys 中删除旧公钥——Git 托管与部署流水线也包括在内。只删除自己手里的私钥副本是不够的,因为泄露出去的副本在公钥被删除之前仍然有效。然后检查旧密钥能触及的地方有没有被使用的迹象。