我正在阅读一本由知名出版商出版的《Linux 管理》书籍:
当客户端发起 SSH 握手时,服务器会请求客户端的公钥,并根据允许的公钥进行验证。如果匹配,则 SSH 握手成功,服务器与客户端共享其公钥,并建立 SSH 会话。 进一步的客户端-服务器通信遵循标准的加密/解密工作流程。客户端使用其私钥加密数据,而服务器使用客户端的公钥解密数据。在响应客户端时,服务器使用自己的私钥加密数据,客户端使用服务器的公钥解密数据。
这完全是错误的,还是我遗漏了什么?我指出,会话通信是使用非对称加密实现的,使用两个密钥对,一个用于客户端->服务器方向,另一个用于服务器->客户端。
所有其他互联网参考资料都指出,服务器和客户端建立对称会话密钥,然后在会话期间使用对称加密......
答案1
这本书所引用的几乎所有内容都是错误的。
(如果客户端使用密码验证并且没有自己的密钥对,那么所描述的过程将如何工作?)
本书可能受到(现已完全过时的)SSHv1 协议的影响,该协议中的服务器确实使用其非对称 RSA 密钥对来加密/解密一些(在 SSHv1 中它始终是 RSA),但即便如此,它也仅用于身份验证,而不是批量数据加密(仍然使用对称算法,例如 3DES)。
但是在 SSHv2 中不再这样做,它(就像 TLS 一样)已经完全转向基于 DH 的密钥和基于签名的身份验证。
当客户端发起 SSH 握手时,服务器会请求客户端的公钥,并根据允许的公钥进行验证。如果匹配,则 SSH 握手成功,服务器与客户端共享其公钥,并建立 SSH 会话。
因此是落后的和不完整的。服务器身份验证发生前客户端身份验证,原因多种多样,但其中一个原因是客户端不一定使用密钥对进行身份验证——例如,它们可能使用普通密码,因此你需要对服务器进行身份验证前向其发送您的密码。
此外,这两个密钥根本不用于加密。这两个密钥仅用于符号事情;在书中忽略提及的“密钥交换”过程(通常是 DH/ECDH 的一种形式)期间,实际的加密密钥是为每个会话生成的新密钥。
DH“密钥交换”是首先发生的事情并生成对称密钥(服务器在此阶段提供其公钥),然后建立对称加密,然后客户端向服务器进行身份验证 – 可能使用密钥对,但也可能不使用。
进一步的客户端-服务器通信遵循标准的加密/解密工作流程。客户端使用其私钥加密数据,而服务器使用客户端的公钥解密数据。在响应客户端时,服务器使用自己的私钥加密数据,客户端使用服务器的公钥解密数据。
这是错误的。尽管 SSH 在两个方向(客户端到服务器和服务器到客户端)都使用不同的密钥,但它们仍然使用对称密码(如 AES),因此这里不涉及“公钥”——客户端使用相同的对称密钥来加密数据,服务器则使用相同的对称密钥来解密数据。
实际上,所有协议都仅使用对称加密进行批量数据传输,SSH 和 TLS 都以这种方式工作。
您可以查看ssh -v
或plink -v somehost
查看正在协商的密码;它将显示在两个方向上正在使用的 AES 或其他类似的对称密码,并且这种密码没有公钥。