我想在我的 MacBook 上生成一堆用于长期存储的密钥。
有什么好方法:
- 测量熵的数量并确保在生成每个密钥之前它是足够的,并且
- 如果需要增加熵?
类似于 Linux 的东西/dev/urandom
和/dev/random
……
我想在我的 MacBook 上生成一堆用于长期存储的密钥。
有什么好方法:
类似于 Linux 的东西/dev/urandom
和/dev/random
……
首先,请注意在 OS X 上,/dev/random
并/dev/urandom
具有相同的行为;/dev/urandom
提供作为与 Linux 的兼容性措施。因此,虽然您会在网上看到很多建议使用/dev/random
,因为如果可用的熵不足,它会阻塞,但在 OS X 下并非如此。
/dev/random
使用Yarrow CSPRNG(由 Schneier、Kelsey 和 Ferguson 开发)。根据random(4)手册页,CSPRNG 定期由“SecurityServer”守护进程提供熵。与 Linux 不同,从中读取值/dev/urandom
不会耗尽熵“池”,然后返回到 CSPRNG。相反,Yarrow 具有长期状态,并定期从两个不同池(快速池和慢池)中收集的熵中重新播种,并/dev/random
直接从 CSPRNG 中读取数据。
尽管如此, random(4) 联机帮助页指出:
如果 SecurityServer 系统守护程序由于任何原因失败,输出质量将随着时间的推移而受到影响,而随机设备本身没有任何明确的指示。
这让人感到非常不安全。此外,OS X 似乎没有公开 Linux 风格的/proc/sys/kernel/random/entropy_avail
界面,因此无法测量 SecurityServer 守护进程已经为 Yarrow 提供了多少熵,似乎也没有办法获得熵池的当前大小.
话虽如此,如果您担心当前可用的熵量,您可以直接写入以/dev/random
向 CSPRNG 提供更多数据,例如echo 'hello' >/dev/random
(当然,希望您在这里使用实际好的随机数据)。不过说实话,默认行为可能就足够了。但是,如果您感到偏执,请使用 Linux live 发行版,可能附加硬件 RNG,并从/dev/random
.
事实上,MacOS X 手册页和Linux 手册页都患有相同的疾病,那就是他们谈论熵,就好像它是某种汽油,在使用时会被消耗掉。
实际上,这是行不通的。熵是衡量一个系统可能是什么的量度。在 Linux 和 Mac OS X 中,都有一个内部“熵池”,即从硬件事件中填充的一组比特。这些事件应该是攻击者不可预测或可测量的,因此池在任何时候都可能积累了“ n位熵”,这意味着如果攻击者想猜测池的内容,那么他需要平均,2 n-1次尝试。然后使用加密安全的 PRNG将该池扩展为任意长的伪随机字节流。
假设您有一个包含n位熵的池。现在使用 PRNG 生成 1 GB 的数据,并以该池为种子。生成后的池熵是多少?还是n位!实际上,池仍然可能有2 n 个可能的内容,并且试图猜测池内容的攻击者获得了千兆字节的伪随机字节并没有任何帮助。为什么呢 ?因为密码安全的 PRNG 是密码安全的。这正是“加密安全”的含义:输出“看起来是随机的”并且无法以比猜测内部状态更高的概率进行预测,即使之前的输出已经被大量观察到。
然而,出于某种原因,Mac OS X 和 Linux 手册页的作者显然都相信随机性会在使用时以某种方式降低。如果 PRNG 很弱并且泄露了有关池的信息,这将是某种意义上的;但无论如何你都不想使用这样的 PRNG。换句话说,当有人写“/dev/(u)random
一段时间后输出质量下降”时,他是在含蓄地告诉您“PRNG 已损坏并泄漏数据”。
幸运的是,即使手册页作者对熵的概念有些模糊,但实现更好。为了确保安全性,需要的是熵池在某个时候达到适当的熵水平(128 位就足够了);从那时起直到机器下一次重新启动,/dev/urandom
将产生非常适合所有实际用途的高质量随机性,包括,是的,生成长期 PGP 或 SSH 密钥。棘手的一点是要确保在最佳熵的那一刻之前没有提取随机性。
当机器启动时,池是空的。然后连续收集硬件事件。FreeBSD是一个类 Unix 操作系统,它在这方面做的一切都是正确的:
/dev/random
将阻塞并拒绝产生伪 alea。它将等到收集到一些体面的熵。/dev/random
就会愉快地产生千兆字节的伪随机性,而不会阻塞。/dev/urandom
是 上的别名/dev/random
。这种行为很好:不要输出不好的随机性,但是当可以安全地完成时,不要拒绝输出大量的随机性。Mac OS X 从 FreeBSD 导入了很多内核代码,所以我们可以想象 Mac OS X 在这方面表现得像 FreeBSD(这应该通过检查源代码来检查)。
Linux 没有那么好,但也没有那么糟糕。在 Linux 上:
/dev/random
使用熵估计器,并且(通过有缺陷的推理,如上所述)在输出随机字节时降低此估计。/dev/random
当估计值低于给定阈值时阻塞。/dev/urandom
从不阻塞。/dev/urandom
正确的事情也是如此,除了在启动之后:/dev/urandom
即使熵池仍然太浅(即攻击者太“可预测”),也可以接受产生伪随机字节。为了避免这个问题,Linux 发行版应用了一个漂亮的修复:它们为下次启动保存一个随机种子。当机器启动时,它会将该文件注入池中,然后生成一个新文件,以便在下次启动时注入。当首次安装操作系统时,这种机制将“低熵”窗口减少到第一次启动。之后,/dev/urandom
正确播种,将产生高质量的随机性,并且永远不会阻塞。
总结一下,就是用/dev/urandom
。没关系,尽管一些手册页作者有千禧年预言;即使在理论上存在“低熵”窗口的 Linux 上,分发供应商也会应用纠正机制。
(但请注意,并非所有 Linux衍生产品都可能是固定的,尤其是嵌入式系统。仅当存在可写文件系统时,为下次启动生成熵种子文件才有效;嵌入式系统不一定如此。)