在 SSL 握手中,客户端和服务器都生成各自的随机数。然后客户端生成一个预主密钥并使用服务器的公钥对其进行加密。但是,为什么客户端不能只生成预主密钥并将其发送到服务器?为什么我们需要一个客户端和服务器随机?是为了增加主密钥中的熵,还是为了与 DH 等其他密钥交换算法保持一致?
为什么 SSL/TLS 握手有客户端和服务器随机?
主密钥是客户端和服务器随机数的函数。
master_secret = PRF(pre_master_secret,
"master secret",
ClientHello.random + ServerHello.random)
客户端和服务器都需要能够计算主密钥。在客户端生成预主密钥并将其发送到服务器意味着客户端永远无法找到主密钥。
为什么不直接使用 pre-master?
这意味着整个密钥生成例程都是基于客户端生成的值。如果中间人攻击者重放握手,则会发送相同的预主密钥,然后用于连接。让服务器生成一个随机ServerHello.random
值(ClientHello.random
恢复会话时很有用
在 TLS 中,主密钥与 PRF 函数中的服务器和客户端随机字节一起用于计算密钥块。
key_block = PRF(SecurityParameters.master_secret,
"key expansion",
SecurityParameters.server_random +
SecurityParameters.client_random)
然后将密钥块划分为提供用于不同操作的六个密钥:
- 2个加密密钥
- 2 个 MAC 键
- 2 IV(当加密原语需要时)
恢复会话时,使用相同的主密钥生成密钥块。因此,使用客户端和服务器随机字节可确保每次握手中的密钥块都不同。
难道是为了主秘中的熵做贡献……
是的。它确保双方都对主秘密做出贡献。
主密钥是用于派生用于批量加密和身份验证的后续密钥的种子。
... 还是为了与 DH 等其他密钥交换算法保持一致?
不可以。Diffie-Hellman 要求双方通过选择一个随机的秘密值a
(或b
)来做出贡献,然后向对方发送A=G^a
(或B=G^b
)。贡献行为被纳入 Diffie-Hellman。
还有其他密钥协议方案。RSA 是一种密钥传输方案,但它不为服务器提供参与预主密钥的机会。也就是说,RSA 密钥传输没有固有的贡献行为。
在 RSA 密钥传输的情况下,确保双方都贡献主密钥的方法是:
master_secret = Transform(premaster_secret + client_random + server_random)
贡献行为解决的一个实际问题是,想象一个 IoT 设备有一个损坏或无用的随机数生成器。即使客户端缺乏随机性,贡献行为也可确保通道 [大部分] 安全。
它是握手的一部分。它暴露了 premaster secret,但只暴露给服务器和客户端,而不暴露给中间的任何人。除了服务器之外,没有人可以访问客户端生成的秘密,因为除了服务器之外没有人拥有要解密的密钥。
显然我的遮阳篷在这里缺少引用@Raz 以使其成为更好的遮阳篷。(合并到我上面的遮阳篷中)
没有 premaster secret 是用服务器的公钥加密的。客户端和服务器赎金与它(和其他常量)一起使用来生成主密钥。然后用于生成会话密钥。可能想阅读 SSL 如何工作的答案以获取有关握手的更多详细信息