熵与随机性

来自 Alpine Linux

简介

熵被描述为“结果不确定性的数值度量”,通常与混乱或无序相关联,但通常更简单地称为随机性

对于安全的操作系统而言,拥有足够的熵量以用于各种加密和非加密目的非常重要,例如

  • 生成加密密钥
  • 地址空间布局随机化 (ASLR) - 当然,Alpine 默认使用 ;)
  • TCP 端口随机化 (NAT,出站连接)
  • TCP 序列号选择 (也请参阅 此处)
  • 写入随机文件以测试网络功能和吞吐量
  • 在重用、转售或加密之前覆盖硬盘

熵包含在一个中,该池从各种来源获取熵。要查看池中当前的熵量

more /proc/sys/kernel/random/entropy_avail

要查看池可以容纳的最大熵量

more /proc/sys/kernel/random/poolsize

在标准系统上,限制为 4096 位(512 字节)。Alpine 上使用的 gr-sec 补丁将此限制增加到 16384 位(2048 字节)。熵以位为单位从各种来源添加到池中,“每个事件的未知位数相对数量大致为 8/键盘、12/鼠标、3/磁盘、4/中断” 来源 意味着在无头服务器(未连接鼠标和键盘)上,讽刺的是,这通常是需要最多熵的系统,熵生成受到一定限制。

默认情况下,可以通过两种方式访问池中的熵

/dev/random - 在 5.6 之前的内核版本中,这是一个阻塞资源,因此它将使用池中可用的熵。如果需要的熵多于可用的熵,则该进程将等待直到池中有更多熵可用。由于此行为,/dev/random 最适合用于需要少量高质量随机性的地方,例如用于加密密钥。

/dev/urandom - 在所有内核版本中都是非阻塞资源。它使用与 /dev/random 相同的熵池中的种子值,因此,如果池中几乎没有可用的熵,则建议不要使用 /dev/urandom,直到池中有更多熵可用为止。它通过算法运行种子值,因此是一个伪随机数生成器,运行速度比 /dev/random 快得多。/dev/urandom 最适合用于非加密目的,例如覆盖磁盘。

写入 /dev/random 或 /dev/urandom 将使用写入的数据更新熵池,但这不会导致更高的熵计数。这意味着它会影响从两个文件中读取的内容,但不会使从 /dev/random 读取的速度更快。有关更多信息,请参阅 random 手册页

通常建议在大量使用熵的地方提供额外的熵源;下面是一些可能性。向池中添加更多熵源是一个好主意。这会使攻击者的工作更加困难,因为他们必须控制(或至少在源头观察)更多来源,并且添加更多熵源,即使是弱熵源,也只会导致更高的熵。

如果您迫切需要更多熵,并且正在使用没有互联网连接的无头服务器,您可以尝试通过磁盘活动生成一些熵。只是不要期望奇迹发生!这是一个例子

dd if=/dev/zero of=/var/tmp/tempfile bs=1M count=200 && find / -size +1k && ls -R / && rm /var/tmp/tempfile && sync

如果您的服务器是“从 RAM 运行”的设置,因此您没有磁盘来创建搅动但需要更多熵,则强烈建议添加如下所述的备用熵源。

备选/附加熵源

此材料已过时...

本节中的大部分内容自 Kernel 5.6 或大约 Alpine Linux 版本 3.13.0 以来已过时 (讨论)

Haveged

Haveged 基于 CPU 抖动生成熵。当达到 write_wakeup_threshold 时,熵被缓冲并馈送到熵池。如果您希望更改它,请向其写入一个值(位数)

echo "1024" > /proc/sys/kernel/random/write_wakeup_threshold

或通过 haveged 更改它

haveged -w 1024

安装 haveged,然后启动并设置为在启动时自动启动

apk -U add haveged && rc-service haveged start && rc-update add haveged

进一步配置是可能的,但是默认设置应该可以开箱即用。

其他可能性

也可以用 EGD(熵收集守护进程)替换 /dev/random,或者在无法支持 /dev/random 的系统上使用它。但是,在正常情况下,这不是必需的(或推荐的)。

使用 ENT 测试熵

可以测试熵,以查看其统计随机性如何。通常,此类测试仅揭示了部分情况,因为某些数字可能通过统计熵测试,但实际上它们并不是随机的。当然,未能通过统计随机性测试并不是一个好的指标!

创建一个文件夹用于测试,并获取 ENT

mkdir /tmp/test/make
cd /tmp/test/make
wget https://www.fourmilab.ch/random/random.zip
unzip random.zip
make
mv ./ent /tmp/test/
cd /tmp/test

创建一些随机数据。在此示例中,我们从 /dev/urandom 读取

dd if=/dev/urandom of=/tmp/test/urandomfile bs=1 count=16384

对其运行 ENT 测试

./ent /tmp/test/urandomfile

尝试相同的测试,同时将数据视为位流并打印字符出现次数的帐户

./ent -b -c /tmp/test/urandomfile

注意与先前测试的任何差异。

我建议也生成更大的数据流(数十或数百 MB)并对此进行测试。任何重复的数据或模式(例如,由小/差的种子值引起)都将使发现任何弱点和缺乏随机性在大量数据中比在少量数据中容易得多。

我还建议针对已知的非随机文件运行测试,这样您可能会看到某些测试表明此类文件可能具有随机文件的一些特征,同时完全未能通过其他随机性测试。

最后,一旦您完成 ENT 测试,删除工作文件夹是一个好习惯

rm -r /tmp/test/


其他测试

其他测试包括 dieharddieharder

延伸阅读

可视化随机性

linux from scratch

Cloudflare

RFC 4086 - 安全性的随机性要求

calomel.org

Turbid

随机数生成:图解入门

挖掘您的 Ps 和 Qs:网络设备中广泛存在的弱密钥检测,PDF

Linux 随机数生成器分析,PDF 🔓

如何吃掉你的熵并拥有它——受损 RNG 的最佳恢复策略,PDF

伪随机数生成器的安全分析与输入:/dev/random 不健壮,PDF