澄清 SSH Diffie-Hellman 密钥交换后发生的情况

澄清 SSH Diffie-Hellman 密钥交换后发生的情况

我观看和阅读了大量有关 SSH 如何工作的内容,以及 diffie-hellman 背后的数学知识等。

问题是,几乎每个 YouTube 视频或文章都会解释密钥交换的完成方式,这意味着客户端和服务器都拥有密钥,并且客户端会验证公钥。我只是不明白之后会发生什么。

这就是我所了解的 SSH 的工作原理(这是从另一篇文章中复制而来的服务器库

  1. SSHv2 客户端:密钥交换初始化几个参数协商,如压缩和一些加密算法。

  2. SSHv2 服务器:密钥交换初始化

  3. SSHv2 客户端:Diffie-Hellman 密钥交换初始化有关数学群的 DH 参数的协商。

  4. SSHv2 服务器:Diffie-Hellman 密钥交换回复

  5. SSHv2 客户端:Diffie-Hellman GEX Init 首次实际交换 DH。

  6. SSHv2 服务器:Diffie-Hellman GEX 回复 收到此数据包后,双方都知道密钥 (gab) 并使用它建立一个伪安全通道(可以防止随意窃听,但不能防止中间人攻击)。

好吧,这就是我感到模糊的地方。客户端和服务器都拥有相同的密钥,但之后会发生什么?当我查看 .ssh 文件夹时,我看到我有私钥和公钥,但这些密钥甚至不需要用于这些交换,除了客户端和服务器“生成的”临时 Diffie-Hellman 公钥和私钥,但这些密钥只是临时的,在 ssh 连接(甚至 DH 交换)结束后就毫无用处了。

我知道服务器还生成了私钥和公钥对(除了临时密钥对),其中公钥在 SSH_MSG_KEX_ECDH_REPLY 中发送给客户端(以及其他内容)。因此,如果是第一次连接到 SSH 服务器(或者通常如果我从未存储过它),我可以选择在弹出框中单击“接受”以存储该公钥。因此,客户端和服务器现在拥有相同的公钥(客户端存储了它),服务器仍然拥有私钥。正在发送的消息使用对称共享密钥进行加密和解密。连接结束,这些密钥将被删除。

如果我再次连接到 ssh 服务器,diffie-hellman 交换是否会以完全相同的方式发生,但现在没有弹出框?

是否只有服务器生成密钥对(不涉及 diffie-hellman 的临时密钥),如果不是,那么它在客户端用于什么?

当我是客户端并且文件被密码锁定时,为什么我的 .ssh 文件夹中会有一个私钥?

服务器生成的密钥对(非临时的)是 RSA 密钥对吗?

客户端的私钥是如何使用的、用于什么用途的,客户端是自己生成私钥的吗,他是否也有公钥?

我希望有人能帮我解释一下一些概念,我想我只是把 RSA 排除在外了,客户端突然拥有私钥真是太奇怪了。如果有人能推荐一些资源让我更深入地了解这个问题,尤其是 Diffie-Hellman 和 RSA 如何结合在一起以及关于临时私钥和公钥的内容,那也真的很有用。

我非常感谢任何答复,祝您有美好的一天!

答案1

总结:SSH 使用多种算法来提供多种安全服务

正如总结的那样rfc4251 第 1 节

   Secure Shell (SSH) is a protocol for secure remote login and other
   secure network services over an insecure network.  It consists of
   three major components:

   o  The Transport Layer Protocol [SSH-TRANS] provides server
      authentication, confidentiality, and integrity.  It may optionally
      also provide compression.  The transport layer will typically be
      run over a TCP/IP connection, but might also be used on top of any
      other reliable data stream.

   o  The User Authentication Protocol [SSH-USERAUTH] authenticates the
      client-side user to the server.  It runs over the transport layer
      protocol.

   o  The Connection Protocol [SSH-CONNECT] multiplexes the encrypted
      tunnel into several logical channels.  It runs over the user
      authentication protocol.

具体来说

  • 数据的机密性和完整性——包括(完美)前向保密,这个术语在 2005 年编写 4251 时并不为人所知且被广泛使用——由短暂的 Diffie-Hellman 密钥协议与对称加密和 MAC 算法相结合提供。最初加密和 MAC 是分开的,但最近的做法是将它们组合成“认证加密”算法,例如 AES-GCM 和 ChaCha20/Poly1305,这些算法通常更具体地称为带附加数据的认证加密 (AEAD)。但请注意,AE/AEAD 的“认证”与下面的认证不同。

  • 服务器(在协议中称为主机)身份验证由公钥签名算法提供;最初是 RSA 或 DSA,但多年来添加了 ECDSA(限制为 P-256、P-384、P-521)和 Ed25519,并且在过去几年中,OpenSSH(使用最广泛的实现,因此对其他人的做法有影响)禁用了 DSA 并限制了 RSA;您可以找到许多关于“为什么我的 SSH 或者我使用的基于 SSH 的东西停止工作了”这一主题的几个 Stacks 问题,答案竟然是“你正在使用 DSA(又名 ssh-dss)或旧形式的 RSA(类似 ssh-rsa)并且 OpenSSH 发生了变化”。

    主机身份验证实际上是作为密钥交换协议的一部分完成的,尽管它严格来说不是密钥交换算法的一部分,并且(因此)在 RFC4253 中进行了描述。4251 将其规定为“应该”,但在实践中它已成为“必须”;今天的实现假定它,如果没有它,可能无法工作。您链接的 serverfault 答案没有提到它,但最后一个 KEX 回复包含主机签名;这是使用 DHGEX 时的 DHGEX_REPLY(第 6 个数据包),如您链接并指定的 serverfault A 中所示RFC4419或 DH_REPLY (第 4 个数据包),用于定义在RFC4253 第 8 节

    为了获得最佳安全性,应在客户端连接到服务器之前手动或至少在带外配置主机(服务器)密钥。但是,这会带来不便,甚至需要工作,因此实际上没有人会这样做,除非是十万分之一的完全安全狂。好吧,也许有两个。实际上,几乎每个人都使用“首次使用即信任” (TOFU):当客户端首次连接到服务器/主机时,它会显示主机密钥的“指纹”(哈希值)并允许用户“验证”它;实际上,用户总是点击(或其他)“只需将我连接到已删除的主机,无论它是谁,我都不在乎它是否会窃取、破坏或销毁我的数据”。然后,客户端会记住与主机身份相关联的密钥,并且在任何后续连接中,如果从应该是同一台主机的主机接收到不同的密钥,则会出现错误 - 这可能表示(延迟)攻击,但也会发生并引起惊愕,如果您使用的云或虚拟机(频繁)重新部署、扩展和/或移动,或者您更改主机上的软件或任何数量的合法事物。

  • 客户端(称为用户)身份验证可以通过多种方式完成(有时不止一种方式,又称多因素身份验证),但一种非常常见的方式是使用与服务器身份验证相同类型的公钥签名。

    用户身份验证是在密钥交换完成后作为单独的步骤完成的 - 因此将在 wireshark 跟踪中显示为无法识别的加密数据 - 并且 publickey 用户身份验证在RFC4252 第 7 节OpenSSH 和其他实现(据我所知)都要求在主机上配置用户密钥才能使用;这通常是通过第一次使用(手动输入的)密码进行身份验证(即登录)并使用该连接来配置用于后续连接的公钥来完成的。(流行的脚本ssh-copy-id会自动执行此过程,但其底层执行的是我所描述的操作。)其他方法也是可行的,例如 ansible 或 kubernetes 或在部署主机时“注入”适当的密钥。

如果我再次连接到 ssh 服务器,diffie-hellman 交换是否会以完全相同的方式发生,但现在没有弹出框?

不完全是。将会有一个新的 DH 交换使用相同的协议但密钥不同(这就是“短暂”的意思)。主机通常会符号使用相同的主机密钥,您的客户端将接受它而不会出现警告(根据软件的不同,可能会弹出警告,也可能不会弹出警告)。但是,如果主机密钥已更改(如上所述),您将至少收到警告,并且可能会收到错误。

是否只有服务器生成密钥对(不涉及 diffie-hellman 的临时密钥),如果不是,那么它在客户端用于什么?

服务器将至少有一个身份验证(长期)密钥对;通常它会为每种支持的算法提供一个密钥对,目前是 3 或 4 个。但它只会发送您的客户端是客户端首选项列表中最高的那个,除非您更改软件,否则它通常会保持不变。半例外是ssh-keyscanOpenSSH 提供的程序;它(除了旧版本)会更改首选项列表以引出所有或几乎所有主机密钥。

当我是客户端并且文件被密码锁定时,为什么我的 .ssh 文件夹中会有一个私钥?

您显然正在使用 OpenSSH,或基于 OpenSSH 构建的程序,或旨在与 OpenSSH 兼容的程序。OpenSSH 或兼容客户端使用.ssh主目录中的子目录来包含几项内容,包括您用于用户/客户端公钥身份验证的任何密钥。OpenSSH 本身不会自动生成这些密钥,您必须运行ssh-keygen,但其他软件可能认为为您创建密钥是“有帮助的”。但是,它不应该在不让您选择或至少知道密码的情况下这样做。如果您知道或找到密码,该密钥的公钥已经或者已经配置在您要连接的主机上,您可以使用它对该主机进行客户端/用户身份验证。

服务器生成的密钥对(非临时的)是 RSA 密钥对吗?

如上所述,它可以是任何受支持的算法,至少包括 RSA、DSA(但在最近的 OpenSSH 中默认不是)、ECDSA、Ed25519。

客户端的私钥是如何使用的、用于什么用途的,客户端是自己生成私钥的吗,他是否也有公钥?

客户端/用户密钥用于上述客户端/用户身份验证。最佳安全实践是用户应生成自己的密钥,其他人永远都看不到它们,但您需要能够正确地按照说明进行操作,通常需要 3 或 4 个步骤,因此拥有大量人员的组织如果没有数小时的指导就无法做到这一点,他们可能会认为集中化更便宜。类似地,某些软件可能会认为安全性的“技术细节”对您来说太令人困惑,因此会自行完成这项工作,如果程序员决定做的事情不是您想要的,那就太可惜了。

OpenSSH 使用的私钥文件始终包含公钥,尽管公钥有时复制将其保存为单独的文件(id_rsa.pub例如,id_rsa以便于访问);自从 OpenSSH 7.8(2018-08)切换到默认的“新格式”私钥文件以来,这很少是必要的。如果您确实需要或想要丢失的公钥文件,您可以使用 重新生成它ssh-keygen -y;请参阅手册页。

相关内容