我尝试了解一下 SSL/TLS 的工作原理,并查看了TLS 握手在 TLS 1.2 和 TLS 1.3 中,以及来自服务器的随机数在那里发挥作用。由于每个 TLS 请求都会产生熵成本,因为需要导出加密密钥,所以我很奇怪为什么服务器不会很快耗尽熵。
首先,我研究了使用 RSA 密钥交换的 TLS 1.2:
根据TLS 1.2 标准第 6 条server random
主秘密的来源是32 字节长。我期望服务器从中获取 32 字节的随机数据/dev/random
。
接下来我研究了带有临时 Diffie-Hellman 密钥交换的 TLS 1.3:
客户端和服务器都会生成自己的一组私有ECDHE 参数。之后,他们进行 Diffie-Hellman 操作并获得共享密钥。此共享密钥用于导出加密的对称密钥和计算 HMAC 以检查消息完整性的密钥。因此,我认为我的加密质量取决于 ECDHE 参数的质量。如果我使用曲线 NIST P-256,那么根据这回答。
综上所述:
在我的 TLS 1.2 示例中,服务器需要生成 256 位熵,在 1.3 示例中则需要生成 128 位熵。我假设所需的位取自。与单次 TLS 握手所需的位数相比,我返回的熵池/dev/random
的最大大小似乎非常小。除非我的计算有误,否则我会在仅 16 个 TLS 1.2 请求的情况下完全耗尽我的熵池(假设熵池没有快速重新填充)。4096
cat /proc/sys/kernel/random/poolsize
问题:
- 如果我的服务器收到大量 TLS 请求,它会耗尽熵吗?或者它是否可以通过某种方式从 TLS 请求中补充熵池,例如利用数据包来回传输的时间或类似方法。
- 假设我想保存一些熵。与 TLS 1.2 相比,具有 256 位 ECC 的 TLS 1.3 的熵成本会更低吗?在上面的例子中,我发现 TLS 1.2 的熵成本为 256 位,而 TLS 1.3 的熵成本仅为 128 位。
- 如果有人发送大量
Client Hello
消息而从未建立过真正的连接,他会以这种方式耗尽我的熵池吗?我认为单个消息不会给我带来太多的熵,但会给服务器带来很大的负担,因为它需要用包含 TLS 1.2 中的 32 字节随机数据Client Hello
进行回答。Server Hello
答案1
我假设必要的位取自 /dev/random。
不。阻塞适用于系统存在熵为零的风险的情况。可能适用于首次启动时生成 ssh 主机密钥。不适用于正常运行期间的 TLS,因为缺少随机位而导致拒绝服务是没有意义的。
使用(非阻塞)加密安全伪随机数生成器。如果您希望使用内核源,请考虑 Linux 上的 getrandom() 或 /dev/urandom,或 Windows 上的 BCryptGenRandom。它们使用与使 TLS 和其他算法工作的相同加密原语;如果它们无法从小种子生成大量看似随机的位,则加密将被破坏。
尽管 TLS 库可能会使用自己的 CSPRNG,并且只使用来自内核源的少量种子。简单地将协议中的随机位相加并不能表明从系统熵池中读取了多少。
关于操作系统,请务必说明您使用的发行版。Linux 积极阻止 /dev/random 是不典型的。大多数 BSD 将其视为与 /dev/urandom 相同的方式。
简短回答:使用 /dev/urandom。Linux 上需要阻止 /dev/random 的可怕之处是迷信。对数十 TB 随机比特的分析表明它们是相同的。